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>
This commit is contained in:
Ujwal Patel 2015-09-22 19:02:49 -07:00 committed by David Keitel
parent d287993820
commit 6489c0aef1
3 changed files with 45 additions and 3 deletions

View file

@ -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,
};

View file

@ -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:

View file

@ -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);