diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c index c573925f448eacaf6e675e560549607498fdecf8..c0b592e500db67657df6c32ed5b59f7dc85ca734 100644 --- a/drivers/video/msm/mdss/mdss_mdp.c +++ b/drivers/video/msm/mdss/mdss_mdp.c @@ -691,16 +691,22 @@ static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) return ret; } -int mdss_mdp_vsync_clk_enable(int enable) +int mdss_mdp_vsync_clk_enable(int enable, bool locked) { int ret = 0; pr_debug("clk enable=%d\n", enable); - mutex_lock(&mdp_clk_lock); + + if (!locked) + mutex_lock(&mdp_clk_lock); + if (mdss_res->vsync_ena != enable) { mdss_res->vsync_ena = enable; ret = mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable); } - mutex_unlock(&mdp_clk_lock); + + if (!locked) + mutex_unlock(&mdp_clk_lock); + return ret; } @@ -733,14 +739,19 @@ void mdss_mdp_set_clk_rate(unsigned long rate) } } -unsigned long mdss_mdp_get_clk_rate(u32 clk_idx) +unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked) { unsigned long clk_rate = 0; struct clk *clk = mdss_mdp_get_clk(clk_idx); - mutex_lock(&mdp_clk_lock); - if (clk) + if (clk) { + if (!locked) + mutex_lock(&mdp_clk_lock); + clk_rate = clk_get_rate(clk); - mutex_unlock(&mdp_clk_lock); + + if (!locked) + mutex_unlock(&mdp_clk_lock); + } return clk_rate; } @@ -806,7 +817,7 @@ static int mdss_mdp_idle_pc_restore(void) } mdss_hw_init(mdata); mdss_iommu_ctrl(0); - mdss_mdp_ctl_restore(); + mdss_mdp_ctl_restore(true); mdata->idle_pc = false; end: @@ -907,10 +918,10 @@ void mdss_mdp_clk_ctrl(int enable) } } - mutex_unlock(&mdp_clk_lock); - if (enable && changed) mdss_mdp_idle_pc_restore(); + + mutex_unlock(&mdp_clk_lock); } static inline int mdss_mdp_irq_clk_register(struct mdss_data_type *mdata, @@ -984,7 +995,7 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata) mdss_mdp_irq_clk_register(mdata, "vsync_clk", MDSS_CLK_MDP_VSYNC); mdss_mdp_set_clk_rate(MDP_CLK_DEFAULT_RATE); - pr_debug("mdp clk rate=%ld\n", mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC)); + pr_debug("mdp clk rate=%ld\n", mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC, false)); return 0; } @@ -1150,11 +1161,9 @@ static void mdss_hw_rev_init(struct mdss_data_type *mdata) if (mdata->mdp_rev) return; - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); mdata->mdp_rev = MDSS_REG_READ(mdata, MDSS_REG_HW_VERSION); pr_info_once("MDP Rev=%x\n", mdata->mdp_rev); mdss_mdp_hw_rev_caps_init(mdata); - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } /** @@ -1420,7 +1429,9 @@ static ssize_t mdss_mdp_show_capabilities(struct device *dev, #define SPRINT(fmt, ...) \ (cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__)) + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); mdss_hw_rev_init(mdata); + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); SPRINT("mdp_version=5\n"); SPRINT("hw_rev=%d\n", mdata->mdp_rev); diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h index 63a388061531a1fa23f9e5dc3de10f7cb106d6f1..9b10121df4b168cca5266166c3bd041230fb1157 100644 --- a/drivers/video/msm/mdss/mdss_mdp.h +++ b/drivers/video/msm/mdss/mdss_mdp.h @@ -228,7 +228,7 @@ struct mdss_mdp_ctl { struct mdss_mdp_vsync_handler *); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps); - int (*restore_fnc) (struct mdss_mdp_ctl *ctl); + int (*restore_fnc)(struct mdss_mdp_ctl *ctl, bool locked); struct blocking_notifier_head notifier_head; @@ -701,8 +701,8 @@ void mdss_mdp_footswitch_ctrl_splash(int on); void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable); int mdss_mdp_bus_scale_set_quota(u64 ab_quota, u64 ib_quota); void mdss_mdp_set_clk_rate(unsigned long min_clk_rate); -unsigned long mdss_mdp_get_clk_rate(u32 clk_idx); -int mdss_mdp_vsync_clk_enable(int enable); +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); struct mdss_data_type *mdss_mdp_get_mdata(void); int mdss_mdp_secure_display_ctrl(unsigned int enable); @@ -916,6 +916,6 @@ int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd, int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe); int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); -void mdss_mdp_ctl_restore(void); +void mdss_mdp_ctl_restore(bool locked); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl); #endif /* MDSS_MDP_H */ diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c index 52910d45c9c4375ad263652aa454cea6025c1f49..c5af3d79aba605200a4b937c293c1dd52679cfd9 100644 --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c @@ -1995,19 +1995,25 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl) /* * mdss_mdp_ctl_restore() - restore mdp ctl path + * @locked - boolean to signal that clock lock is already acquired * * This function is called whenever MDP comes out of a power collapse as * a result of a screen update. It restores the MDP controller's software * state to the hardware registers. + * Function does not enable the clocks, so caller must make sure + * clocks are enabled before calling. + * The locked boolean in the parametrs signals that synchronization + * with mdp clocks access is not required downstream. + * Only call this function setting this value to true if the clocks access + * synchronization is guaranteed by the caller. */ -void mdss_mdp_ctl_restore(void) +void mdss_mdp_ctl_restore(bool locked) { struct mdss_mdp_ctl *ctl = NULL; struct mdss_mdp_ctl *sctl; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 cnum; - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); for (cnum = MDSS_MDP_CTL0; cnum < mdata->nctl; cnum++) { ctl = mdata->ctl_off + cnum; if (!mdss_mdp_ctl_is_power_on(ctl)) @@ -2023,9 +2029,8 @@ void mdss_mdp_ctl_restore(void) mdss_mdp_ctl_split_display_enable(1, ctl, sctl); } if (ctl->restore_fnc) - ctl->restore_fnc(ctl); + ctl->restore_fnc(ctl, locked); } - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff) diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c index cde188301ba6a2206e80fa0a24e654d9405d721e..3a58049b600457caaf942d0203cd49f4ea4be319 100644 --- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c @@ -113,7 +113,7 @@ exit: static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl, - struct mdss_mdp_mixer *mixer, bool enable) + struct mdss_mdp_mixer *mixer, bool enable, bool locked) { struct mdss_mdp_pp_tear_check *te = NULL; struct mdss_panel_info *pinfo; @@ -130,10 +130,10 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl, pinfo = &ctl->panel_data->panel_info; te = &ctl->panel_data->panel_info.te; - mdss_mdp_vsync_clk_enable(1); + mdss_mdp_vsync_clk_enable(1, locked); vsync_clk_speed_hz = - mdss_mdp_get_clk_rate(MDSS_CLK_MDP_VSYNC); + mdss_mdp_get_clk_rate(MDSS_CLK_MDP_VSYNC, locked); total_lines = mdss_panel_get_vtotal(pinfo); @@ -193,14 +193,15 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl, return 0; } -static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable) +static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable, + bool locked) { int rc = 0; struct mdss_mdp_mixer *mixer; mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT); if (mixer) { - rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable); + rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable, locked); if (rc) goto err; } @@ -208,7 +209,7 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, bool enable) if (!(ctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE)) { mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT); if (mixer) - rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable); + rc = mdss_mdp_cmd_tearcheck_cfg(ctl, mixer, enable, locked); } err: return rc; @@ -793,13 +794,11 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) return 0; } -int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl) +int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl, bool locked) { pr_debug("%s: called for ctl%d\n", __func__, ctl->num); - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - if (mdss_mdp_cmd_tearcheck_setup(ctl, true)) + if (mdss_mdp_cmd_tearcheck_setup(ctl, true, locked)) pr_warn("%s: tearcheck setup failed\n", __func__); - mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); return 0; } @@ -867,7 +866,7 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session, mdss_mdp_cmd_clk_off(ctx); flush_work(&ctx->pp_done_work); - mdss_mdp_cmd_tearcheck_setup(ctl, false); + mdss_mdp_cmd_tearcheck_setup(ctl, false, false); if (mdss_panel_is_power_on(panel_power_state)) { pr_debug("%s: intf stopped with panel on\n", __func__); @@ -1047,7 +1046,9 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, * explictly call the restore function to enable * tearcheck logic. */ - mdss_mdp_cmd_restore(ctl); + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); + mdss_mdp_cmd_restore(ctl, false); + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); /* Turn on panel so that it can exit low power mode */ ret = mdss_mdp_cmd_panel_on(ctl, sctl); @@ -1099,7 +1100,7 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num, mdss_mdp_cmd_pingpong_done, ctl); - ret = mdss_mdp_cmd_tearcheck_setup(ctl, true); + ret = mdss_mdp_cmd_tearcheck_setup(ctl, true, true); if (ret) { pr_err("tearcheck setup failed\n"); return ret; diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index e3f2790d4d630872d4c29fc226723cef0621981d..c97bba2f421e35df0321cc1451b59b041d3be2e3 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -3621,7 +3621,7 @@ static int mdss_mdp_overlay_handoff(struct msm_fb_data_type *mfd) goto error; } - ctl->clk_rate = mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC); + ctl->clk_rate = mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC, false); pr_debug("Set the ctl clock rate to %d Hz\n", ctl->clk_rate); rc = __mdss_mdp_ctl_handoff(ctl, mdata);