diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index a5368cdf2254..19a37d076048 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -459,6 +459,7 @@ struct mdss_data_type { u32 nmax_concurrent_ad_hw; struct workqueue_struct *ad_calc_wq; u32 ad_debugen; + bool mem_retain; struct mdss_intr hist_intr; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 81e3438befca..610c574b9d3f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1345,7 +1345,12 @@ int mdss_iommu_ctrl(int enable) return mdata->iommu_ref_cnt; } -static void mdss_mdp_memory_retention_enter(void) +#define MEM_RETAIN_ON 1 +#define MEM_RETAIN_OFF 0 +#define PERIPH_RETAIN_ON 1 +#define PERIPH_RETAIN_OFF 0 + +static void mdss_mdp_memory_retention_ctrl(bool mem_ctrl, bool periph_ctrl) { struct clk *mdss_mdp_clk = NULL; struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE); @@ -1366,49 +1371,35 @@ static void mdss_mdp_memory_retention_enter(void) __mdss_mdp_reg_access_clk_enable(mdata, true); if (mdss_mdp_clk) { - clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM); - clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET); - clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH); - } + if (mem_ctrl) + clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM); + else + clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_MEM); - if (mdss_mdp_lut_clk) { - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM); - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET); - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_PERIPH); - } - __mdss_mdp_reg_access_clk_enable(mdata, false); -} - -static void mdss_mdp_memory_retention_exit(void) -{ - struct clk *mdss_mdp_clk = NULL; - struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE); - struct clk *mdss_mdp_lut_clk = NULL; - struct clk *mdp_lut_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_LUT); - struct mdss_data_type *mdata = mdss_mdp_get_mdata(); - - if (mdp_vote_clk) { - if (test_bit(MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, - mdata->mdss_caps_map)) { - mdss_mdp_clk = mdp_vote_clk; - mdss_mdp_lut_clk = mdp_lut_vote_clk; + if (periph_ctrl) { + clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH); + clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_CLEAR); } else { - mdss_mdp_clk = clk_get_parent(mdp_vote_clk); - mdss_mdp_lut_clk = clk_get_parent(mdp_lut_vote_clk); + clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET); + clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH); } } - __mdss_mdp_reg_access_clk_enable(mdata, true); - if (mdss_mdp_clk) { - clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM); - clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH); - clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_CLEAR); - } - if (mdss_mdp_lut_clk) { - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM); - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH); - clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_CLEAR); + if (mem_ctrl) + clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM); + else + clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_MEM); + + if (periph_ctrl) { + clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH); + clk_set_flags(mdss_mdp_lut_clk, + CLKFLAG_PERIPH_OFF_CLEAR); + } else { + clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET); + clk_set_flags(mdss_mdp_lut_clk, + CLKFLAG_NORETAIN_PERIPH); + } } __mdss_mdp_reg_access_clk_enable(mdata, false); } @@ -1441,17 +1432,21 @@ static int mdss_mdp_idle_pc_restore(void) mdss_hw_init(mdata); mdss_iommu_ctrl(0); - /** - * sleep 10 microseconds to make sure AD auto-reinitialization - * is done - */ - udelay(10); - mdss_mdp_memory_retention_exit(); - mdss_mdp_ctl_restore(true); mdata->idle_pc = false; end: + if (mdata->mem_retain) { + /** + * sleep 10 microseconds to make sure AD auto-reinitialization + * is done + */ + udelay(10); + mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON, + PERIPH_RETAIN_ON); + mdata->mem_retain = false; + } + mutex_unlock(&mdp_fs_idle_pc_lock); return rc; } @@ -4910,10 +4905,12 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) * Turning off GDSC while overlays are still * active. */ + + mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON, + PERIPH_RETAIN_OFF); mdata->idle_pc = true; pr_debug("idle pc. active overlays=%d\n", active_cnt); - mdss_mdp_memory_retention_enter(); } else { /* * Advise RPM to turn MMSS GDSC off during @@ -4925,7 +4922,11 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) mdss_mdp_cx_ctrl(mdata, false); mdss_mdp_batfet_ctrl(mdata, false); + mdss_mdp_memory_retention_ctrl( + MEM_RETAIN_OFF, + PERIPH_RETAIN_OFF); } + mdata->mem_retain = true; if (mdata->en_svs_high) mdss_mdp_config_cx_voltage(mdata, false); regulator_disable(mdata->fs);