diff options
| author | Ujwal Patel <ujwalp@codeaurora.org> | 2015-09-22 19:02:49 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:47:30 -0700 |
| commit | 6489c0aef1e0d776ea5fc0620cb58ec439fb6bb2 (patch) | |
| tree | 019c3bf781ce9e5282e68408d5168bd95a50d7ec /drivers | |
| parent | d287993820a94b404aef44c5a299ccbfa458cb97 (diff) | |
msm: mdss: fix dsi underflow during partial updates on DSC based panels
When 2 soft slices per DSC encoder without merge is used, HW expects
certain DSI pixel clock to MDP clock ratio. If not maintained, DSI can
underflow. This happens if full-frame is split into 4 slices, thus
requiring 2 DSC encoders, 2 soft slices per encoder. Now if partial update
frame is left-only or right-only with 2 slices then normal topology would
dictate using 1 DSC encoder with 2 soft slices. However during partial
update, we don't change the pixel clock, but mdp clock is reduced because
less number of pixels needs to be processed. This changes the ratio
mentioned earlier and DSI underflows. To fix this, either we increase the
MDP clock rate or change the topology such a way that we use 2 DSC
encoders with 1 slice each. Implement later option to avoid increasing
MDP clock.
Change-Id: Ia37d8045baefcd1e680902446b4725d279db6a89
Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.c | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 46 |
3 files changed, 45 insertions, 3 deletions
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 2e07fc87701a..212b752016de 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -154,6 +154,7 @@ enum mdss_hw_quirk { MDSS_QUIRK_ROTCDP, MDSS_QUIRK_DOWNSCALE_HANG, MDSS_QUIRK_DSC_RIGHT_ONLY_PU, + MDSS_QUIRK_DSC_2SLICE_PU_THRPUT, MDSS_QUIRK_MAX, }; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 28216ab8222a..fee51562bad5 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1249,6 +1249,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->mdss_caps_map); mdss_mdp_init_default_prefill_factors(mdata); mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU); + mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT); break; case MDSS_MDP_HW_REV_105: case MDSS_MDP_HW_REV_109: diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 3a888597dcc3..9611a4e6e41f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2430,9 +2430,6 @@ static void mdss_mdp_ctl_dsc_config(struct mdss_mdp_mixer *mixer, mdss_mdp_pingpong_write(mixer->pingpong_base, MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP, data); - /* dce0_sel->pp0, dce1_sel->pp1 */ - writel_relaxed(0x0, offset + MDSS_MDP_REG_DCE_SEL); - if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0) { offset += MDSS_MDP_DSC_0_OFFSET; } else if (mixer->num == MDSS_MDP_INTF_LAYERMIXER1) { @@ -2684,6 +2681,49 @@ void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl, left_valid = true; } + if ((is_dual_lm_single_display(ctl->mfd)) && + (pinfo->partial_update_enabled) && + (pinfo->dsc_enc_total == 2) && (dsc->full_frame_slices == 4) && + (mdss_has_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT))) { + + if (mdss_mdp_is_both_lm_valid(ctl)) { + /* left + right */ + + pr_debug("full line (4 slices) or middle 2 slice partial update\n"); + writel_relaxed(0x0, + mdata->mdp_base + mdata->ppb[0].ctl_off); + writel_relaxed(0x0, + mdata->mdp_base + MDSS_MDP_REG_DCE_SEL); + } else if (mixer_left->valid_roi || mixer_right->valid_roi) { + /* left-only or right-only */ + + u32 this_frame_slices = + dsc->pic_width / dsc->slice_width; + + if (this_frame_slices == 2) { + pr_debug("2 slice parital update, use merge\n"); + + /* tandem + merge */ + mode = BIT(1) | BIT(0); + + right_valid = true; + left_valid = true; + + writel_relaxed(0x2 << 4, mdata->mdp_base + + mdata->ppb[0].ctl_off); + writel_relaxed(BIT(0), + mdata->mdp_base + MDSS_MDP_REG_DCE_SEL); + } else { + pr_debug("only one slice partial update\n"); + writel_relaxed(0x0, + mdata->mdp_base + + mdata->ppb[0].ctl_off); + writel_relaxed(0x0, + mdata->mdp_base + MDSS_MDP_REG_DCE_SEL); + } + } + } + if (left_valid) { mdss_mdp_ctl_dsc_config(mixer_left, dsc, mode, ich_reset_override); |
