Merge "msm: mdss: Disable the PP features if partial update feature is enabled"
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index a72779d..6e2a7f5 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -41,6 +41,7 @@
{
int ret;
u32 duty;
+ u32 period_ns;
if (ctrl->pwm_bl == NULL) {
pr_err("%s: no PWM\n", __func__);
@@ -69,10 +70,23 @@
ctrl->pwm_enabled = 0;
}
- ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
- if (ret) {
- pr_err("%s: pwm_config_us() failed err=%d.\n", __func__, ret);
- return;
+ if (ctrl->pwm_period >= USEC_PER_SEC) {
+ ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
+ if (ret) {
+ pr_err("%s: pwm_config_us() failed err=%d.\n",
+ __func__, ret);
+ return;
+ }
+ } else {
+ period_ns = ctrl->pwm_period * NSEC_PER_USEC;
+ ret = pwm_config(ctrl->pwm_bl,
+ level * period_ns / ctrl->bklt_max,
+ period_ns);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n",
+ __func__, ret);
+ return;
+ }
}
ret = pwm_enable(ctrl->pwm_bl);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 95d403b..bf91a29 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -884,6 +884,8 @@
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)) {
@@ -896,6 +898,12 @@
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");
+ }
+
mfd->bl_level_prev_scaled = mfd->bl_level_scaled;
if (!IS_CALIB_MODE_BL(mfd))
mdss_fb_scale_bl(mfd, &temp);
@@ -911,31 +919,42 @@
mfd->bl_level = bkl_lvl;
return;
}
+ 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) {
+ 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);
- mdss_fb_bl_update_notify(mfd);
mutex_lock(&mfd->bl_lock);
}
+ mdss_fb_bl_update_notify(mfd);
}
}
void mdss_fb_update_backlight(struct msm_fb_data_type *mfd)
{
struct mdss_panel_data *pdata;
+ int ret = 0;
+ u32 temp;
mutex_lock(&mfd->bl_lock);
if (mfd->unset_bl_level && !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;
}
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index fc53c55..1ab0fb7 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -123,6 +123,8 @@
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);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index d52a44a..0b67a6d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -379,6 +379,7 @@
#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
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index ad8e8a6..92be2ad 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -399,13 +399,27 @@
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);
static u32 last_sts, last_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)
{
@@ -1749,9 +1763,13 @@
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)
@@ -3905,6 +3923,11 @@
return -ENODEV;
}
+ if (ad_mfd->panel_info->type == DTV_PANEL) {
+ pr_debug("AD not supported on external display\n");
+ return ret;
+ }
+
mixer_num = mdss_mdp_get_ctl_mixers(ad_mfd->index, mixer_id);
if (!mixer_num) {
pr_debug("no mixers connected, %d", mixer_num);
@@ -4049,11 +4072,7 @@
} 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;
}
@@ -4176,7 +4195,7 @@
if (!ret) {
if (wait) {
mutex_lock(&ad->lock);
- init_completion(&ad->comp);
+ INIT_COMPLETION(ad->comp);
mutex_unlock(&ad->lock);
}
if (wait) {
@@ -4315,10 +4334,7 @@
frame_end = 0xFFFF;
procs_start = 0x0;
procs_end = 0xFFFF;
- if (split_mode)
- tile_ctrl = 0x0;
- else
- tile_ctrl = 0x1;
+ tile_ctrl = 0x0;
}
@@ -4471,9 +4487,13 @@
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;
@@ -4523,6 +4543,7 @@
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);
@@ -4552,6 +4573,7 @@
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);
@@ -4692,28 +4714,60 @@
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 || !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,
+ 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 - 1)) {
+ 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)
@@ -4751,6 +4805,7 @@
mdata->ad_cfgs[i].last_str = 0xFFFFFFFF;
mdata->ad_cfgs[i].last_bl = 0;
mutex_init(&mdata->ad_cfgs[i].lock);
+ init_completion(&mdata->ad_cfgs[i].comp);
mdata->ad_cfgs[i].handle.vsync_handler = pp_ad_vsync_handler;
mdata->ad_cfgs[i].handle.cmd_post_flush = true;
INIT_WORK(&mdata->ad_cfgs[i].calc_work, pp_ad_calc_worker);