Loading drivers/video/msm/mdss/mdss_fb.c +35 −28 Original line number Diff line number Diff line Loading @@ -720,6 +720,7 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->bl_level = 0; mfd->bl_scale = 1024; mfd->bl_min_lvl = 30; mfd->ad_bl_level = 0; mfd->fb_imgType = MDP_RGBA_8888; mfd->pdev = pdev; Loading Loading @@ -1054,10 +1055,9 @@ static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl) 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; u32 temp = bkl_lvl, ad_bl; int ret = -EINVAL; bool is_bl_changed = (bkl_lvl != mfd->bl_level); bool bl_notify_needed = false; /* todo: temporary workaround to support doze mode */ if ((bkl_lvl == 0) && (mfd->doze_mode)) { Loading @@ -1077,12 +1077,18 @@ 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) { ret = (*mfd->mdp.ad_attenuate_bl)(bkl_lvl, &temp, mfd); if (ret) pr_err("Failed to attenuate BL\n"); if (mfd->mdp.ad_calc_bl) { if (mfd->ad_bl_level == 0) mfd->ad_bl_level = temp; ad_bl = mfd->ad_bl_level; ret = (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp, &ad_bl); if ((!ret) && (mfd->ad_bl_level != ad_bl) && mfd->mdp.ad_invalidate_input) { mfd->ad_bl_level = ad_bl; (*mfd->mdp.ad_invalidate_input)(mfd); bl_notify_needed = true; } } if (!IS_CALIB_MODE_BL(mfd)) mdss_fb_scale_bl(mfd, &temp); /* Loading @@ -1095,20 +1101,14 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl) */ if (mfd->bl_level_scaled == temp) { mfd->bl_level = bkl_lvl; return; } } else { pr_debug("backlight sent to panel :%d\n", temp); pdata->set_backlight(pdata, temp); mfd->bl_level = bkl_lvl; mfd->bl_level_scaled = temp; 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 */ update_ad_input(mfd); mutex_lock(&mfd->bl_lock); bl_notify_needed = true; } if (bl_notify_needed) mdss_fb_bl_update_notify(mfd); } } Loading @@ -1118,6 +1118,7 @@ void mdss_fb_update_backlight(struct msm_fb_data_type *mfd) struct mdss_panel_data *pdata; int ret = 0; u32 temp; u32 ad_bl; if (!mfd->unset_bl_level) return; Loading @@ -1127,16 +1128,22 @@ void mdss_fb_update_backlight(struct msm_fb_data_type *mfd) if ((pdata) && (pdata->set_backlight)) { mfd->bl_level = mfd->unset_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"); if (mfd->mdp.ad_calc_bl) { if (mfd->ad_bl_level == 0) mfd->ad_bl_level = temp; ad_bl = mfd->ad_bl_level; ret = (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp, &ad_bl); if ((!ret) && (mfd->ad_bl_level != ad_bl) && mfd->mdp.ad_invalidate_input) { mfd->ad_bl_level = ad_bl; (*mfd->mdp.ad_invalidate_input)(mfd); } } pdata->set_backlight(pdata, temp); mfd->bl_level_scaled = mfd->unset_bl_level; mfd->bl_updated = 1; mdss_fb_bl_update_notify(mfd); } } mutex_unlock(&mfd->bl_lock); Loading drivers/video/msm/mdss/mdss_fb.h +7 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif #define MDP_PP_AD_BL_LINEAR 0x0 #define MDP_PP_AD_BL_LINEAR_INV 0x1 /** * enum mdp_notify_event - Different frame events to indicate frame update state * Loading Loading @@ -147,9 +150,9 @@ struct msm_mdp_interface { int (*lut_update)(struct msm_fb_data_type *mfd, struct fb_cmap *cmap); 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 (*ad_invalidate_input)(struct msm_fb_data_type *mfd); int (*ad_calc_bl)(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out); 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); Loading Loading @@ -219,6 +222,7 @@ struct msm_fb_data_type { int ext_ad_ctrl; u32 ext_bl_ctrl; u32 calib_mode; u32 ad_bl_level; u32 bl_level; u32 bl_scale; u32 bl_min_lvl; Loading drivers/video/msm/mdss/mdss_mdp.h +1 −1 Original line number Diff line number Diff line Loading @@ -354,7 +354,6 @@ struct mdss_ad_info { u32 last_bl; u32 bl_data; u32 calc_itr; uint32_t bl_bright_shift; uint32_t bl_lin[AD_BL_LIN_LEN]; uint32_t bl_lin_inv[AD_BL_LIN_LEN]; uint32_t bl_att_lut[AD_BL_ATT_LUT_LEN]; Loading Loading @@ -805,6 +804,7 @@ int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx, int mdss_mdp_pp_init(struct device *dev); void mdss_mdp_pp_term(struct device *dev); int mdss_mdp_pp_override_pu(int enable); int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num); Loading drivers/video/msm/mdss/mdss_mdp_overlay.c +2 −0 Original line number Diff line number Diff line Loading @@ -3893,6 +3893,8 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) } } if (mdss_mdp_pp_overlay_init(mfd)) pr_warn("Failed to initialize pp overlay data.\n"); return rc; init_fail: kfree(mdp5_data); Loading drivers/video/msm/mdss/mdss_mdp_pp.c +218 −107 Original line number Diff line number Diff line Loading @@ -395,10 +395,11 @@ static int pp_read_pa_v2_regs(char __iomem *addr, u32 disp_num); static void pp_read_pa_mem_col_regs(char __iomem *addr, struct mdp_pa_mem_col_cfg *mem_col_cfg); static struct msm_fb_data_type *mdss_get_mfd_from_index(int index); static int mdss_ad_init_checks(struct msm_fb_data_type *mfd); static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, struct mdss_ad_info **ad); static int pp_update_ad_input(struct msm_fb_data_type *mfd); static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd); static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t); static void pp_ad_cfg_write(struct mdss_mdp_ad *ad_hw, struct mdss_ad_info *ad); Loading @@ -412,8 +413,11 @@ 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 int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, struct msm_fb_data_type *mfd); static int pp_ad_attenuate_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out); static int pp_ad_linearize_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out, int inv); static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out); 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); Loading Loading @@ -1876,6 +1880,7 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) struct pp_sts_type pp_sts; struct mdss_ad_info *ad; struct mdss_data_type *mdata = ctl->mdata; struct msm_fb_data_type *bl_mfd; if (!mdata) return -EPERM; Loading @@ -1885,36 +1890,6 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) return -EINVAL; } disp_num = ctl->mfd->index; if (dspp_num < mdata->nad_cfgs) { ret = mdss_mdp_get_ad(ctl->mfd, &ad); if (ret) return ret; if (PP_AD_STATE_CFG & ad->state) pp_ad_cfg_write(&mdata->ad_off[dspp_num], ad); if (PP_AD_STATE_INIT & ad->state) pp_ad_init_write(&mdata->ad_off[dspp_num], ad, ctl); if ((PP_AD_STATE_DATA & ad->state) && (ad->sts & PP_STS_ENABLE)) { bl = ad->bl_mfd->bl_level; ad->last_bl = bl; if (ad->state & PP_AD_STATE_BL_LIN) { bl = ad->bl_lin[bl >> ad->bl_bright_shift]; bl = bl << ad->bl_bright_shift; ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd); if (ret) pr_err("Failed to attenuate BL\n"); } 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) ctl->add_vsync_handler(ctl, &ad->handle); } pp_sts = mdss_pp_res->pp_disp_sts[disp_num]; if (pp_sts.pa_sts & PP_STS_ENABLE) { Loading Loading @@ -1983,6 +1958,47 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) mdss_pp_res->pp_disp_flags[disp_num] |= flags; mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_RESUME_COMMIT; if (dspp_num < mdata->nad_cfgs) { ret = mdss_mdp_get_ad(ctl->mfd, &ad); if (ret) { pr_warn("Failed to get AD info, err = %d\n", ret); return ret; } if (ctl->mfd->panel_info->type == WRITEBACK_PANEL) { bl_mfd = mdss_get_mfd_from_index(0); if (!bl_mfd) { ret = -EINVAL; pr_warn("Failed to get primary FB bl handle, err = %d\n", ret); return ret; } } else { bl_mfd = ctl->mfd; } mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->ad_bl_level; mutex_unlock(&bl_mfd->bl_lock); mutex_lock(&ad->lock); if (PP_AD_STATE_CFG & ad->state) pp_ad_cfg_write(&mdata->ad_off[dspp_num], ad); if (PP_AD_STATE_INIT & ad->state) pp_ad_init_write(&mdata->ad_off[dspp_num], ad, ctl); if ((PP_AD_STATE_DATA & ad->state) && (ad->sts & PP_STS_ENABLE)) { ad->last_bl = 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) ctl->add_vsync_handler(ctl, &ad->handle); mutex_unlock(&ad->lock); } return 0; } Loading Loading @@ -2072,6 +2088,80 @@ int mdss_mdp_pp_override_pu(int enable) return 0; } int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd) { if (!mfd) { pr_err("Invalid mfd.\n"); return -EPERM; } mfd->mdp.ad_invalidate_input = pp_ad_invalidate_input; mfd->mdp.ad_calc_bl = pp_ad_calc_bl; return 0; } int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out) { int ret = -1; int temp = bl_in; struct mdss_ad_info *ad; ret = mdss_mdp_get_ad(mfd, &ad); if (ret == -ENODEV) { pr_debug("AD not supported on device.\n"); return ret; } else if (ret || !ad) { pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", ret, ad); return ret; } mutex_lock(&ad->lock); if (!(ad->state & PP_AD_STATE_RUN)) { pr_debug("AD is not running.\n"); mutex_unlock(&ad->lock); return -EPERM; } if (!ad->bl_mfd || !ad->bl_mfd->panel_info || !ad->bl_att_lut) { pr_err("Invalid ad info: bl_mfd = 0x%p, ad->bl_mfd->panel_info = 0x%p, bl_att_lut = 0x%p\n", ad->bl_mfd, (!ad->bl_mfd) ? NULL : ad->bl_mfd->panel_info, ad->bl_att_lut); mutex_unlock(&ad->lock); return -EINVAL; } ret = pp_ad_linearize_bl(ad, bl_in, &temp, MDP_PP_AD_BL_LINEAR); if (ret) { pr_err("Failed to linearize BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } ret = pp_ad_attenuate_bl(ad, temp, &temp); if (ret) { pr_err("Failed to attenuate BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } *ad_bl_out = temp; ret = pp_ad_linearize_bl(ad, temp, &temp, MDP_PP_AD_BL_LINEAR_INV); if (ret) { pr_err("Failed to inverse linearize BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } *bl_out = temp; mutex_unlock(&ad->lock); return 0; } static int pp_get_dspp_num(u32 disp_num, u32 *dspp_num) { int i; Loading Loading @@ -4232,34 +4322,42 @@ static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, return ret; } static int pp_update_ad_input(struct msm_fb_data_type *mfd) /* must call this function from within ad->lock */ static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd) { int ret; struct mdss_ad_info *ad; struct mdss_ad_input input; struct mdss_mdp_ctl *ctl; if (!mfd) if (!mfd) { pr_err("Invalid mfd\n"); return -EINVAL; } ctl = mfd_to_ctl(mfd); if (!ctl) if (!ctl) { pr_err("Invalid ctl\n"); return -EINVAL; } ret = mdss_mdp_get_ad(mfd, &ad); if (ret) return ret; if (!ad || ad->cfg.mode == MDSS_AD_MODE_AUTO_BL) if (ret || !ad) { pr_err("Fail to get ad: ret = %d, ad = 0x%p\n", ret, ad); return -EINVAL; } pr_debug("AD backlight level changed (%d), trigger update to AD\n", mfd->ad_bl_level); if (ad->cfg.mode == MDSS_AD_MODE_AUTO_BL) { pr_err("AD auto backlight no longer supported.\n"); return -EINVAL; } pr_debug("backlight level changed (%d), trigger update to AD\n", mfd->bl_level); input.mode = ad->cfg.mode; if (MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode, MDSS_AD_INPUT_AMBIENT)) input.in.amb_light = ad->ad_data; else input.in.strength = ad->ad_data; /* call to ad_input will trigger backlight read */ return mdss_mdp_ad_input(mfd, &input, 0); if (ad->state & PP_AD_STATE_RUN) { ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; ad->sts |= PP_AD_STS_DIRTY_DATA; } return 0; } int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, Loading @@ -4268,7 +4366,7 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, struct mdss_ad_info *ad; struct msm_fb_data_type *bl_mfd; int lin_ret = -1, inv_ret = -1, att_ret = -1, ret = 0; u32 ratio_temp, shift = 0, last_ops; u32 last_ops; ret = mdss_mdp_get_ad(mfd, &ad); if (ret) Loading Loading @@ -4301,12 +4399,6 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, sizeof(uint32_t)); if (lin_ret || inv_ret) ret = -ENOMEM; ratio_temp = mfd->panel_info->bl_max / AD_BL_LIN_LEN; while (ratio_temp > 0) { ratio_temp = ratio_temp >> 1; shift++; } ad->bl_bright_shift = shift; } else { ret = -EINVAL; } Loading Loading @@ -4406,7 +4498,7 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd, goto error; } ad->ad_data_mode = MDSS_AD_INPUT_AMBIENT; pr_debug("ambient = %d", input->in.amb_light); pr_debug("ambient = %d\n", input->in.amb_light); ad->ad_data = input->in.amb_light; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; Loading @@ -4425,7 +4517,7 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd, goto error; } ad->ad_data_mode = MDSS_AD_INPUT_STRENGTH; pr_debug("strength = %d", input->in.strength); pr_debug("strength = %d\n", input->in.strength); ad->ad_data = input->in.strength; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; Loading Loading @@ -4725,6 +4817,10 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) mdata = mfd_to_mdata(mfd); mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->ad_bl_level; mutex_unlock(&bl_mfd->bl_lock); mutex_lock(&ad->lock); if (ad->sts != last_sts || ad->state != last_state) { last_sts = ad->sts; Loading @@ -4741,26 +4837,16 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) */ ad->sts &= ~PP_AD_STS_DIRTY_DATA; ad->state |= PP_AD_STATE_DATA; mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->bl_level; pr_debug("dirty data, last_bl = %d\n", ad->last_bl); if ((ad->cfg.mode == MDSS_AD_MODE_AUTO_STR) && (ad->last_bl != bl)) { ad->last_bl = bl; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; if (ad->state & PP_AD_STATE_BL_LIN) { bl = ad->bl_lin[bl >> ad->bl_bright_shift]; bl = bl << ad->bl_bright_shift; ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd); if (ret) pr_err("Failed to attenuate BL\n"); } 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; } Loading Loading @@ -4804,14 +4890,9 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) bypass = 0; ad->reg_sts |= PP_AD_STS_DIRTY_ENABLE; ad->state |= PP_AD_STATE_RUN; mutex_lock(&bl_mfd->bl_lock); 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); } else { if (ad->state & PP_AD_STATE_RUN) { ad->reg_sts = PP_AD_STS_DIRTY_ENABLE; Loading @@ -4822,7 +4903,6 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) ad->state &= !PP_AD_STATE_CFG; ad->state &= !PP_AD_STATE_DATA; ad->state &= !PP_AD_STATE_BL_LIN; ad->bl_bright_shift = 0; ad->ad_data = 0; ad->ad_data_mode = 0; ad->last_bl = 0; Loading @@ -4836,12 +4916,8 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) AD_BL_ATT_LUT_LEN); memset(&ad->init, 0, sizeof(struct mdss_ad_init)); 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); } ad->state &= ~PP_AD_STATE_RUN; } Loading Loading @@ -4883,7 +4959,7 @@ static void pp_ad_calc_worker(struct work_struct *work) struct msm_fb_data_type *mfd, *bl_mfd; struct mdss_data_type *mdata; char __iomem *base; u32 bl, calc_done = 0; u32 calc_done = 0; ad = container_of(work, struct mdss_ad_info, calc_work); mutex_lock(&ad->lock); Loading Loading @@ -4925,22 +5001,8 @@ static void pp_ad_calc_worker(struct work_struct *work) if (calc_done) { ad->last_str = 0xFF & readl_relaxed(base + MDSS_MDP_REG_AD_STR_OUT); if (MDSS_AD_RUNNING_AUTO_BL(ad)) { bl = 0xFFFF & readl_relaxed(base + MDSS_MDP_REG_AD_BL_OUT); if (ad->state & PP_AD_STATE_BL_LIN) { bl = bl >> ad->bl_bright_shift; bl = min_t(u32, bl, (AD_BL_LIN_LEN-1)); bl = ad->bl_lin_inv[bl]; bl = bl << ad->bl_bright_shift; } pr_debug("calc bl = %d\n", bl); ad->last_str |= bl << 16; mutex_lock(&ad->bl_mfd->bl_lock); if (ad->bl_mfd->bl_level) mdss_fb_set_backlight(ad->bl_mfd, bl); mutex_unlock(&ad->bl_mfd->bl_lock); } if (MDSS_AD_RUNNING_AUTO_BL(ad)) pr_err("AD auto backlight no longer supported.\n"); pr_debug("calc_str = %d, calc_itr %d\n", ad->last_str & 0xFF, ad->calc_itr); Loading Loading @@ -4980,25 +5042,17 @@ static void pp_ad_cfg_lut(char __iomem *addr, u32 *data) addr + ((PP_AD_LUT_LEN - 1) * 2)); } static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, struct msm_fb_data_type *mfd) /* must call this function from within ad->lock */ static int pp_ad_attenuate_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out) { u32 shift = 0, ratio_temp = 0; u32 n, lut_interval, bl_att; int ret = -1; struct mdss_ad_info *ad; if (bl < 0) { pr_err("Invalid backlight input\n"); return ret; return -EINVAL; } ret = mdss_mdp_get_ad(mfd, &ad); if (ret || !ad || !ad->bl_mfd || !ad->bl_mfd->panel_info || !ad->bl_mfd->panel_info->bl_max || !ad->bl_att_lut) { 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, Loading @@ -5013,7 +5067,7 @@ static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, n = bl >> shift; if (n >= (AD_BL_ATT_LUT_LEN - 1)) { pr_err("Invalid index for BL attenuation: %d.\n", n); return ret; return -EINVAL; } 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) * Loading @@ -5036,6 +5090,63 @@ static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, return 0; } /* must call this function from within ad->lock */ static int pp_ad_linearize_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out, int inv) { u32 n; int ret = -EINVAL; if (bl < 0 || bl > ad->bl_mfd->panel_info->bl_max) { pr_err("Invalid backlight input: bl = %d, bl_max = %d\n", bl, ad->bl_mfd->panel_info->bl_max); return -EINVAL; } pr_debug("bl_in = %d, inv = %d\n", bl, inv); /* 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 linearization = %d\n", bl); n = bl * (AD_BL_LIN_LEN - 1) / MDSS_MDP_AD_BL_SCALE; pr_debug("n = %d\n", n); if (n > (AD_BL_LIN_LEN - 1)) { pr_err("Invalid index for BL linearization: %d.\n", n); return ret; } else if (n == (AD_BL_LIN_LEN - 1)) { if (inv == MDP_PP_AD_BL_LINEAR_INV) *bl_out = ad->bl_lin_inv[n]; else if (inv == MDP_PP_AD_BL_LINEAR) *bl_out = ad->bl_lin[n]; } else { /* linear piece-wise interpolation */ if (inv == MDP_PP_AD_BL_LINEAR_INV) { *bl_out = bl * (AD_BL_LIN_LEN - 1) * (ad->bl_lin_inv[n + 1] - ad->bl_lin_inv[n]) / MDSS_MDP_AD_BL_SCALE - n * (ad->bl_lin_inv[n + 1] - ad->bl_lin_inv[n]) + ad->bl_lin_inv[n]; } else if (inv == MDP_PP_AD_BL_LINEAR) { *bl_out = bl * (AD_BL_LIN_LEN - 1) * (ad->bl_lin[n + 1] - ad->bl_lin[n]) / MDSS_MDP_AD_BL_SCALE - n * (ad->bl_lin[n + 1] - ad->bl_lin[n]) + ad->bl_lin[n]; } } pr_debug("After linearization = %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) { u32 i; Loading Loading
drivers/video/msm/mdss/mdss_fb.c +35 −28 Original line number Diff line number Diff line Loading @@ -720,6 +720,7 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->bl_level = 0; mfd->bl_scale = 1024; mfd->bl_min_lvl = 30; mfd->ad_bl_level = 0; mfd->fb_imgType = MDP_RGBA_8888; mfd->pdev = pdev; Loading Loading @@ -1054,10 +1055,9 @@ static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl) 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; u32 temp = bkl_lvl, ad_bl; int ret = -EINVAL; bool is_bl_changed = (bkl_lvl != mfd->bl_level); bool bl_notify_needed = false; /* todo: temporary workaround to support doze mode */ if ((bkl_lvl == 0) && (mfd->doze_mode)) { Loading @@ -1077,12 +1077,18 @@ 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) { ret = (*mfd->mdp.ad_attenuate_bl)(bkl_lvl, &temp, mfd); if (ret) pr_err("Failed to attenuate BL\n"); if (mfd->mdp.ad_calc_bl) { if (mfd->ad_bl_level == 0) mfd->ad_bl_level = temp; ad_bl = mfd->ad_bl_level; ret = (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp, &ad_bl); if ((!ret) && (mfd->ad_bl_level != ad_bl) && mfd->mdp.ad_invalidate_input) { mfd->ad_bl_level = ad_bl; (*mfd->mdp.ad_invalidate_input)(mfd); bl_notify_needed = true; } } if (!IS_CALIB_MODE_BL(mfd)) mdss_fb_scale_bl(mfd, &temp); /* Loading @@ -1095,20 +1101,14 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl) */ if (mfd->bl_level_scaled == temp) { mfd->bl_level = bkl_lvl; return; } } else { pr_debug("backlight sent to panel :%d\n", temp); pdata->set_backlight(pdata, temp); mfd->bl_level = bkl_lvl; mfd->bl_level_scaled = temp; 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 */ update_ad_input(mfd); mutex_lock(&mfd->bl_lock); bl_notify_needed = true; } if (bl_notify_needed) mdss_fb_bl_update_notify(mfd); } } Loading @@ -1118,6 +1118,7 @@ void mdss_fb_update_backlight(struct msm_fb_data_type *mfd) struct mdss_panel_data *pdata; int ret = 0; u32 temp; u32 ad_bl; if (!mfd->unset_bl_level) return; Loading @@ -1127,16 +1128,22 @@ void mdss_fb_update_backlight(struct msm_fb_data_type *mfd) if ((pdata) && (pdata->set_backlight)) { mfd->bl_level = mfd->unset_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"); if (mfd->mdp.ad_calc_bl) { if (mfd->ad_bl_level == 0) mfd->ad_bl_level = temp; ad_bl = mfd->ad_bl_level; ret = (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp, &ad_bl); if ((!ret) && (mfd->ad_bl_level != ad_bl) && mfd->mdp.ad_invalidate_input) { mfd->ad_bl_level = ad_bl; (*mfd->mdp.ad_invalidate_input)(mfd); } } pdata->set_backlight(pdata, temp); mfd->bl_level_scaled = mfd->unset_bl_level; mfd->bl_updated = 1; mdss_fb_bl_update_notify(mfd); } } mutex_unlock(&mfd->bl_lock); Loading
drivers/video/msm/mdss/mdss_fb.h +7 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif #define MDP_PP_AD_BL_LINEAR 0x0 #define MDP_PP_AD_BL_LINEAR_INV 0x1 /** * enum mdp_notify_event - Different frame events to indicate frame update state * Loading Loading @@ -147,9 +150,9 @@ struct msm_mdp_interface { int (*lut_update)(struct msm_fb_data_type *mfd, struct fb_cmap *cmap); 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 (*ad_invalidate_input)(struct msm_fb_data_type *mfd); int (*ad_calc_bl)(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out); 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); Loading Loading @@ -219,6 +222,7 @@ struct msm_fb_data_type { int ext_ad_ctrl; u32 ext_bl_ctrl; u32 calib_mode; u32 ad_bl_level; u32 bl_level; u32 bl_scale; u32 bl_min_lvl; Loading
drivers/video/msm/mdss/mdss_mdp.h +1 −1 Original line number Diff line number Diff line Loading @@ -354,7 +354,6 @@ struct mdss_ad_info { u32 last_bl; u32 bl_data; u32 calc_itr; uint32_t bl_bright_shift; uint32_t bl_lin[AD_BL_LIN_LEN]; uint32_t bl_lin_inv[AD_BL_LIN_LEN]; uint32_t bl_att_lut[AD_BL_ATT_LUT_LEN]; Loading Loading @@ -805,6 +804,7 @@ int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx, int mdss_mdp_pp_init(struct device *dev); void mdss_mdp_pp_term(struct device *dev); int mdss_mdp_pp_override_pu(int enable); int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num); Loading
drivers/video/msm/mdss/mdss_mdp_overlay.c +2 −0 Original line number Diff line number Diff line Loading @@ -3893,6 +3893,8 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) } } if (mdss_mdp_pp_overlay_init(mfd)) pr_warn("Failed to initialize pp overlay data.\n"); return rc; init_fail: kfree(mdp5_data); Loading
drivers/video/msm/mdss/mdss_mdp_pp.c +218 −107 Original line number Diff line number Diff line Loading @@ -395,10 +395,11 @@ static int pp_read_pa_v2_regs(char __iomem *addr, u32 disp_num); static void pp_read_pa_mem_col_regs(char __iomem *addr, struct mdp_pa_mem_col_cfg *mem_col_cfg); static struct msm_fb_data_type *mdss_get_mfd_from_index(int index); static int mdss_ad_init_checks(struct msm_fb_data_type *mfd); static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, struct mdss_ad_info **ad); static int pp_update_ad_input(struct msm_fb_data_type *mfd); static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd); static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t); static void pp_ad_cfg_write(struct mdss_mdp_ad *ad_hw, struct mdss_ad_info *ad); Loading @@ -412,8 +413,11 @@ 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 int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, struct msm_fb_data_type *mfd); static int pp_ad_attenuate_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out); static int pp_ad_linearize_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out, int inv); static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out); 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); Loading Loading @@ -1876,6 +1880,7 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) struct pp_sts_type pp_sts; struct mdss_ad_info *ad; struct mdss_data_type *mdata = ctl->mdata; struct msm_fb_data_type *bl_mfd; if (!mdata) return -EPERM; Loading @@ -1885,36 +1890,6 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) return -EINVAL; } disp_num = ctl->mfd->index; if (dspp_num < mdata->nad_cfgs) { ret = mdss_mdp_get_ad(ctl->mfd, &ad); if (ret) return ret; if (PP_AD_STATE_CFG & ad->state) pp_ad_cfg_write(&mdata->ad_off[dspp_num], ad); if (PP_AD_STATE_INIT & ad->state) pp_ad_init_write(&mdata->ad_off[dspp_num], ad, ctl); if ((PP_AD_STATE_DATA & ad->state) && (ad->sts & PP_STS_ENABLE)) { bl = ad->bl_mfd->bl_level; ad->last_bl = bl; if (ad->state & PP_AD_STATE_BL_LIN) { bl = ad->bl_lin[bl >> ad->bl_bright_shift]; bl = bl << ad->bl_bright_shift; ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd); if (ret) pr_err("Failed to attenuate BL\n"); } 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) ctl->add_vsync_handler(ctl, &ad->handle); } pp_sts = mdss_pp_res->pp_disp_sts[disp_num]; if (pp_sts.pa_sts & PP_STS_ENABLE) { Loading Loading @@ -1983,6 +1958,47 @@ int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 dspp_num) mdss_pp_res->pp_disp_flags[disp_num] |= flags; mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_RESUME_COMMIT; if (dspp_num < mdata->nad_cfgs) { ret = mdss_mdp_get_ad(ctl->mfd, &ad); if (ret) { pr_warn("Failed to get AD info, err = %d\n", ret); return ret; } if (ctl->mfd->panel_info->type == WRITEBACK_PANEL) { bl_mfd = mdss_get_mfd_from_index(0); if (!bl_mfd) { ret = -EINVAL; pr_warn("Failed to get primary FB bl handle, err = %d\n", ret); return ret; } } else { bl_mfd = ctl->mfd; } mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->ad_bl_level; mutex_unlock(&bl_mfd->bl_lock); mutex_lock(&ad->lock); if (PP_AD_STATE_CFG & ad->state) pp_ad_cfg_write(&mdata->ad_off[dspp_num], ad); if (PP_AD_STATE_INIT & ad->state) pp_ad_init_write(&mdata->ad_off[dspp_num], ad, ctl); if ((PP_AD_STATE_DATA & ad->state) && (ad->sts & PP_STS_ENABLE)) { ad->last_bl = 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) ctl->add_vsync_handler(ctl, &ad->handle); mutex_unlock(&ad->lock); } return 0; } Loading Loading @@ -2072,6 +2088,80 @@ int mdss_mdp_pp_override_pu(int enable) return 0; } int mdss_mdp_pp_overlay_init(struct msm_fb_data_type *mfd) { if (!mfd) { pr_err("Invalid mfd.\n"); return -EPERM; } mfd->mdp.ad_invalidate_input = pp_ad_invalidate_input; mfd->mdp.ad_calc_bl = pp_ad_calc_bl; return 0; } int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, int *ad_bl_out) { int ret = -1; int temp = bl_in; struct mdss_ad_info *ad; ret = mdss_mdp_get_ad(mfd, &ad); if (ret == -ENODEV) { pr_debug("AD not supported on device.\n"); return ret; } else if (ret || !ad) { pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", ret, ad); return ret; } mutex_lock(&ad->lock); if (!(ad->state & PP_AD_STATE_RUN)) { pr_debug("AD is not running.\n"); mutex_unlock(&ad->lock); return -EPERM; } if (!ad->bl_mfd || !ad->bl_mfd->panel_info || !ad->bl_att_lut) { pr_err("Invalid ad info: bl_mfd = 0x%p, ad->bl_mfd->panel_info = 0x%p, bl_att_lut = 0x%p\n", ad->bl_mfd, (!ad->bl_mfd) ? NULL : ad->bl_mfd->panel_info, ad->bl_att_lut); mutex_unlock(&ad->lock); return -EINVAL; } ret = pp_ad_linearize_bl(ad, bl_in, &temp, MDP_PP_AD_BL_LINEAR); if (ret) { pr_err("Failed to linearize BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } ret = pp_ad_attenuate_bl(ad, temp, &temp); if (ret) { pr_err("Failed to attenuate BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } *ad_bl_out = temp; ret = pp_ad_linearize_bl(ad, temp, &temp, MDP_PP_AD_BL_LINEAR_INV); if (ret) { pr_err("Failed to inverse linearize BL: %d\n", ret); mutex_unlock(&ad->lock); return ret; } *bl_out = temp; mutex_unlock(&ad->lock); return 0; } static int pp_get_dspp_num(u32 disp_num, u32 *dspp_num) { int i; Loading Loading @@ -4232,34 +4322,42 @@ static int mdss_mdp_get_ad(struct msm_fb_data_type *mfd, return ret; } static int pp_update_ad_input(struct msm_fb_data_type *mfd) /* must call this function from within ad->lock */ static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd) { int ret; struct mdss_ad_info *ad; struct mdss_ad_input input; struct mdss_mdp_ctl *ctl; if (!mfd) if (!mfd) { pr_err("Invalid mfd\n"); return -EINVAL; } ctl = mfd_to_ctl(mfd); if (!ctl) if (!ctl) { pr_err("Invalid ctl\n"); return -EINVAL; } ret = mdss_mdp_get_ad(mfd, &ad); if (ret) return ret; if (!ad || ad->cfg.mode == MDSS_AD_MODE_AUTO_BL) if (ret || !ad) { pr_err("Fail to get ad: ret = %d, ad = 0x%p\n", ret, ad); return -EINVAL; } pr_debug("AD backlight level changed (%d), trigger update to AD\n", mfd->ad_bl_level); if (ad->cfg.mode == MDSS_AD_MODE_AUTO_BL) { pr_err("AD auto backlight no longer supported.\n"); return -EINVAL; } pr_debug("backlight level changed (%d), trigger update to AD\n", mfd->bl_level); input.mode = ad->cfg.mode; if (MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode, MDSS_AD_INPUT_AMBIENT)) input.in.amb_light = ad->ad_data; else input.in.strength = ad->ad_data; /* call to ad_input will trigger backlight read */ return mdss_mdp_ad_input(mfd, &input, 0); if (ad->state & PP_AD_STATE_RUN) { ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; ad->sts |= PP_AD_STS_DIRTY_DATA; } return 0; } int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, Loading @@ -4268,7 +4366,7 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, struct mdss_ad_info *ad; struct msm_fb_data_type *bl_mfd; int lin_ret = -1, inv_ret = -1, att_ret = -1, ret = 0; u32 ratio_temp, shift = 0, last_ops; u32 last_ops; ret = mdss_mdp_get_ad(mfd, &ad); if (ret) Loading Loading @@ -4301,12 +4399,6 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd, sizeof(uint32_t)); if (lin_ret || inv_ret) ret = -ENOMEM; ratio_temp = mfd->panel_info->bl_max / AD_BL_LIN_LEN; while (ratio_temp > 0) { ratio_temp = ratio_temp >> 1; shift++; } ad->bl_bright_shift = shift; } else { ret = -EINVAL; } Loading Loading @@ -4406,7 +4498,7 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd, goto error; } ad->ad_data_mode = MDSS_AD_INPUT_AMBIENT; pr_debug("ambient = %d", input->in.amb_light); pr_debug("ambient = %d\n", input->in.amb_light); ad->ad_data = input->in.amb_light; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; Loading @@ -4425,7 +4517,7 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd, goto error; } ad->ad_data_mode = MDSS_AD_INPUT_STRENGTH; pr_debug("strength = %d", input->in.strength); pr_debug("strength = %d\n", input->in.strength); ad->ad_data = input->in.strength; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; Loading Loading @@ -4725,6 +4817,10 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) mdata = mfd_to_mdata(mfd); mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->ad_bl_level; mutex_unlock(&bl_mfd->bl_lock); mutex_lock(&ad->lock); if (ad->sts != last_sts || ad->state != last_state) { last_sts = ad->sts; Loading @@ -4741,26 +4837,16 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) */ ad->sts &= ~PP_AD_STS_DIRTY_DATA; ad->state |= PP_AD_STATE_DATA; mutex_lock(&bl_mfd->bl_lock); bl = bl_mfd->bl_level; pr_debug("dirty data, last_bl = %d\n", ad->last_bl); if ((ad->cfg.mode == MDSS_AD_MODE_AUTO_STR) && (ad->last_bl != bl)) { ad->last_bl = bl; ad->calc_itr = ad->cfg.stab_itr; ad->sts |= PP_AD_STS_DIRTY_VSYNC; if (ad->state & PP_AD_STATE_BL_LIN) { bl = ad->bl_lin[bl >> ad->bl_bright_shift]; bl = bl << ad->bl_bright_shift; ret = pp_ad_attenuate_bl(bl, &bl, ad->mfd); if (ret) pr_err("Failed to attenuate BL\n"); } 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; } Loading Loading @@ -4804,14 +4890,9 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) bypass = 0; ad->reg_sts |= PP_AD_STS_DIRTY_ENABLE; ad->state |= PP_AD_STATE_RUN; mutex_lock(&bl_mfd->bl_lock); 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); } else { if (ad->state & PP_AD_STATE_RUN) { ad->reg_sts = PP_AD_STS_DIRTY_ENABLE; Loading @@ -4822,7 +4903,6 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) ad->state &= !PP_AD_STATE_CFG; ad->state &= !PP_AD_STATE_DATA; ad->state &= !PP_AD_STATE_BL_LIN; ad->bl_bright_shift = 0; ad->ad_data = 0; ad->ad_data_mode = 0; ad->last_bl = 0; Loading @@ -4836,12 +4916,8 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd) AD_BL_ATT_LUT_LEN); memset(&ad->init, 0, sizeof(struct mdss_ad_init)); 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); } ad->state &= ~PP_AD_STATE_RUN; } Loading Loading @@ -4883,7 +4959,7 @@ static void pp_ad_calc_worker(struct work_struct *work) struct msm_fb_data_type *mfd, *bl_mfd; struct mdss_data_type *mdata; char __iomem *base; u32 bl, calc_done = 0; u32 calc_done = 0; ad = container_of(work, struct mdss_ad_info, calc_work); mutex_lock(&ad->lock); Loading Loading @@ -4925,22 +5001,8 @@ static void pp_ad_calc_worker(struct work_struct *work) if (calc_done) { ad->last_str = 0xFF & readl_relaxed(base + MDSS_MDP_REG_AD_STR_OUT); if (MDSS_AD_RUNNING_AUTO_BL(ad)) { bl = 0xFFFF & readl_relaxed(base + MDSS_MDP_REG_AD_BL_OUT); if (ad->state & PP_AD_STATE_BL_LIN) { bl = bl >> ad->bl_bright_shift; bl = min_t(u32, bl, (AD_BL_LIN_LEN-1)); bl = ad->bl_lin_inv[bl]; bl = bl << ad->bl_bright_shift; } pr_debug("calc bl = %d\n", bl); ad->last_str |= bl << 16; mutex_lock(&ad->bl_mfd->bl_lock); if (ad->bl_mfd->bl_level) mdss_fb_set_backlight(ad->bl_mfd, bl); mutex_unlock(&ad->bl_mfd->bl_lock); } if (MDSS_AD_RUNNING_AUTO_BL(ad)) pr_err("AD auto backlight no longer supported.\n"); pr_debug("calc_str = %d, calc_itr %d\n", ad->last_str & 0xFF, ad->calc_itr); Loading Loading @@ -4980,25 +5042,17 @@ static void pp_ad_cfg_lut(char __iomem *addr, u32 *data) addr + ((PP_AD_LUT_LEN - 1) * 2)); } static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, struct msm_fb_data_type *mfd) /* must call this function from within ad->lock */ static int pp_ad_attenuate_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out) { u32 shift = 0, ratio_temp = 0; u32 n, lut_interval, bl_att; int ret = -1; struct mdss_ad_info *ad; if (bl < 0) { pr_err("Invalid backlight input\n"); return ret; return -EINVAL; } ret = mdss_mdp_get_ad(mfd, &ad); if (ret || !ad || !ad->bl_mfd || !ad->bl_mfd->panel_info || !ad->bl_mfd->panel_info->bl_max || !ad->bl_att_lut) { 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, Loading @@ -5013,7 +5067,7 @@ static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, n = bl >> shift; if (n >= (AD_BL_ATT_LUT_LEN - 1)) { pr_err("Invalid index for BL attenuation: %d.\n", n); return ret; return -EINVAL; } 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) * Loading @@ -5036,6 +5090,63 @@ static int pp_ad_attenuate_bl(u32 bl, u32 *bl_out, return 0; } /* must call this function from within ad->lock */ static int pp_ad_linearize_bl(struct mdss_ad_info *ad, u32 bl, u32 *bl_out, int inv) { u32 n; int ret = -EINVAL; if (bl < 0 || bl > ad->bl_mfd->panel_info->bl_max) { pr_err("Invalid backlight input: bl = %d, bl_max = %d\n", bl, ad->bl_mfd->panel_info->bl_max); return -EINVAL; } pr_debug("bl_in = %d, inv = %d\n", bl, inv); /* 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 linearization = %d\n", bl); n = bl * (AD_BL_LIN_LEN - 1) / MDSS_MDP_AD_BL_SCALE; pr_debug("n = %d\n", n); if (n > (AD_BL_LIN_LEN - 1)) { pr_err("Invalid index for BL linearization: %d.\n", n); return ret; } else if (n == (AD_BL_LIN_LEN - 1)) { if (inv == MDP_PP_AD_BL_LINEAR_INV) *bl_out = ad->bl_lin_inv[n]; else if (inv == MDP_PP_AD_BL_LINEAR) *bl_out = ad->bl_lin[n]; } else { /* linear piece-wise interpolation */ if (inv == MDP_PP_AD_BL_LINEAR_INV) { *bl_out = bl * (AD_BL_LIN_LEN - 1) * (ad->bl_lin_inv[n + 1] - ad->bl_lin_inv[n]) / MDSS_MDP_AD_BL_SCALE - n * (ad->bl_lin_inv[n + 1] - ad->bl_lin_inv[n]) + ad->bl_lin_inv[n]; } else if (inv == MDP_PP_AD_BL_LINEAR) { *bl_out = bl * (AD_BL_LIN_LEN - 1) * (ad->bl_lin[n + 1] - ad->bl_lin[n]) / MDSS_MDP_AD_BL_SCALE - n * (ad->bl_lin[n + 1] - ad->bl_lin[n]) + ad->bl_lin[n]; } } pr_debug("After linearization = %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) { u32 i; Loading