From ceb0faf9e3f9fbe1fca54e4084d52f474622e5b8 Mon Sep 17 00:00:00 2001 From: Ping Li Date: Mon, 3 Oct 2016 15:54:31 -0700 Subject: [PATCH] msm: mdss: Update memory retention and periph control setting Previously memory retention and preiph control are only set when device enters/exits idle power collapse mode. The memory retention and periph setting will remain ON when device is actually in suspend state, which will cause unnecessary power consumption. This change updates those setting for both idle power collapse cases and suspend/resume case. With this change, the memory retention and periph will be set to OFF in suspend case to optimize power consumption. Change-Id: I1598dbc97cb9d02b946de5c9803a49d923c7edc1 Signed-off-by: Ping Li --- drivers/video/fbdev/msm/mdss.h | 1 + drivers/video/fbdev/msm/mdss_mdp.c | 93 +++++++++++++++--------------- 2 files changed, 48 insertions(+), 46 deletions(-) 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);