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

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

Merge "msm: mdss: Fix the AD backlight attenuation implementation"

parents e461c331 4b49a521
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -951,6 +951,8 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
	struct mdss_panel_data *pdata;
	int (*update_ad_input)(struct msm_fb_data_type *mfd);
	u32 temp = bkl_lvl;
	int ret = -EINVAL;
	bool is_bl_changed = (bkl_lvl != mfd->bl_level);

	if (((!mfd->panel_power_on && mfd->dcm_state != DCM_ENTER)
		|| !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
@@ -963,6 +965,12 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
	pdata = dev_get_platdata(&mfd->pdev->dev);

	if ((pdata) && (pdata->set_backlight)) {
		if (mfd->mdp.ad_attenuate_bl && is_bl_changed) {
			ret = (*mfd->mdp.ad_attenuate_bl)(bkl_lvl, &temp, mfd);
			if (ret)
				pr_err("Failed to attenuate BL\n");
		}

		mfd->bl_level_prev_scaled = mfd->bl_level_scaled;
		if (!IS_CALIB_MODE_BL(mfd))
			mdss_fb_scale_bl(mfd, &temp);
@@ -982,7 +990,7 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
		mfd->bl_level = bkl_lvl;
		mfd->bl_level_scaled = temp;

		if (mfd->mdp.update_ad_input) {
		if (mfd->mdp.update_ad_input && is_bl_changed) {
			update_ad_input = mfd->mdp.update_ad_input;
			mutex_unlock(&mfd->bl_lock);
			/* Will trigger ad_setup which will grab bl_lock */
@@ -996,21 +1004,31 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
void mdss_fb_update_backlight(struct msm_fb_data_type *mfd)
{
	struct mdss_panel_data *pdata;
	int ret = 0;
	u32 temp;

	if (mfd->unset_bl_level) {
	if (!mfd->unset_bl_level)
		return;
	mutex_lock(&mfd->bl_lock);
	if (!mfd->bl_updated) {
		pdata = dev_get_platdata(&mfd->pdev->dev);
		if ((pdata) && (pdata->set_backlight)) {
			mfd->bl_level = mfd->unset_bl_level;
				pdata->set_backlight(pdata, mfd->bl_level);
			temp = mfd->bl_level;
			if (mfd->mdp.ad_attenuate_bl) {
				ret = (*mfd->mdp.ad_attenuate_bl)(temp,
						&temp, mfd);
				if (ret)
					pr_err("Failed to attenuate BL\n");
			}

			pdata->set_backlight(pdata, temp);
			mfd->bl_level_scaled = mfd->unset_bl_level;
			mfd->bl_updated = 1;
		}
	}
	mutex_unlock(&mfd->bl_lock);
}
}

static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
			     int op_enable)
+2 −0
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ struct msm_mdp_interface {
	int (*do_histogram)(struct msm_fb_data_type *mfd,
				struct mdp_histogram *hist);
	int (*update_ad_input)(struct msm_fb_data_type *mfd);
	int (*ad_attenuate_bl)(u32 bl, u32 *bl_out,
			struct msm_fb_data_type *mfd);
	int (*panel_register_done)(struct mdss_panel_data *pdata);
	u32 (*fb_stride)(u32 fb_index, u32 xres, int bpp);
	int (*splash_init_fnc)(struct msm_fb_data_type *mfd);
+1 −0
Original line number Diff line number Diff line
@@ -402,6 +402,7 @@ enum mdss_mdp_writeback_index {

#define MDSS_MDP_MAX_AD_AL	65535
#define MDSS_MDP_MAX_AD_STR	255
#define MDSS_MDP_AD_BL_SCALE	4095

#define MDSS_MDP_REG_AD_BYPASS				0x000
#define MDSS_MDP_REG_AD_CTRL_0				0x004
+68 −17
Original line number Diff line number Diff line
@@ -403,7 +403,8 @@ static void pp_ad_bypass_config(struct mdss_ad_info *ad,
				struct mdss_mdp_ctl *ctl, u32 num, u32 *opmode);
static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd);
static void pp_ad_cfg_lut(char __iomem *addr, u32 *data);
static u32 pp_ad_attenuate_bl(u32 bl, struct mdss_ad_info *ad);
static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out,
		struct msm_fb_data_type *mfd);
static int pp_num_to_side(struct mdss_mdp_ctl *ctl, u32 num);
static inline bool pp_sts_is_enabled(u32 sts, int side);
static inline void pp_sts_set_split_bits(u32 *sts, u32 bits);
@@ -418,6 +419,19 @@ static inline void mdss_mdp_pp_get_dcm_state(struct mdss_mdp_pipe *pipe,
		*dcm_state = pipe->mixer_left->ctl->mfd->dcm_state;
}

inline int linear_map(int in, int *out, int in_max, int out_max)
{
	if (in < 0 || !out || in_max <= 0 || out_max <= 0)
		return -EINVAL;
	*out = ((in * out_max) / in_max);
	pr_debug("in = %d, out = %d, in_max = %d, out_max = %d\n",
		in, *out, in_max, out_max);
	if ((in > 0) && (*out == 0))
		*out = 1;
	return 0;

}

int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
				   struct mdp_csc_cfg *data)
{
@@ -1794,9 +1808,13 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num)
			if (ad->state & PP_AD_STATE_BL_LIN) {
				bl = ad->bl_lin[bl >> ad->bl_bright_shift];
				bl = bl << ad->bl_bright_shift;
				bl = pp_ad_attenuate_bl(bl, ad);
				ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd);
				if (ret)
					pr_err("Failed to attenuate BL\n");
			}
			ad->bl_data = bl;
			linear_map(bl, &ad->bl_data,
				ad->bl_mfd->panel_info->bl_max,
				MDSS_MDP_AD_BL_SCALE);
			pp_ad_input_write(&mdata->ad_off[dspp_num], ad);
		}
		if ((PP_AD_STATE_VSYNC & ad->state) && ad->calc_itr)
@@ -4201,11 +4219,7 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd,
	} else if (init_cfg->ops & MDP_PP_AD_CFG) {
		memcpy(&ad->cfg, &init_cfg->params.cfg,
				sizeof(struct mdss_ad_cfg));
		/*
		 * TODO: specify panel independent range of input from cfg,
		 * scale input backlight_scale to panel bl_max's range
		 */
		ad->cfg.backlight_scale = bl_mfd->panel_info->bl_max;
		ad->cfg.backlight_scale = MDSS_MDP_AD_BL_SCALE;
		ad->sts |= PP_AD_STS_DIRTY_CFG;
	}

@@ -4620,9 +4634,13 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
			if (ad->state & PP_AD_STATE_BL_LIN) {
				bl = ad->bl_lin[bl >> ad->bl_bright_shift];
				bl = bl << ad->bl_bright_shift;
				bl = pp_ad_attenuate_bl(bl, ad);
				ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd);
				if (ret)
					pr_err("Failed to attenuate BL\n");
			}
			ad->bl_data = bl;
			linear_map(bl, &ad->bl_data,
				ad->bl_mfd->panel_info->bl_max,
				MDSS_MDP_AD_BL_SCALE);
		}
		mutex_unlock(&bl_mfd->bl_lock);
		ad->reg_sts |= PP_AD_STS_DIRTY_DATA;
@@ -4672,6 +4690,7 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
		if (bl_mfd != mfd)
			bl_mfd->ext_ad_ctrl = mfd->index;
		bl_mfd->mdp.update_ad_input = pp_update_ad_input;
		bl_mfd->mdp.ad_attenuate_bl = pp_ad_attenuate_bl;
		bl_mfd->ext_bl_ctrl = ad->cfg.bl_ctrl_mode;
		mutex_unlock(&bl_mfd->bl_lock);

@@ -4701,6 +4720,7 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
			memset(&ad->cfg, 0, sizeof(struct mdss_ad_cfg));
			mutex_lock(&bl_mfd->bl_lock);
			bl_mfd->mdp.update_ad_input = NULL;
			bl_mfd->mdp.ad_attenuate_bl = NULL;
			bl_mfd->ext_bl_ctrl = 0;
			bl_mfd->ext_ad_ctrl = -1;
			mutex_unlock(&bl_mfd->bl_lock);
@@ -4842,28 +4862,59 @@ static void pp_ad_cfg_lut(char __iomem *addr, u32 *data)
			addr + ((PP_AD_LUT_LEN - 1) * 2));
}

static u32 pp_ad_attenuate_bl(u32 bl, struct mdss_ad_info *ad)
static int  pp_ad_attenuate_bl(u32 bl, u32 *bl_out,
	struct msm_fb_data_type *mfd)
{
	u32 shift = 0, ratio_temp = 0;
	u32 n, lut_interval, bl_att, out;
	u32 n, lut_interval, bl_att;
	int ret = -1;
	struct mdss_ad_info *ad;

	ratio_temp = ad->cfg.backlight_max / (AD_BL_ATT_LUT_LEN - 1);
	if (bl < 0) {
		pr_err("Invalid backlight input\n");
		return ret;
	}

	ret = mdss_mdp_get_ad(mfd, &ad);
	if (ret || !ad) {
		pr_err("Failed to get the ad.\n");
		return ret;
	}
	pr_debug("bl_in = %d\n", bl);
	/* map panel backlight range to AD backlight range */
	linear_map(bl, &bl, ad->bl_mfd->panel_info->bl_max,
		MDSS_MDP_AD_BL_SCALE);

	pr_debug("Before attenuation = %d\n", bl);
	ratio_temp = MDSS_MDP_AD_BL_SCALE / (AD_BL_ATT_LUT_LEN - 1);
	while (ratio_temp > 0) {
		ratio_temp = ratio_temp >> 1;
		shift++;
	}
	n = bl >> shift;
	lut_interval = (ad->cfg.backlight_max + 1) / (AD_BL_ATT_LUT_LEN - 1);
	if (n >= AD_BL_ATT_LUT_LEN) {
		pr_err("Invalid index for BL attenuation: %d.\n", n);
		return ret;
	}
	lut_interval = (MDSS_MDP_AD_BL_SCALE + 1) / (AD_BL_ATT_LUT_LEN - 1);
	bl_att = ad->bl_att_lut[n] + (bl - lut_interval * n) *
			(ad->bl_att_lut[n + 1] - ad->bl_att_lut[n]) /
			lut_interval;
	pr_debug("n = %d, bl_att = %d\n", n, bl_att);
	if (ad->init.alpha_base)
		out = (ad->init.alpha * bl_att +
		*bl_out = (ad->init.alpha * bl_att +
			(ad->init.alpha_base - ad->init.alpha) * bl) /
			ad->init.alpha_base;
	else
		out = bl;
	return out;
		*bl_out = bl;

	pr_debug("After attenuation = %d\n", *bl_out);
	/* map AD backlight range back to panel backlight range */
	linear_map(*bl_out, bl_out, MDSS_MDP_AD_BL_SCALE,
		ad->bl_mfd->panel_info->bl_max);

	pr_debug("bl_out = %d\n", *bl_out);
	return 0;
}

int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_offsets)