summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorCarl Vanderlip <carlv@codeaurora.org>2013-10-18 15:34:20 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:23:23 -0700
commit3a5af245d73ecb7d69c6dfe8260644cb522ae4e3 (patch)
tree42a9e207331f2b700feea6c6b1b5548ce618012a /drivers/video/fbdev
parentf974b39842413dd88c71a0e0332c44e7b06f8a7b (diff)
msm: mdss: Relocate Assertive Display register access
Move the register writes for Assertive Display (AD) into the dspp_setup function. This separates the state of AD from the configuration of the hardware and adds to the implementation of dual pipe AD feature. Change-Id: I9f21f9461b3d4ae3c29ad52e17ad33d8e6e4b904 Signed-off-by: Carl Vanderlip <carlv@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c60
2 files changed, 48 insertions, 13 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index b328aae91c5b..07ccb652bb8b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -285,6 +285,7 @@ struct mdss_mdp_ad {
struct mdss_ad_info {
u8 num;
u32 sts;
+ u32 reg_sts;
u32 state;
u32 ad_data;
u32 ad_data_mode;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index b605a8e0afae..d932fdb89fa8 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -373,6 +373,7 @@ static void pp_ad_init_write(struct mdss_mdp_ad *ad_hw,
struct mdss_ad_info *ad);
static void pp_ad_input_write(struct mdss_mdp_ad *ad_hw,
struct mdss_ad_info *ad);
+static void pp_ad_bypass_config(struct mdss_ad_info *ad, 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);
@@ -1388,12 +1389,14 @@ static void pp_dspp_opmode_config(struct pp_sts_type *pp_sts, u32 *opmode,
static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
{
- u32 flags, dspp_num, opmode = 0;
+ u32 ad_flags, flags, dspp_num, opmode = 0, ad_bypass;
struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
char __iomem *base, *addr;
int ret = 0;
struct mdss_data_type *mdata;
+ struct mdss_ad_info *ad = NULL;
+ struct mdss_mdp_ad *ad_hw = NULL;
struct mdss_mdp_ctl *ctl;
u32 mixer_cnt;
u32 mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
@@ -1423,15 +1426,21 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
if (dspp_num < mdata->nad_cfgs && (mixer_cnt != 2)) {
ret = mdss_mdp_ad_setup(ctl->mfd);
+ ad = &mdata->ad_cfgs[disp_num];
+ ad_flags = ad->reg_sts;
+ ad_hw = &mdata->ad_off[dspp_num];
if (ret < 0)
pr_warn("ad_setup(dspp%d) returns %d", dspp_num, ret);
+ } else {
+ ad_flags = 0;
}
+
/* call calibration specific processing here */
if (ctl->mfd->calib_mode)
goto flush_exit;
/* nothing to update */
- if ((!flags) && (!(opmode)) && (ret <= 0))
+ if ((!flags) && (!(opmode)) && (ret <= 0) && (!ad_flags))
goto dspp_exit;
ret = 0;
@@ -1485,6 +1494,20 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
pp_sts->pgc_sts |= PP_STS_ENABLE;
}
+ if (ad_hw) {
+ mutex_lock(&ad->lock);
+ ad_flags = ad->reg_sts;
+ if (ad_flags & PP_AD_STS_DIRTY_DATA)
+ pp_ad_input_write(ad_hw, ad);
+ if (ad_flags & PP_AD_STS_DIRTY_INIT)
+ pp_ad_init_write(ad_hw, ad);
+ if (ad_flags & PP_AD_STS_DIRTY_CFG)
+ pp_ad_cfg_write(ad_hw, ad);
+ pp_ad_bypass_config(ad, &ad_bypass);
+ writel_relaxed(ad_bypass, ad_hw->base);
+ mutex_unlock(&ad->lock);
+ }
+
pp_dspp_opmode_config(pp_sts, &opmode, mdata->mdp_rev);
flush_exit:
writel_relaxed(opmode, base + MDSS_MDP_REG_DSPP_OP_MODE);
@@ -1523,6 +1546,7 @@ error:
/* call only when holding and mfd->lock */
int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
{
+ struct mdss_data_type *mdata = ctl->mdata;
u32 disp_num;
if ((!ctl->mfd) || (!mdss_pp_res))
return -EINVAL;
@@ -1540,8 +1564,11 @@ int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl)
pp_dspp_setup(disp_num, ctl->mixer_right);
}
/* clear dirty flag */
- if (disp_num < MDSS_BLOCK_DISP_NUM)
+ if (disp_num < MDSS_BLOCK_DISP_NUM) {
mdss_pp_res->pp_disp_flags[disp_num] = 0;
+ if (disp_num < mdata->nad_cfgs)
+ mdata->ad_cfgs[disp_num].reg_sts = 0;
+ }
mutex_unlock(&mdss_pp_mutex);
return 0;
@@ -3823,15 +3850,21 @@ static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t)
}
#define MDSS_PP_AD_BYPASS_DEF 0x101
+static void pp_ad_bypass_config(struct mdss_ad_info *ad, u32 *opmode)
+{
+ if (ad->reg_sts & PP_STS_ENABLE)
+ *opmode = 0;
+ else
+ *opmode = MDSS_PP_AD_BYPASS_DEF;
+}
+
static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
{
int ret = 0;
struct mdss_ad_info *ad;
- struct mdss_mdp_ad *ad_hw;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct msm_fb_data_type *bl_mfd;
struct mdss_data_type *mdata;
- u32 temp;
u32 bypass = MDSS_PP_AD_BYPASS_DEF, bl;
ret = mdss_mdp_get_ad(mfd, &ad);
@@ -3846,7 +3879,6 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
}
mdata = mfd_to_mdata(mfd);
- ad_hw = &mdata->ad_off[ad->num];
mutex_lock(&ad->lock);
if (ad->sts != last_sts || ad->state != last_state) {
@@ -3879,14 +3911,14 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
ad->bl_data = bl;
}
mutex_unlock(&bl_mfd->bl_lock);
- pp_ad_input_write(ad_hw, ad);
+ ad->reg_sts |= PP_AD_STS_DIRTY_DATA;
}
if (ad->sts & PP_AD_STS_DIRTY_CFG) {
ad->sts &= ~PP_AD_STS_DIRTY_CFG;
ad->state |= PP_AD_STATE_CFG;
- pp_ad_cfg_write(ad_hw, ad);
+ ad->reg_sts |= PP_AD_STS_DIRTY_CFG;
if (!MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode, ad->ad_data_mode)) {
ad->sts &= ~PP_AD_STS_DIRTY_DATA;
@@ -3897,7 +3929,7 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
if (ad->sts & PP_AD_STS_DIRTY_INIT) {
ad->sts &= ~PP_AD_STS_DIRTY_INIT;
ad->state |= PP_AD_STATE_INIT;
- pp_ad_init_write(ad_hw, ad);
+ ad->reg_sts |= PP_AD_STS_DIRTY_INIT;
}
/* update ad screen size if it has changed since last configuration */
@@ -3910,9 +3942,7 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
ctl->height);
ad->init.frame_w = ctl->width;
ad->init.frame_h = ctl->height;
- temp = ad->init.frame_w << 16;
- temp |= ad->init.frame_h & 0xFFFF;
- writel_relaxed(temp, ad_hw->base + MDSS_MDP_REG_AD_FRAME_SIZE);
+ ad->reg_sts |= PP_AD_STS_DIRTY_INIT;
}
if ((ad->sts & PP_STS_ENABLE) && PP_AD_STATE_IS_READY(ad->state)) {
@@ -3955,7 +3985,10 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
}
ad->state &= ~PP_AD_STATE_RUN;
}
- writel_relaxed(bypass, ad_hw->base);
+ if (!bypass)
+ ad->reg_sts |= PP_STS_ENABLE;
+ else
+ ad->reg_sts &= ~PP_STS_ENABLE;
if (PP_AD_STS_DIRTY_VSYNC & ad->sts) {
pr_debug("dirty vsync, calc_itr = %d", ad->calc_itr);
@@ -4108,6 +4141,7 @@ int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_offsets)
mdata->ad_off[i].base = mdata->mdp_base + ad_offsets[i];
mdata->ad_off[i].num = i;
mdata->ad_cfgs[i].num = i;
+ mdata->ad_cfgs[i].reg_sts = 0;
mdata->ad_cfgs[i].calc_itr = 0;
mdata->ad_cfgs[i].last_str = 0xFFFFFFFF;
mdata->ad_cfgs[i].last_bl = 0;