msm_fb: display: replace msleep with wait4vsync

vsync is controlled by frame work which means vsync irq
off may happen at any instance. This patch use a reference
count to control vsync irq enable/disable so that
wait4vsync can replace msleep safely during suspend.

Change-Id: Ief84b1b421436e1f750288eb9a9760a9cb96c555
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
This commit is contained in:
Kuogee Hsieh 2013-01-18 14:16:31 -08:00 committed by Stephen Boyd
parent a2781e468c
commit 56a49ded66
6 changed files with 112 additions and 58 deletions

View file

@ -488,7 +488,7 @@ int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
void mdp4_dmae_done_dtv(void);
void mdp4_dtv_wait4vsync(int cndx, long long *vtime);
void mdp4_dtv_wait4vsync(int cndx);
void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable);
void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
#else
@ -521,7 +521,7 @@ static inline void mdp4_dmae_done_dtv(void)
{
/* empty */
}
static inline void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
static inline void mdp4_dtv_wait4vsync(int cndx)
{
/* empty */
}
@ -597,7 +597,7 @@ int mdp4_overlay_format2type(uint32 format);
int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_wait4vsync(struct fb_info *info, long long *vtime);
int mdp4_overlay_wait4vsync(struct fb_info *info);
int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable);
int mdp4_overlay_unset(struct fb_info *info, int ndx);
int mdp4_overlay_unset_mixer(int mixer);
@ -628,7 +628,7 @@ void mdp4_overlay1_done_dtv(void);
void mdp4_overlay1_done_atv(void);
void mdp4_primary_vsync_lcdc(void);
void mdp4_external_vsync_dtv(void);
void mdp4_lcdc_wait4vsync(int cndx, long long *vtime);
void mdp4_lcdc_wait4vsync(int cndx);
void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
void mdp4_mddi_overlay_dmas_restore(void);
@ -786,8 +786,8 @@ int mdp4_dsi_video_off(struct platform_device *pdev);
int mdp4_dsi_video_on(struct platform_device *pdev);
void mdp4_primary_vsync_dsi_video(void);
void mdp4_dsi_cmd_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime);
void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime);
void mdp4_dsi_cmd_wait4vsync(int cndx);
void mdp4_dsi_video_wait4vsync(int cndx);
void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable);
@ -825,10 +825,10 @@ static inline void mdp4_dsi_cmd_base_swap(int cndx,
struct mdp4_overlay_pipe *pipe)
{
}
static inline void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
static inline void mdp4_dsi_cmd_wait4vsync(int cndx)
{
}
static inline void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
static inline void mdp4_dsi_video_wait4vsync(int cndx)
{
}
static inline void mdp4_dsi_cmd_pipe_queue(int cndx,

View file

@ -3224,17 +3224,17 @@ int mdp4_overlay_unset(struct fb_info *info, int ndx)
return 0;
}
int mdp4_overlay_wait4vsync(struct fb_info *info, long long *vtime)
int mdp4_overlay_wait4vsync(struct fb_info *info)
{
if (!hdmi_prim_display && info->node == 0) {
if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
mdp4_dsi_video_wait4vsync(0, vtime);
mdp4_dsi_video_wait4vsync(0);
else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
mdp4_dsi_cmd_wait4vsync(0, vtime);
mdp4_dsi_cmd_wait4vsync(0);
else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
mdp4_lcdc_wait4vsync(0, vtime);
mdp4_lcdc_wait4vsync(0);
} else if (hdmi_prim_display || info->node == 1) {
mdp4_dtv_wait4vsync(0, vtime);
mdp4_dtv_wait4vsync(0);
}
return 0;

View file

@ -388,11 +388,8 @@ int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
mdp4_stat.overlay_commit[pipe->mixer_num]++;
if (wait) {
long long tick;
mdp4_dsi_cmd_wait4vsync(0, &tick);
}
if (wait)
mdp4_dsi_cmd_wait4vsync(0);
return cnt;
}
@ -444,7 +441,7 @@ void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable)
mutex_unlock(&vctrl->update_lock);
}
void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
void mdp4_dsi_cmd_wait4vsync(int cndx)
{
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
@ -458,10 +455,8 @@ void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
if (atomic_read(&vctrl->suspend) > 0) {
*vtime = -1;
if (atomic_read(&vctrl->suspend) > 0)
return;
}
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (vctrl->wait_vsync_cnt == 0)
@ -471,8 +466,6 @@ void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
wait_for_completion(&vctrl->vsync_comp);
mdp4_stat.wait4vsync0++;
*vtime = ktime_to_ns(vctrl->vsync_time);
}
static void mdp4_dsi_cmd_wait4dmap(int cndx)

View file

@ -265,6 +265,31 @@ int mdp4_dsi_video_pipe_commit(int cndx, int wait)
return cnt;
}
static void mdp4_video_vsync_irq_ctrl(int cndx, int enable)
{
struct vsycn_ctrl *vctrl;
static int vsync_irq_cnt;
vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
if (enable) {
if (vsync_irq_cnt == 0)
vsync_irq_enable(INTR_PRIMARY_VSYNC,
MDP_PRIM_VSYNC_TERM);
vsync_irq_cnt++;
} else {
if (vsync_irq_cnt) {
vsync_irq_cnt--;
if (vsync_irq_cnt == 0)
vsync_irq_disable(INTR_PRIMARY_VSYNC,
MDP_PRIM_VSYNC_TERM);
}
}
pr_debug("%s: enable=%d cnt=%d\n", __func__, enable, vsync_irq_cnt);
mutex_unlock(&vctrl->update_lock);
}
void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
{
struct vsycn_ctrl *vctrl;
@ -279,16 +304,13 @@ void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
vctrl->vsync_irq_enabled = enable;
if (enable)
vsync_irq_enable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
else
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
mdp4_video_vsync_irq_ctrl(cndx, enable);
if (vctrl->vsync_irq_enabled && atomic_read(&vctrl->suspend) == 0)
atomic_set(&vctrl->vsync_resume, 1);
}
void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
void mdp4_dsi_video_wait4vsync(int cndx)
{
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
@ -302,14 +324,14 @@ void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
if (atomic_read(&vctrl->suspend) > 0) {
*vtime = -1;
if (atomic_read(&vctrl->suspend) > 0)
return;
}
/* start timing generator & mmu if they are not started yet */
mdp4_overlay_dsi_video_start();
mdp4_video_vsync_irq_ctrl(cndx, 1);
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (vctrl->wait_vsync_cnt == 0)
INIT_COMPLETION(vctrl->vsync_comp);
@ -318,9 +340,8 @@ void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
wait_for_completion(&vctrl->vsync_comp);
mdp4_video_vsync_irq_ctrl(cndx, 0);
mdp4_stat.wait4vsync0++;
*vtime = ktime_to_ns(vctrl->vsync_time);
}
static void mdp4_dsi_video_wait4dmap(int cndx)
@ -692,7 +713,7 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
atomic_set(&vctrl->suspend, 1);
atomic_set(&vctrl->vsync_resume, 0);
msleep(20); /* >= 17 ms */
mdp4_dsi_video_wait4vsync(cndx);
complete_all(&vctrl->vsync_comp);
@ -1058,13 +1079,12 @@ static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable)
if (vctrl->blt_ctrl == OVERLAY_BLT_SWITCH_TG_OFF) {
int tg_enabled;
long long vtime;
pr_info("%s: blt enabled by switching TG off\n", __func__);
vctrl->blt_change = 0;
tg_enabled = inpdw(MDP_BASE + DSI_VIDEO_BASE) & 0x01;
if (tg_enabled) {
mdp4_dsi_video_wait4vsync(0, &vtime);
mdp4_dsi_video_wait4vsync(cndx);
MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
mdp4_dsi_video_wait4dmap_done(0);
}

View file

@ -246,6 +246,31 @@ int mdp4_dtv_pipe_commit(int cndx, int wait)
return cnt;
}
static void mdp4_dtv_vsync_irq_ctrl(int cndx, int enable)
{
struct vsycn_ctrl *vctrl;
static int vsync_irq_cnt;
vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
if (enable) {
if (vsync_irq_cnt == 0)
vsync_irq_enable(INTR_EXTERNAL_VSYNC,
MDP_EXTER_VSYNC_TERM);
vsync_irq_cnt++;
} else {
if (vsync_irq_cnt) {
vsync_irq_cnt--;
if (vsync_irq_cnt == 0)
vsync_irq_disable(INTR_EXTERNAL_VSYNC,
MDP_EXTER_VSYNC_TERM);
}
}
pr_debug("%s: enable=%d cnt=%d\n", __func__, enable, vsync_irq_cnt);
mutex_unlock(&vctrl->update_lock);
}
void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable)
{
struct vsycn_ctrl *vctrl;
@ -263,16 +288,13 @@ void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable)
vctrl->vsync_irq_enabled = enable;
if (enable)
vsync_irq_enable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
else
vsync_irq_disable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
mdp4_dtv_vsync_irq_ctrl(cndx, enable);
if (vctrl->vsync_irq_enabled && atomic_read(&vctrl->suspend) == 0)
atomic_set(&vctrl->vsync_resume, 1);
}
void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
void mdp4_dtv_wait4vsync(int cndx)
{
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
@ -289,6 +311,8 @@ void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
if (atomic_read(&vctrl->suspend) > 0)
return;
mdp4_dtv_vsync_irq_ctrl(cndx, 1);
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (vctrl->wait_vsync_cnt == 0)
@ -297,9 +321,8 @@ void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
wait_for_completion(&vctrl->vsync_comp);
mdp4_dtv_vsync_irq_ctrl(cndx, 0);
mdp4_stat.wait4vsync1++;
*vtime = ktime_to_ns(vctrl->vsync_time);
}
static void mdp4_dtv_wait4dmae(int cndx)
@ -608,10 +631,7 @@ int mdp4_dtv_off(struct platform_device *pdev)
atomic_set(&vctrl->suspend, 1);
atomic_set(&vctrl->vsync_resume, 0);
if (vctrl->vsync_irq_enabled) {
while (vctrl->wait_vsync_cnt)
msleep(20); /* >= 17 ms */
}
mdp4_dtv_wait4vsync(cndx);
complete_all(&vctrl->vsync_comp);

View file

@ -270,6 +270,31 @@ int mdp4_lcdc_pipe_commit(int cndx, int wait)
return cnt;
}
static void mdp4_lcdc_vsync_irq_ctrl(int cndx, int enable)
{
struct vsycn_ctrl *vctrl;
static int vsync_irq_cnt;
vctrl = &vsync_ctrl_db[cndx];
mutex_lock(&vctrl->update_lock);
if (enable) {
if (vsync_irq_cnt == 0)
vsync_irq_enable(INTR_PRIMARY_VSYNC,
MDP_PRIM_VSYNC_TERM);
vsync_irq_cnt++;
} else {
if (vsync_irq_cnt) {
vsync_irq_cnt--;
if (vsync_irq_cnt == 0)
vsync_irq_disable(INTR_PRIMARY_VSYNC,
MDP_PRIM_VSYNC_TERM);
}
}
pr_debug("%s: enable=%d cnt=%d\n", __func__, enable, vsync_irq_cnt);
mutex_unlock(&vctrl->update_lock);
}
void mdp4_lcdc_vsync_ctrl(struct fb_info *info, int enable)
{
struct vsycn_ctrl *vctrl;
@ -284,16 +309,13 @@ void mdp4_lcdc_vsync_ctrl(struct fb_info *info, int enable)
vctrl->vsync_irq_enabled = enable;
if (enable)
vsync_irq_enable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
else
vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
mdp4_lcdc_vsync_irq_ctrl(cndx, enable);
if (vctrl->vsync_irq_enabled && atomic_read(&vctrl->suspend) == 0)
atomic_set(&vctrl->vsync_resume, 1);
}
void mdp4_lcdc_wait4vsync(int cndx, long long *vtime)
void mdp4_lcdc_wait4vsync(int cndx)
{
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
@ -307,14 +329,14 @@ void mdp4_lcdc_wait4vsync(int cndx, long long *vtime)
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
if (atomic_read(&vctrl->suspend) > 0) {
*vtime = -1;
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);
if (vctrl->wait_vsync_cnt == 0)
@ -323,9 +345,8 @@ void mdp4_lcdc_wait4vsync(int cndx, long long *vtime)
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
wait_for_completion(&vctrl->vsync_comp);
mdp4_lcdc_vsync_irq_ctrl(cndx, 0);
mdp4_stat.wait4vsync0++;
*vtime = vctrl->vsync_time.tv64;
}
static void mdp4_lcdc_wait4dmap(int cndx)