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

Commit 267fe449 authored by Benet Clark's avatar Benet Clark
Browse files

msm: mdss: Remove 1:1 mixer to DSPP assumption in pp mixer setup



Previously, the PP driver assumed that there would be a DSPP for every
INTF mixer. However, this assumption does not hold true for all targets.
This change fixes the errors caused by assuming the 1:1 ratio and allows
all layer mixers to be programmed based on CTL configuration.

Change-Id: I15d03921c9b91212717417296e3a157e97b5113a
Signed-off-by: default avatarBenet Clark <benetc@codeaurora.org>
parent 48cae9a4
Loading
Loading
Loading
Loading
+54 −39
Original line number Diff line number Diff line
@@ -1457,45 +1457,40 @@ int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op)
	return ret;
}

static int pp_mixer_setup(u32 disp_num,
		struct mdss_mdp_mixer *mixer)
static int pp_mixer_setup(struct mdss_mdp_mixer *mixer)
{
	u32 flags, dspp_num, opmode = 0, lm_bitmask = 0;
	u32 flags, disp_num, opmode = 0, lm_bitmask = 0;
	struct mdp_pgc_lut_data *pgc_config;
	struct pp_sts_type *pp_sts;
	struct mdss_mdp_ctl *ctl;
	char __iomem *addr;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();

	if (!mixer || !mixer->ctl || !mdata)
	if (!mixer || !mixer->ctl || !mixer->ctl->mfd || !mdata) {
		pr_err("invalid parameters, mixer %p ctl %p mfd %p mdata %p\n",
			mixer, (mixer ? mixer->ctl : NULL),
			(mixer ? (mixer->ctl ? mixer->ctl->mfd : NULL) : NULL),
			mdata);
		return -EINVAL;
	dspp_num = mixer->num;
	}
	ctl = mixer->ctl;
	disp_num = ctl->mfd->index;

	/* no corresponding dspp */
	if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
		(dspp_num >= mdata->ndspp))
		return 0;
	if (disp_num < MDSS_BLOCK_DISP_NUM)
		flags = mdss_pp_res->pp_disp_flags[disp_num];
	else
		flags = 0;

	lm_bitmask = (dspp_num == MDSS_MDP_DSPP3) ?
		BIT(20) : (BIT(6) << dspp_num);
	if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
		lm_bitmask = BIT(20);
	else if (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
		lm_bitmask = BIT(9) << mixer->num;
	else
		lm_bitmask = BIT(6) << mixer->num;

	pp_sts = &mdss_pp_res->pp_disp_sts[disp_num];
	/* GC_LUT is in layer mixer */
	if (flags & PP_FLAGS_DIRTY_ARGC) {
		/*
		 * GC LUT should be disabled before being rewritten. Skip
		 * GC LUT programming if it is already enabled.
		 */
		if (pp_sts->argc_sts & PP_STS_ENABLE) {
			pr_debug("LM %d GC already enabled, skipping programming\n",
					mixer->num);
			return 0;
		}
		if (pp_ops[GC].pp_set_config) {
			if (mdata->pp_block_off.lm_pgc_off == U32_MAX) {
				pr_err("invalid pgc offset %d\n", U32_MAX);
@@ -1536,17 +1531,17 @@ static int pp_mixer_setup(u32 disp_num,
	return 0;
}

static char __iomem *mdss_mdp_get_mixer_addr_off(u32 dspp_num)
static char __iomem *mdss_mdp_get_mixer_addr_off(u32 mixer_num)
{
	struct mdss_data_type *mdata;
	struct mdss_mdp_mixer *mixer;

	mdata = mdss_mdp_get_mdata();
	if (mdata->ndspp <= dspp_num) {
		pr_err("Invalid dspp_num=%d\n", dspp_num);
	if (mdata->nmixers_intf <= mixer_num) {
		pr_err("Invalid mixer_num=%d\n", mixer_num);
		return ERR_PTR(-EINVAL);
	}
	mixer = mdata->mixer_intf + dspp_num;
	mixer = mdata->mixer_intf + mixer_num;
	return mixer->base;
}

@@ -1974,7 +1969,7 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
	int i, req = -1;
	bool valid_mixers = true;
	bool valid_ad_panel = true;
	if ((!ctl->mfd) || (!mdss_pp_res) || (!mdata))
	if ((!ctl) || (!ctl->mfd) || (!mdss_pp_res) || (!mdata))
		return -EINVAL;

	/* treat fb_num the same as block logical id*/
@@ -2031,11 +2026,11 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
	}

	if (ctl->mixer_left) {
		pp_mixer_setup(disp_num, ctl->mixer_left);
		pp_mixer_setup(ctl->mixer_left);
		pp_dspp_setup(disp_num, ctl->mixer_left);
	}
	if (ctl->mixer_right) {
		pp_mixer_setup(disp_num, ctl->mixer_right);
		pp_mixer_setup(ctl->mixer_right);
		pp_dspp_setup(disp_num, ctl->mixer_right);
	}
	/* clear dirty flag */
@@ -3440,17 +3435,20 @@ int mdss_mdp_argc_config(struct msm_fb_data_type *mfd,
				u32 *copyback)
{
	int ret = 0;
	u32 disp_num, dspp_num = 0, is_lm = 0;
	u32 disp_num, num = 0, is_lm = 0;
	struct mdp_pgc_lut_data local_cfg;
	struct mdp_pgc_lut_data *pgc_ptr;
	u32 tbl_size, r_size, g_size, b_size;
	char __iomem *argc_addr = 0;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct mdss_mdp_ctl *ctl = NULL;
	u32 dirty_flag = 0;

	if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
		(PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
		(PP_BLOCK(config->block) >= MDP_BLOCK_MAX)) {
		pr_err("invalid block value %d\n", PP_BLOCK(config->block));
		return -EINVAL;
	}

	if ((config->flags & MDSS_PP_SPLIT_MASK) == MDSS_PP_SPLIT_MASK) {
		pr_warn("Can't set both split bits\n");
@@ -3465,21 +3463,38 @@ int mdss_mdp_argc_config(struct msm_fb_data_type *mfd,
	}

	disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
	ret = pp_get_dspp_num(disp_num, &dspp_num);
	if (ret) {
		pr_err("%s, no dspp connects to disp %d\n", __func__, disp_num);
		goto argc_config_exit;
	ctl = mfd_to_ctl(mfd);
	num = (ctl && ctl->mixer_left) ? ctl->mixer_left->num : -1;
	if (num < 0) {
		pr_err("invalid mfd index %d config\n",
				mfd->index);
		return -EPERM;
	}

	switch (PP_LOCAT(config->block)) {
	case MDSS_PP_LM_CFG:
		argc_addr = mdss_mdp_get_mixer_addr_off(dspp_num) +
		/*
		 * LM GC LUT should be disabled before being rewritten. Skip
		 * GC LUT config if it is already enabled.
		 */
		if ((mdss_pp_res->pp_disp_sts[disp_num].argc_sts &
				PP_STS_ENABLE) &&
				!(config->flags & MDP_PP_OPS_DISABLE)) {
			pr_err("LM GC already enabled disp %d, skipping config\n",
					mfd->index);
			return -EPERM;
		}
		argc_addr = mdss_mdp_get_mixer_addr_off(num) +
			MDSS_MDP_REG_LM_GC_LUT_BASE;
		pgc_ptr = &mdss_pp_res->argc_disp_cfg[disp_num];
		dirty_flag = PP_FLAGS_DIRTY_ARGC;
		break;
	case MDSS_PP_DSPP_CFG:
		argc_addr = mdss_mdp_get_dspp_addr_off(dspp_num) +
		if (!mdss_mdp_mfd_valid_dspp(mfd)) {
			pr_err("invalid mfd index %d for dspp config\n",
				mfd->index);
			return -EPERM;
		}
		argc_addr = mdss_mdp_get_dspp_addr_off(num) +
					MDSS_MDP_REG_DSPP_GC_BASE;
		pgc_ptr = &mdss_pp_res->pgc_disp_cfg[disp_num];
		dirty_flag = PP_FLAGS_DIRTY_PGC;
@@ -3507,8 +3522,8 @@ int mdss_mdp_argc_config(struct msm_fb_data_type *mfd,
				goto clock_off;
			}
			temp_addr = (is_lm) ?
				     mdss_mdp_get_mixer_addr_off(dspp_num) :
				     mdss_mdp_get_dspp_addr_off(dspp_num);
				     mdss_mdp_get_mixer_addr_off(num) :
				     mdss_mdp_get_dspp_addr_off(num);
			if (IS_ERR_OR_NULL(temp_addr)) {
				pr_err("invalid addr is_lm %d\n", is_lm);
				ret = -EINVAL;
@@ -3558,7 +3573,7 @@ clock_off:
			pr_debug("version of gc is %d\n", config->version);
			is_lm = (PP_LOCAT(config->block) == MDSS_PP_LM_CFG);
			ret = pp_pgc_lut_cache_params(config, mdss_pp_res,
				((is_lm) ? LM : DSPP), dspp_num);
				((is_lm) ? LM : DSPP));
			if (ret) {
				pr_err("gamut set config failed ret %d\n",
					ret);
+4 −6
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@

#define MDSS_BLOCK_DISP_NUM (MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)

#define MDSS_BLOCK_LM_NUM (MDSS_BLOCK_DISP_NUM + \
			  MDSS_MDP_INTF_MAX_LAYERMIXER)
/* PP STS related flags */
#define PP_STS_ENABLE	0x1
#define PP_STS_GAMUT_FIRST	0x2
@@ -103,9 +101,9 @@ struct mdp_pp_driver_ops {
};

struct mdss_pp_res_type_v1_7 {
	u32 pgc_lm_table_c0[MDSS_BLOCK_LM_NUM][PGC_LUT_ENTRIES];
	u32 pgc_lm_table_c1[MDSS_BLOCK_LM_NUM][PGC_LUT_ENTRIES];
	u32 pgc_lm_table_c2[MDSS_BLOCK_LM_NUM][PGC_LUT_ENTRIES];
	u32 pgc_lm_table_c0[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
	u32 pgc_lm_table_c1[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
	u32 pgc_lm_table_c2[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
	u32 pgc_table_c0[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
	u32 pgc_table_c1[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
	u32 pgc_table_c2[MDSS_BLOCK_DISP_NUM][PGC_LUT_ENTRIES];
@@ -115,7 +113,7 @@ struct mdss_pp_res_type_v1_7 {
	u32 six_zone_lut_p0[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
	u32 six_zone_lut_p1[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
	struct mdp_pgc_lut_data_v1_7 pgc_dspp_v17_data[MDSS_BLOCK_DISP_NUM];
	struct mdp_pgc_lut_data_v1_7 pgc_lm_v17_data[MDSS_BLOCK_LM_NUM];
	struct mdp_pgc_lut_data_v1_7 pgc_lm_v17_data[MDSS_BLOCK_DISP_NUM];
	struct mdp_igc_lut_data_v1_7 igc_v17_data[MDSS_BLOCK_DISP_NUM];
	struct mdp_hist_lut_data_v1_7 hist_lut_v17_data[MDSS_BLOCK_DISP_NUM];
	struct mdp_dither_data_v1_7 dither_v17_data[MDSS_BLOCK_DISP_NUM];
+31 −27
Original line number Diff line number Diff line
@@ -967,21 +967,20 @@ igc_exit:

static int pp_pgc_lut_cache_params_v1_7(struct mdp_pgc_lut_data *config,
			    struct mdss_pp_res_type *mdss_pp_res,
			    int location, int cnt)
			    int location)
{
	int ret = 0, max_cnt = 0;
	int ret = 0;
	u32 sz = 0;
	u32 disp_num;
	struct mdp_pgc_lut_data_v1_7 *v17_cache_data = NULL, v17_usr_config;
	struct mdss_pp_res_type_v1_7 *res_cache = NULL;
	if (location != DSPP && location != LM) {
		pr_err("Invalid location for pgc %d\n", location);
		return -EINVAL;
	}
	max_cnt = (location == DSPP) ? MDSS_BLOCK_DISP_NUM :
		   MDSS_BLOCK_LM_NUM;
	if (cnt >= max_cnt) {
		pr_err("invalid layer count %d max is %d location is %d\n",
			cnt, max_cnt, location);
	disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
	if (disp_num >= MDSS_BLOCK_DISP_NUM) {
		pr_err("invalid disp_num %d\n", disp_num);
		return -EINVAL;
	}
	res_cache = mdss_pp_res->pp_data_res;
@@ -1006,25 +1005,32 @@ static int pp_pgc_lut_cache_params_v1_7(struct mdp_pgc_lut_data *config,
	if (!(config->flags & MDP_PP_OPS_WRITE)) {
		pr_debug("ops write not set flags %d\n", config->flags);
		if (location == DSPP)
			mdss_pp_res->pgc_disp_cfg[cnt].flags = config->flags;
			mdss_pp_res->pgc_disp_cfg[disp_num].flags =
				config->flags;
		else
			mdss_pp_res->argc_disp_cfg[cnt].flags = config->flags;
			mdss_pp_res->argc_disp_cfg[disp_num].flags =
				config->flags;
		return 0;
	}
	if (location == DSPP) {
		mdss_pp_res->pgc_disp_cfg[cnt] = *config;
		v17_cache_data = &res_cache->pgc_dspp_v17_data[cnt];
		v17_cache_data->c0_data = &res_cache->pgc_table_c0[cnt][0];
		v17_cache_data->c1_data = &res_cache->pgc_table_c1[cnt][0];
		v17_cache_data->c2_data = &res_cache->pgc_table_c2[cnt][0];
		mdss_pp_res->pgc_disp_cfg[cnt].cfg_payload = v17_cache_data;
		mdss_pp_res->pgc_disp_cfg[disp_num] = *config;
		v17_cache_data = &res_cache->pgc_dspp_v17_data[disp_num];
		v17_cache_data->c0_data = &res_cache->pgc_table_c0[disp_num][0];
		v17_cache_data->c1_data = &res_cache->pgc_table_c1[disp_num][0];
		v17_cache_data->c2_data = &res_cache->pgc_table_c2[disp_num][0];
		mdss_pp_res->pgc_disp_cfg[disp_num].cfg_payload =
			v17_cache_data;
	} else {
		mdss_pp_res->argc_disp_cfg[cnt] = *config;
		v17_cache_data = &res_cache->pgc_lm_v17_data[cnt];
		v17_cache_data->c0_data = &res_cache->pgc_lm_table_c0[cnt][0];
		v17_cache_data->c1_data = &res_cache->pgc_lm_table_c1[cnt][0];
		v17_cache_data->c2_data = &res_cache->pgc_lm_table_c2[cnt][0];
		mdss_pp_res->argc_disp_cfg[cnt].cfg_payload = v17_cache_data;
		mdss_pp_res->argc_disp_cfg[disp_num] = *config;
		v17_cache_data = &res_cache->pgc_lm_v17_data[disp_num];
		v17_cache_data->c0_data =
			&res_cache->pgc_lm_table_c0[disp_num][0];
		v17_cache_data->c1_data =
			&res_cache->pgc_lm_table_c1[disp_num][0];
		v17_cache_data->c2_data =
			&res_cache->pgc_lm_table_c2[disp_num][0];
		mdss_pp_res->argc_disp_cfg[disp_num].cfg_payload =
			v17_cache_data;
	}
	v17_cache_data->len = 0;
	sz = PGC_LUT_ENTRIES * sizeof(u32);
@@ -1050,15 +1056,14 @@ static int pp_pgc_lut_cache_params_v1_7(struct mdp_pgc_lut_data *config,
	return 0;
bail_out:
	if (location == DSPP)
		mdss_pp_res->pgc_disp_cfg[cnt].flags = 0;
		mdss_pp_res->pgc_disp_cfg[disp_num].flags = 0;
	else
		mdss_pp_res->argc_disp_cfg[cnt].flags = 0;
		mdss_pp_res->argc_disp_cfg[disp_num].flags = 0;
	return ret;
}

int pp_pgc_lut_cache_params(struct mdp_pgc_lut_data *config,
			    struct mdss_pp_res_type *mdss_pp_res, int loc,
			    int cnt)
			    struct mdss_pp_res_type *mdss_pp_res, int loc)
{
	int ret = 0;
	if (!config || !mdss_pp_res) {
@@ -1068,8 +1073,7 @@ int pp_pgc_lut_cache_params(struct mdp_pgc_lut_data *config,
	}
	switch (config->version) {
	case mdp_pgc_v1_7:
		ret = pp_pgc_lut_cache_params_v1_7(config, mdss_pp_res,
						   loc, cnt);
		ret = pp_pgc_lut_cache_params_v1_7(config, mdss_pp_res, loc);
		break;
	default:
		pr_err("unsupported igc version %d\n",
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ int pp_igc_lut_cache_params(struct mdp_igc_lut_data *config,

int pp_pgc_lut_cache_params(struct mdp_pgc_lut_data *config,
			    struct mdss_pp_res_type *mdss_pp_res,
			    int location, int cnt);
			    int location);

int pp_copy_layer_igc_payload(struct mdp_overlay_pp_params *pp_info);
int pp_copy_layer_hist_lut_payload(struct mdp_overlay_pp_params *pp_info);
+22 −15
Original line number Diff line number Diff line
@@ -1900,7 +1900,7 @@ static int pp_pgc_set_config(char __iomem *base_addr,
		u32 block_type)
{
	char __iomem *c0 = NULL, *c1 = NULL, *c2 = NULL;
	u32 val = 0, i = 0;
	u32 val = 0, i = 0, *sts = NULL;
	struct mdp_pgc_lut_data *pgc_data = NULL;
	struct mdp_pgc_lut_data_v1_7  *pgc_data_v17 = NULL;

@@ -1909,22 +1909,32 @@ static int pp_pgc_set_config(char __iomem *base_addr,
		      base_addr, cfg_data, pp_sts);
		return -EINVAL;
	}
	if (block_type != DSPP && block_type != LM) {
		pr_err("invalid block type %d\n", block_type);
		return -EINVAL;
	}
	sts = (block_type == DSPP) ? &pp_sts->pgc_sts : &pp_sts->argc_sts;
	pgc_data = (struct mdp_pgc_lut_data *) cfg_data;
	pgc_data_v17 = (struct mdp_pgc_lut_data_v1_7 *)
			pgc_data->cfg_payload;
	if (pgc_data->version != mdp_pgc_v1_7 || !pgc_data_v17) {
		pr_err("invalid pgc version %d payload %p\n",
			pgc_data->version, pgc_data_v17);
	if (pgc_data->version != mdp_pgc_v1_7) {
		pr_err("invalid pgc version %d\n",
			pgc_data->version);
		return -EINVAL;
	}
	if (!(pgc_data->flags & ~(MDP_PP_OPS_READ))) {
		pr_info("only read ops is set %d", pgc_data->flags);
		pr_debug("only read ops is set %d", pgc_data->flags);
		return 0;
	}
	if (!(pgc_data->flags & MDP_PP_OPS_WRITE)) {
		pr_info("only read ops is set %d", pgc_data->flags);
	if (pgc_data->flags & MDP_PP_OPS_DISABLE) {
		pr_debug("disable GC\n");
		goto set_ops;
	}

	pgc_data_v17 = (struct mdp_pgc_lut_data_v1_7 *) pgc_data->cfg_payload;
	if (!pgc_data_v17) {
		pr_err("invalid payload for GC %p\n", pgc_data_v17);
		return -EINVAL;
	}

	if (pgc_data_v17->len != PGC_LUT_ENTRIES || !pgc_data_v17->c0_data ||
	    !pgc_data_v17->c1_data || !pgc_data_v17->c2_data) {
		pr_err("Invalid params entries %d c0_data %p c1_data %p c2_data %p\n",
@@ -1932,10 +1942,6 @@ static int pp_pgc_set_config(char __iomem *base_addr,
			pgc_data_v17->c1_data, pgc_data_v17->c2_data);
		return -EINVAL;
	}
	if (block_type != DSPP && block_type != LM) {
		pr_err("invalid block type %d\n", block_type);
		return -EINVAL;
	}
	c0 = base_addr + PGC_C0_LUT_INDEX;
	c1 = c0 + PGC_C1C2_LUT_OFF;
	c2 = c1 + PGC_C1C2_LUT_OFF;
@@ -1961,14 +1967,15 @@ static int pp_pgc_set_config(char __iomem *base_addr,
		val = PGC_SWAP;
		writel_relaxed(val, base_addr + PGC_LUT_SWAP);
	}

set_ops:
	if (pgc_data->flags & MDP_PP_OPS_DISABLE) {
		pp_sts->pgc_sts &= ~PP_STS_ENABLE;
		*sts &= ~PP_STS_ENABLE;
		writel_relaxed(0, base_addr + PGC_OPMODE_OFF);
	} else if (pgc_data->flags & MDP_PP_OPS_ENABLE) {
		val = PGC_ENABLE;
		writel_relaxed(val, base_addr + PGC_OPMODE_OFF);
		pp_sts->pgc_sts |= PP_STS_ENABLE;
		*sts |= PP_STS_ENABLE;
	}
	return 0;
}