From ea45dc60a17b253d9b5921ffddf20b6573f9f84b Mon Sep 17 00:00:00 2001 From: Adrian Salido-Moreno Date: Wed, 25 Jun 2014 16:40:05 -0700 Subject: [PATCH] msm: mdss: ensure retire fences are signaled during panel off When turning off command mode panel, if retire fences are still active and suspend sequence goes through some fences may remain active. If fences remain active command panel off sequence would stop signaling vsyncs and would throw off the timeline. To fix this clear the retire timeline when turning panel off. Change-Id: I32a5fe0f81b16fa2ef959c7f05e484fb9f9f8598 Signed-off-by: Adrian Salido-Moreno --- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 37 +++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index b43426790ea9..0a6b765d2c79 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -59,6 +59,8 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd); static void __overlay_kickoff_requeue(struct msm_fb_data_type *mfd); static int __mdss_mdp_overlay_check_zorder(struct mdss_data_type *mdata, struct mdp_overlay *req); +static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val); + static inline bool is_ov_right_blend(struct mdp_rect *left_blend, struct mdp_rect *right_blend, u32 left_lm_w) { @@ -3278,6 +3280,20 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) mdss_mdp_overlay_kickoff(mfd, NULL); } + /* + * If retire fences are still active wait for a vsync time + * for retire fence to be updated. + * As a last resort signal the timeline if vsync doesn't arrive. + */ + if (mdp5_data->retire_cnt) { + u32 fps = mdss_panel_get_framerate(mfd->panel_info); + u32 vsync_time = 1000 / (fps ? : DEFAULT_FRAME_RATE); + + msleep(vsync_time); + + __vsync_retire_signal(mfd, mdp5_data->retire_cnt); + } + mutex_lock(&mdp5_data->ov_lock); rc = mdss_mdp_ctl_stop(mdp5_data->ctl); if (rc == 0) { @@ -3460,7 +3476,6 @@ static void __vsync_retire_work_handler(struct work_struct *work) { struct mdss_overlay_private *mdp5_data = container_of(work, typeof(*mdp5_data), retire_work); - struct msm_sync_pt_data *sync_pt_data; if (!mdp5_data->ctl || !mdp5_data->ctl->mfd) return; @@ -3468,12 +3483,18 @@ static void __vsync_retire_work_handler(struct work_struct *work) if (!mdp5_data->ctl->remove_vsync_handler) return; - sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data; - mutex_lock(&sync_pt_data->sync_mutex); - if (mdp5_data->retire_cnt > 0) { - sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1); + __vsync_retire_signal(mdp5_data->ctl->mfd, 1); +} - mdp5_data->retire_cnt--; +static void __vsync_retire_signal(struct msm_fb_data_type *mfd, int val) +{ + struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + + mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); + if (mdp5_data->retire_cnt > 0) { + sw_sync_timeline_inc(mdp5_data->vsync_timeline, val); + + mdp5_data->retire_cnt -= min(val, mdp5_data->retire_cnt); if (mdp5_data->retire_cnt == 0) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl, @@ -3481,7 +3502,7 @@ static void __vsync_retire_work_handler(struct work_struct *work) mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } } - mutex_unlock(&sync_pt_data->sync_mutex); + mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); } static struct sync_fence * @@ -3507,7 +3528,7 @@ __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data) return ERR_PTR(-EPERM); } - if (mdp5_data->retire_cnt == 0) { + if (!mdp5_data->vsync_retire_handler.enabled) { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); rc = ctl->add_vsync_handler(ctl, &mdp5_data->vsync_retire_handler);