msm_fb: display: wait4vsync before set suspend flag

Since wait4vsync checks suspend flag, wait4vsync needs to
be executed before suspend flag set to enforce wait happen.
Also, when timing generator is turned off, wait4vsync can
not be used anymore since the last vsync may have passed
before wait4vsync called. This patch fixed commit_comp
timeout cause fence timeout happen on hdmi plug and unplug
cases.

CRs-fixed: 449027
Change-Id: I0f5520538bb290643a648c937296b6bc097fe051
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
This commit is contained in:
Kuogee Hsieh 2013-02-14 11:19:52 -08:00 committed by Iliyan Malchev
parent f7f116bf52
commit 24683eeb25
3 changed files with 62 additions and 36 deletions

View file

@ -486,6 +486,20 @@ void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
vctrl->base_pipe = pipe;
}
/* timing generator off */
static void mdp4_dsi_video_tg_off(struct vsycn_ctrl *vctrl)
{
unsigned long flags;
spin_lock_irqsave(&vctrl->spin_lock, flags);
INIT_COMPLETION(vctrl->vsync_comp);
vctrl->wait_vsync_cnt++;
MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); /* turn off timing generator */
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
mdp4_dsi_video_wait4vsync(0);
}
int mdp4_dsi_video_on(struct platform_device *pdev)
{
int dsi_width;
@ -585,8 +599,7 @@ int mdp4_dsi_video_on(struct platform_device *pdev)
if (!(mfd->cont_splash_done)) {
mfd->cont_splash_done = 1;
MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
mdp4_dsi_video_wait4vsync(0);
mdp4_dsi_video_tg_off(vctrl);
mipi_dsi_controller_cfg(0);
/* Clks are enabled in probe.
Disabling clocks now */
@ -722,11 +735,10 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
atomic_set(&vctrl->suspend, 1);
atomic_set(&vctrl->vsync_resume, 0);
mdp4_dsi_video_wait4vsync(cndx);
atomic_set(&vctrl->vsync_resume, 0);
complete_all(&vctrl->vsync_comp);
if (pipe->ov_blt_addr) {
@ -740,8 +752,6 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
mdp_histogram_ctrl_all(FALSE);
MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
dsi_video_enabled = 0;
undx = vctrl->update_ndx;
@ -768,7 +778,6 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
mdp4_mixer_stage_down(pipe, 1);
mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
msleep(20);
} else {
/* system suspending */
mdp4_mixer_stage_down(vctrl->base_pipe, 1);
@ -777,6 +786,10 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
}
}
mdp4_dsi_video_tg_off(vctrl);
atomic_set(&vctrl->suspend, 1);
if (vctrl->vsync_irq_enabled) {
vctrl->vsync_irq_enabled = 0;
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);

View file

@ -570,20 +570,6 @@ static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
return 0;
}
static int mdp4_dtv_stop(struct msm_fb_data_type *mfd)
{
int cndx = 0;
struct vsycn_ctrl *vctrl;
vctrl = &vsync_ctrl_db[cndx];
if (vctrl->base_pipe == NULL)
return -EINVAL;
MDP_OUTP(MDP_BASE + DTV_BASE, 0);
return 0;
}
int mdp4_dtv_on(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
@ -629,6 +615,20 @@ int mdp4_dtv_on(struct platform_device *pdev)
return ret;
}
/* timing generator off */
static void mdp4_dtv_tg_off(struct vsycn_ctrl *vctrl)
{
unsigned long flags;
spin_lock_irqsave(&vctrl->spin_lock, flags);
INIT_COMPLETION(vctrl->vsync_comp);
vctrl->wait_vsync_cnt++;
MDP_OUTP(MDP_BASE + DTV_BASE, 0); /* turn off timing generator */
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
mdp4_dtv_wait4vsync(0);
}
int mdp4_dtv_off(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
@ -643,11 +643,10 @@ int mdp4_dtv_off(struct platform_device *pdev)
vctrl = &vsync_ctrl_db[cndx];
atomic_set(&vctrl->suspend, 1);
atomic_set(&vctrl->vsync_resume, 0);
mdp4_dtv_wait4vsync(cndx);
atomic_set(&vctrl->vsync_resume, 0);
complete_all(&vctrl->vsync_comp);
pipe = vctrl->base_pipe;
@ -666,10 +665,12 @@ int mdp4_dtv_off(struct platform_device *pdev)
mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
}
mdp4_dtv_stop(mfd);
mdp4_dtv_wait4vsync(cndx);
}
mdp4_dtv_tg_off(vctrl);
atomic_set(&vctrl->suspend, 1);
mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
undx = vctrl->update_ndx;
@ -867,7 +868,7 @@ int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
pipe->pipe_type == OVERLAY_TYPE_RGB) {
result = mdp4_dtv_stop(mfd);
mdp4_dtv_tg_off(vctrl);
vctrl->base_pipe = NULL;
}
return result;

View file

@ -347,9 +347,6 @@ void mdp4_lcdc_wait4vsync(int cndx)
if (atomic_read(&vctrl->suspend) > 0)
return;
/* start timing generator & mmu if they are not started yet */
mdp4_overlay_lcdc_start();
mdp4_lcdc_vsync_irq_ctrl(cndx, 1);
spin_lock_irqsave(&vctrl->spin_lock, flags);
@ -688,10 +685,24 @@ int mdp4_lcdc_on(struct platform_device *pdev)
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
mdp_histogram_ctrl_all(TRUE);
mdp4_overlay_lcdc_start();
return ret;
}
/* timing generator off */
static void mdp4_lcdc_tg_off(struct vsycn_ctrl *vctrl)
{
unsigned long flags;
spin_lock_irqsave(&vctrl->spin_lock, flags);
INIT_COMPLETION(vctrl->vsync_comp);
vctrl->wait_vsync_cnt++;
MDP_OUTP(MDP_BASE + LCDC_BASE, 0); /* turn off timing generator */
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
mdp4_lcdc_wait4vsync(0);
}
int mdp4_lcdc_off(struct platform_device *pdev)
{
int ret = 0;
@ -707,10 +718,9 @@ int mdp4_lcdc_off(struct platform_device *pdev)
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
atomic_set(&vctrl->suspend, 1);
atomic_set(&vctrl->vsync_resume, 0);
mdp4_lcdc_wait4vsync(cndx);
msleep(20); /* >= 17 ms */
atomic_set(&vctrl->vsync_resume, 0);
complete_all(&vctrl->vsync_comp);
@ -725,8 +735,6 @@ int mdp4_lcdc_off(struct platform_device *pdev)
mdp_histogram_ctrl_all(FALSE);
MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
lcdc_enabled = 0;
undx = vctrl->update_ndx;
@ -761,6 +769,10 @@ int mdp4_lcdc_off(struct platform_device *pdev)
}
}
mdp4_lcdc_tg_off(vctrl);
atomic_set(&vctrl->suspend, 1);
/* MDP clock disable */
mdp_clk_ctrl(0);
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);