msm: mdss: Add backlight attenuation mechanism in AD auto strength mode
AD backlight attenuation provides the ability to modulate backlight based
on calibration before feeding it to AD core for strength computation.
Change-Id: Iea011807b25882463b1142e17324fa0509007aa4
Signed-off-by: Ping Li <quicpingli@codeaurora.org>
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 9d200b9..4d68d03b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -319,6 +319,7 @@
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];
};
struct pp_sts_type {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index f706700..5c9ad9c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -396,6 +396,7 @@
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_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);
@@ -1648,6 +1649,7 @@
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);
}
ad->bl_data = bl;
pp_ad_input_write(&mdata->ad_off[dspp_num], ad);
@@ -3781,7 +3783,7 @@
{
struct mdss_ad_info *ad;
struct msm_fb_data_type *bl_mfd;
- int lin_ret = -1, inv_ret = -1, ret = 0;
+ int lin_ret = -1, inv_ret = -1, att_ret = -1, ret = 0;
u32 ratio_temp, shift = 0, last_ops;
ret = mdss_mdp_get_ad(mfd, &ad);
@@ -3830,6 +3832,23 @@
} else
ad->state |= PP_AD_STATE_BL_LIN;
+ if ((init_cfg->params.init.bl_att_len == AD_BL_ATT_LUT_LEN) &&
+ (init_cfg->params.init.bl_att_lut)) {
+ att_ret = copy_from_user(&ad->bl_att_lut,
+ init_cfg->params.init.bl_att_lut,
+ init_cfg->params.init.bl_att_len *
+ sizeof(uint32_t));
+ if (att_ret)
+ ret = -ENOMEM;
+ } else {
+ ret = -EINVAL;
+ }
+ if (ret) {
+ ad->state &= ~PP_AD_STATE_BL_LIN;
+ goto ad_config_exit;
+ } else
+ ad->state |= PP_AD_STATE_BL_LIN;
+
ad->sts |= PP_AD_STS_DIRTY_INIT;
} else if (init_cfg->ops & MDP_PP_AD_CFG) {
memcpy(&ad->cfg, &init_cfg->params.cfg,
@@ -4256,6 +4275,7 @@
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);
}
ad->bl_data = bl;
}
@@ -4330,6 +4350,8 @@
AD_BL_LIN_LEN);
memset(&ad->bl_lin_inv, 0, sizeof(uint32_t) *
AD_BL_LIN_LEN);
+ memset(&ad->bl_att_lut, 0, sizeof(uint32_t) *
+ 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);
@@ -4474,6 +4496,30 @@
addr + ((PP_AD_LUT_LEN - 1) * 2));
}
+static u32 pp_ad_attenuate_bl(u32 bl, struct mdss_ad_info *ad)
+{
+ u32 shift = 0, ratio_temp = 0;
+ u32 n, lut_interval, bl_att, out;
+
+ ratio_temp = ad->cfg.backlight_max / (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);
+ bl_att = ad->bl_att_lut[n] + (bl - lut_interval * n) *
+ (ad->bl_att_lut[n + 1] - ad->bl_att_lut[n]) /
+ lut_interval;
+ if (ad->init.alpha_base)
+ out = (ad->init.alpha * bl_att +
+ (ad->init.alpha_base - ad->init.alpha) * bl) /
+ ad->init.alpha_base;
+ else
+ out = bl;
+ return out;
+}
+
int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_offsets)
{
u32 i;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 45975f9..2aaceb2 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -811,6 +811,7 @@
#define MDSS_MAX_BL_BRIGHTNESS 255
#define AD_BL_LIN_LEN 256
+#define AD_BL_ATT_LUT_LEN 33
#define MDSS_AD_MODE_AUTO_BL 0x0
#define MDSS_AD_MODE_AUTO_STR 0x1
@@ -839,9 +840,13 @@
uint16_t frame_h;
uint8_t logo_v;
uint8_t logo_h;
+ uint32_t alpha;
+ uint32_t alpha_base;
uint32_t bl_lin_len;
+ uint32_t bl_att_len;
uint32_t *bl_lin;
uint32_t *bl_lin_inv;
+ uint32_t *bl_att_lut;
};
#define MDSS_AD_BL_CTRL_MODE_EN 1