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 <adrianm@codeaurora.org>
This commit is contained in:
Adrian Salido-Moreno 2014-06-25 16:40:05 -07:00 committed by David Keitel
parent 1b769308cc
commit ea45dc60a1

View file

@ -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);