Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32e59650 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: Add support for AD4 manual strength"

parents 0f135213 4222a290
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -48,6 +48,7 @@ enum ad_property {
	AD_SUSPEND,
	AD_ASSERTIVE,
	AD_BACKLIGHT,
	AD_STRENGTH,
	AD_IPC_SUSPEND,
	AD_IPC_RESUME,
	AD_IPC_RESET,
+17 −0
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ enum {
	SDE_CP_CRTC_DSPP_AD_INPUT,
	SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS,
	SDE_CP_CRTC_DSPP_AD_BACKLIGHT,
	SDE_CP_CRTC_DSPP_AD_STRENGTH,
	SDE_CP_CRTC_DSPP_MAX,
	/* DSPP features end */

@@ -803,6 +804,15 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
			ad_cfg.hw_cfg = &hw_cfg;
			hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg);
			break;
		case SDE_CP_CRTC_DSPP_AD_STRENGTH:
			if (!hw_dspp || !hw_dspp->ops.setup_ad) {
				ret = -EINVAL;
				continue;
			}
			ad_cfg.prop = AD_STRENGTH;
			ad_cfg.hw_cfg = &hw_cfg;
			hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg);
			break;
		default:
			ret = -EINVAL;
			break;
@@ -1359,6 +1369,9 @@ static void dspp_ad_install_property(struct drm_crtc *crtc)
		sde_cp_crtc_install_range_property(crtc,
			"SDE_DSPP_AD_V4_ASSERTIVENESS",
			SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, 0, (BIT(8) - 1), 0);
		sde_cp_crtc_install_range_property(crtc,
			"SDE_DSPP_AD_V4_STRENGTH",
			SDE_CP_CRTC_DSPP_AD_STRENGTH, 0, (BIT(10) - 1), 0);
		sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_INPUT",
			SDE_CP_CRTC_DSPP_AD_INPUT, 0, U16_MAX, 0);
		sde_cp_crtc_install_range_property(crtc,
@@ -1502,6 +1515,7 @@ static void sde_cp_update_list(struct sde_cp_node *prop_node,
	case SDE_CP_CRTC_DSPP_AD_INPUT:
	case SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS:
	case SDE_CP_CRTC_DSPP_AD_BACKLIGHT:
	case SDE_CP_CRTC_DSPP_AD_STRENGTH:
		if (dirty_list)
			list_add_tail(&prop_node->dirty_list, &crtc->ad_dirty);
		else
@@ -1550,6 +1564,9 @@ static int sde_cp_ad_validate_prop(struct sde_cp_node *prop_node,
		case SDE_CP_CRTC_DSPP_AD_BACKLIGHT:
			ad_prop = AD_BACKLIGHT;
			break;
		case SDE_CP_CRTC_DSPP_AD_STRENGTH:
			ad_prop = AD_STRENGTH;
			break;
		default:
			/* Not an AD property */
			return 0;
+119 −19
Original line number Diff line number Diff line
@@ -16,7 +16,12 @@
#include "sde_hw_lm.h"
#include "sde_ad4.h"

#define AD_STATE_READY(x) ((x) == (ad4_init | ad4_cfg | ad4_mode | ad4_input))
#define AD_STATE_READY(x) \
	(((x) & ad4_init) && \
	((x) & ad4_cfg) && \
	((x) & ad4_mode) && \
	(((x) & ad4_input) | ((x) & ad4_strength)))

#define MERGE_WIDTH_RIGHT 6
#define MERGE_WIDTH_LEFT 5
#define AD_IPC_FRAME_COUNT 2
@@ -26,6 +31,7 @@ enum ad4_ops_bitmask {
	ad4_cfg = BIT(AD_CFG),
	ad4_mode = BIT(AD_MODE),
	ad4_input = BIT(AD_INPUT),
	ad4_strength = BIT(AD_STRENGTH),
	ad4_ops_max = BIT(31),
};

@@ -37,6 +43,8 @@ enum ad4_state {
	ad4_state_ipcs,
	/* idle power collapse resume state */
	ad4_state_ipcr,
	/* manual mode state */
	ad4_state_manual,
	ad4_state_max,
};

@@ -48,6 +56,8 @@ static int ad4_params_check(struct sde_hw_dspp *dspp,

static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode);
static int ad4_mode_setup_common(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
@@ -81,6 +91,10 @@ static int ad4_backlight_setup(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
static int ad4_backlight_setup_ipcr(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
static int ad4_strength_setup(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);

static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg);
@@ -103,6 +117,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
	[ad4_state_idle][AD_SUSPEND] = ad4_suspend_setup,
	[ad4_state_idle][AD_ASSERTIVE] = ad4_assertive_setup,
	[ad4_state_idle][AD_BACKLIGHT] = ad4_backlight_setup,
	[ad4_state_idle][AD_STRENGTH] = ad4_strength_setup_idle,
	[ad4_state_idle][AD_IPC_SUSPEND] = ad4_no_op_setup,
	[ad4_state_idle][AD_IPC_RESUME] = ad4_no_op_setup,
	[ad4_state_idle][AD_IPC_RESET] = ad4_no_op_setup,
@@ -115,6 +130,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
	[ad4_state_startup][AD_ASSERTIVE] = ad4_assertive_setup,
	[ad4_state_startup][AD_BACKLIGHT] = ad4_backlight_setup,
	[ad4_state_startup][AD_IPC_SUSPEND] = ad4_no_op_setup,
	[ad4_state_startup][AD_STRENGTH] = ad4_no_op_setup,
	[ad4_state_startup][AD_IPC_RESUME] = ad4_no_op_setup,
	[ad4_state_startup][AD_IPC_RESET] = ad4_ipc_reset_setup_startup,

@@ -125,6 +141,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
	[ad4_state_run][AD_SUSPEND] = ad4_suspend_setup,
	[ad4_state_run][AD_ASSERTIVE] = ad4_assertive_setup,
	[ad4_state_run][AD_BACKLIGHT] = ad4_backlight_setup,
	[ad4_state_run][AD_STRENGTH] = ad4_no_op_setup,
	[ad4_state_run][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_run,
	[ad4_state_run][AD_IPC_RESUME] = ad4_no_op_setup,
	[ad4_state_run][AD_IPC_RESET] = ad4_setup_debug,
@@ -136,6 +153,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
	[ad4_state_ipcs][AD_SUSPEND] = ad4_no_op_setup,
	[ad4_state_ipcs][AD_ASSERTIVE] = ad4_no_op_setup,
	[ad4_state_ipcs][AD_BACKLIGHT] = ad4_no_op_setup,
	[ad4_state_ipcs][AD_STRENGTH] = ad4_no_op_setup,
	[ad4_state_ipcs][AD_IPC_SUSPEND] = ad4_no_op_setup,
	[ad4_state_ipcs][AD_IPC_RESUME] = ad4_ipc_resume_setup_ipcs,
	[ad4_state_ipcs][AD_IPC_RESET] = ad4_no_op_setup,
@@ -147,9 +165,22 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
	[ad4_state_ipcr][AD_SUSPEND] = ad4_suspend_setup,
	[ad4_state_ipcr][AD_ASSERTIVE] = ad4_assertive_setup_ipcr,
	[ad4_state_ipcr][AD_BACKLIGHT] = ad4_backlight_setup_ipcr,
	[ad4_state_ipcr][AD_STRENGTH] = ad4_no_op_setup,
	[ad4_state_ipcr][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_ipcr,
	[ad4_state_ipcr][AD_IPC_RESUME] = ad4_no_op_setup,
	[ad4_state_ipcr][AD_IPC_RESET] = ad4_ipc_reset_setup_ipcr,

	[ad4_state_manual][AD_MODE] = ad4_mode_setup_common,
	[ad4_state_manual][AD_INIT] = ad4_init_setup,
	[ad4_state_manual][AD_CFG] = ad4_cfg_setup,
	[ad4_state_manual][AD_INPUT] = ad4_no_op_setup,
	[ad4_state_manual][AD_SUSPEND] = ad4_no_op_setup,
	[ad4_state_manual][AD_ASSERTIVE] = ad4_no_op_setup,
	[ad4_state_manual][AD_BACKLIGHT] = ad4_no_op_setup,
	[ad4_state_manual][AD_STRENGTH] = ad4_strength_setup,
	[ad4_state_manual][AD_IPC_SUSPEND] = ad4_no_op_setup,
	[ad4_state_manual][AD_IPC_RESUME] = ad4_no_op_setup,
	[ad4_state_manual][AD_IPC_RESET] = ad4_setup_debug_manual,
};

struct ad4_info {
@@ -288,24 +319,34 @@ static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)

static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
{
	u32 strength = 0, i = 0;
	u32 strength = 0;
	struct sde_hw_mixer *hw_lm;

	hw_lm = cfg->hw_cfg->mixer_info;
	if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer) {
	if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
		/* this AD core is the salve core */
		for (i = DSPP_0; i < DSPP_MAX; i++) {
			if (info[i].is_master) {
				strength = info[i].last_str;
				break;
			}
		}
	} else {
		strength = SDE_REG_READ(&dspp->hw,
				dspp->cap->sblk->ad.base + 0x4c);
		return 0;

	strength = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c);
	pr_debug("%s(): AD strength = %d\n", __func__, strength);

	return 0;
}

static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg)
{
	u32 strength = 0;
	struct sde_hw_mixer *hw_lm;

	hw_lm = cfg->hw_cfg->mixer_info;
	if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
		/* this AD core is the salve core */
		return 0;

	strength = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x15c);
	pr_debug("%s(): AD strength = %d in manual mode\n", __func__, strength);

	return 0;
}

@@ -313,8 +354,8 @@ static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode)
{
	u32 blk_offset;

	blk_offset = 0x04;
	if (mode == AD4_OFF) {
		blk_offset = 0x04;
		SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
				0x101);
		info[dspp->idx].state = ad4_state_idle;
@@ -328,11 +369,30 @@ static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode)
		info[dspp->idx].last_als = 0x0;
		info[dspp->idx].cached_als = U64_MAX;
	} else {
		if (mode == AD4_MANUAL) {
			/*vc_control_0 */
			blk_offset = 0x138;
			SDE_REG_WRITE(&dspp->hw,
				dspp->cap->sblk->ad.base + blk_offset, 0);
			/* irdx_control_0 */
			blk_offset = 0x13c;
			SDE_REG_WRITE(&dspp->hw,
				dspp->cap->sblk->ad.base + blk_offset,
				info[dspp->idx].irdx_control_0);
		}
		if (info[dspp->idx].state == ad4_state_idle) {
			if (mode == AD4_MANUAL) {
				info[dspp->idx].state = ad4_state_manual;
				pr_debug("%s(): AD state move to manual\n",
					__func__);
			} else {
				info[dspp->idx].frame_count = 0;
				info[dspp->idx].state = ad4_state_startup;
			pr_debug("%s(): AD state move to startup\n", __func__);
				pr_debug("%s(): AD state move to startup\n",
					__func__);
			}
		}
		blk_offset = 0x04;
		SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
				0x100);
	}
@@ -831,7 +891,7 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)

	info[dspp->idx].vc_control_0 = (ad_cfg->cfg_param_041 & (BIT(7) - 1));

	blk_offset += 160;
	blk_offset = 0x160;
	val = (ad_cfg->cfg_param_043 & (BIT(10) - 1));
	SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);

@@ -1264,6 +1324,8 @@ void sde_read_intr_resp_ad4(struct sde_hw_dspp *dspp, u32 event,
				dspp->cap->sblk->ad.base + 0x2c);
		*resp_out = SDE_REG_READ(&dspp->hw,
				dspp->cap->sblk->ad.base + 0x48);
		pr_debug("%s(): AD4 input BL %u, output BL %u\n", __func__,
			(*resp_in), (*resp_out));
		break;
	default:
		break;
@@ -1446,3 +1508,41 @@ static int ad4_ipc_reset_setup_startup(struct sde_hw_dspp *dspp,

	return 0;
}

static int ad4_strength_setup(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg)
{
	u64 strength = 0, val;
	u32 blk_offset = 0x15c;

	if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
		DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
			sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
		return -EINVAL;
	}

	if (cfg->hw_cfg->payload)
		strength = *((u64 *)cfg->hw_cfg->payload);
	else
		strength = 0;

	/* set manual strength */
	info[dspp->idx].completed_ops_mask |= ad4_strength;
	val = (strength & (BIT(10) - 1));
	SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
	return 0;
}

static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
		struct sde_ad_hw_cfg *cfg)
{
	int ret;

	ret = ad4_strength_setup(dspp, cfg);
	if (ret)
		return ret;

	if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
		ad4_mode_setup(dspp, info[dspp->idx].mode);
	return 0;
}