diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 5a24a1995af9..5a6d7bc3ff78 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -164,6 +164,7 @@ enum mdss_hw_quirk { MDSS_QUIRK_NEED_SECURE_MAP, MDSS_QUIRK_SRC_SPLIT_ALWAYS, MDSS_QUIRK_MMSS_GDSC_COLLAPSE, + MDSS_QUIRK_MDP_CLK_SET_RATE, MDSS_QUIRK_MAX, }; @@ -289,6 +290,7 @@ struct mdss_data_type { bool en_svs_high; u32 max_mdp_clk_rate; struct mdss_util_intf *mdss_util; + unsigned long mdp_clk_rate; struct platform_device *pdev; struct dss_io_data mdss_io; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 1dae41391795..a1505226e0ad 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1139,12 +1139,31 @@ static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; struct clk *clk = mdss_mdp_get_clk(clk_idx); + struct mdss_data_type *mdata = mdss_res; if (clk) { pr_debug("clk=%d en=%d\n", clk_idx, enable); if (enable) { if (clk_idx == MDSS_CLK_MDP_VSYNC) clk_set_rate(clk, 19200000); + if (mdss_has_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE) + && (clk_idx == MDSS_CLK_MDP_CORE)) { + + if (WARN_ON(!mdata->mdp_clk_rate)) { + /* + * rate should have been set in probe + * or during clk scaling; but if this + * is not the case, set max clk rate. + */ + pr_warn("set max mdp clk rate:%u\n", + mdata->max_mdp_clk_rate); + mdss_mdp_set_clk_rate( + mdata->max_mdp_clk_rate, true); + } else { + clk_set_rate(clk, mdata->mdp_clk_rate); + } + } + ret = clk_prepare_enable(clk); } else { clk_disable_unprepare(clk); @@ -1172,7 +1191,7 @@ int mdss_mdp_vsync_clk_enable(int enable, bool locked) return ret; } -void mdss_mdp_set_clk_rate(unsigned long rate) +void mdss_mdp_set_clk_rate(unsigned long rate, bool locked) { struct mdss_data_type *mdata = mdss_res; unsigned long clk_rate; @@ -1182,7 +1201,9 @@ void mdss_mdp_set_clk_rate(unsigned long rate) min_clk_rate = max(rate, mdata->perf_tune.min_mdp_clk); if (clk) { - mutex_lock(&mdp_clk_lock); + + if (!locked) + mutex_lock(&mdp_clk_lock); if (min_clk_rate < mdata->max_mdp_clk_rate) clk_rate = clk_round_rate(clk, min_clk_rate); else @@ -1190,12 +1211,15 @@ void mdss_mdp_set_clk_rate(unsigned long rate) if (IS_ERR_VALUE(clk_rate)) { pr_err("unable to round rate err=%ld\n", clk_rate); } else if (clk_rate != clk_get_rate(clk)) { + + mdata->mdp_clk_rate = clk_rate; if (IS_ERR_VALUE(clk_set_rate(clk, clk_rate))) pr_err("clk_set_rate failed\n"); else pr_debug("mdp clk rate=%lu\n", clk_rate); } - mutex_unlock(&mdp_clk_lock); + if (!locked) + mutex_unlock(&mdp_clk_lock); } else { pr_err("mdp src clk not setup properly\n"); } @@ -1779,7 +1803,7 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata) mdss_mdp_irq_clk_register(mdata, "mnoc_clk", MDSS_CLK_MNOC_AHB); /* Setting the default clock rate to the max supported.*/ - mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate); + mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate, false); pr_debug("mdp clk rate=%ld\n", mdss_mdp_get_clk_rate(MDSS_CLK_MDP_CORE, false)); @@ -2020,6 +2044,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU); mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT); mdss_set_quirk(mdata, MDSS_QUIRK_MMSS_GDSC_COLLAPSE); + mdss_set_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE); mdata->has_wb_ubwc = true; set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map); diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index e1c3841c82de..396523ea1775 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1586,7 +1586,7 @@ u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num); void mdss_mdp_footswitch_ctrl_splash(int on); void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable); -void mdss_mdp_set_clk_rate(unsigned long min_clk_rate); +void mdss_mdp_set_clk_rate(unsigned long min_clk_rate, bool locked); unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked); int mdss_mdp_vsync_clk_enable(int enable, bool locked); void mdss_mdp_clk_ctrl(int enable); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 6b71025229a0..36c4a2ea2b47 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2374,7 +2374,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, */ if (update_clk) { ATRACE_INT("mdp_clk", clk_rate); - mdss_mdp_set_clk_rate(clk_rate); + mdss_mdp_set_clk_rate(clk_rate, false); pr_debug("update clk rate = %d HZ\n", clk_rate); }