msm: msm_fb: wait for VSYNC instead of DMA_P for commit completion.

In the current implementation, we are waiting for DMA_P interrupt
in commit call to signal completion. This can cause 2 commits happening
in the same vsync period due to which IOMMU page faults can happen when
vsync comes while second commit is programming resgisters. To avoid this,
wait for DMA_P is replaced by wait for VSYNC.

Change-Id: I68d4d4b4e7a574f86faecd5b4812e1f5852f4209
Signed-off-by: Vishnuvardhan Prodduturi <vproddut@codeaurora.org>
This commit is contained in:
Vishnuvardhan Prodduturi 2013-09-14 15:42:42 +05:30 committed by Artem Borisov
parent 3c4ccf282e
commit 77e93ca69c

View file

@ -66,6 +66,7 @@ static struct vsycn_ctrl {
struct vsync_update vlist[2];
int vsync_irq_enabled;
ktime_t vsync_time;
wait_queue_head_t wait_queue_internal;
wait_queue_head_t wait_queue;
} vsync_ctrl_db[MAX_CONTROLLER];
@ -266,10 +267,6 @@ int mdp4_dsi_video_pipe_commit(int cndx, int wait)
/* kickoff overlay engine */
mdp4_stat.kickoff_ov0++;
outpdw(MDP_BASE + 0x0004, 0);
} else {
/* schedule second phase update at dmap */
INIT_COMPLETION(vctrl->dmap_comp);
vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
}
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
@ -279,7 +276,7 @@ int mdp4_dsi_video_pipe_commit(int cndx, int wait)
if (pipe->ov_blt_addr)
mdp4_dsi_video_wait4ov(0);
else
mdp4_dsi_video_wait4dmap(0);
mdp4_dsi_video_wait4vsync(0);
}
return cnt;
@ -329,8 +326,9 @@ void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
void mdp4_dsi_video_wait4vsync(int cndx)
{
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
int ret;
ktime_t timestamp;
unsigned long flags;
if (cndx >= MAX_CONTROLLER) {
pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
@ -338,14 +336,16 @@ void mdp4_dsi_video_wait4vsync(int cndx)
}
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
if (atomic_read(&vctrl->suspend) > 0)
return;
spin_lock_irqsave(&vctrl->spin_lock, flags);
timestamp = vctrl->vsync_time;
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
mdp4_video_vsync_irq_ctrl(cndx, 1);
ret = wait_event_interruptible_timeout(vctrl->wait_queue, 1,
ret = wait_event_timeout(vctrl->wait_queue_internal,
!ktime_equal(timestamp, vctrl->vsync_time),
msecs_to_jiffies(VSYNC_PERIOD * 8));
if (ret <= 0)
@ -417,10 +417,14 @@ ssize_t mdp4_dsi_video_show_event(struct device *dev,
ssize_t ret = 0;
u64 vsync_tick;
ktime_t timestamp;
unsigned long flags;
cndx = 0;
vctrl = &vsync_ctrl_db[0];
spin_lock_irqsave(&vctrl->spin_lock, flags);
timestamp = vctrl->vsync_time;
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
ret = wait_event_interruptible(vctrl->wait_queue,
!ktime_equal(timestamp, vctrl->vsync_time) &&
@ -428,7 +432,10 @@ ssize_t mdp4_dsi_video_show_event(struct device *dev,
if (ret == -ERESTARTSYS)
return ret;
spin_lock_irqsave(&vctrl->spin_lock, flags);
vsync_tick = ktime_to_ns(vctrl->vsync_time);
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
buf[strlen(buf) + 1] = '\0';
return ret;
@ -456,6 +463,7 @@ void mdp4_dsi_vsync_init(int cndx)
init_completion(&vctrl->ov_comp);
atomic_set(&vctrl->suspend, 1);
spin_lock_init(&vctrl->spin_lock);
init_waitqueue_head(&vctrl->wait_queue_internal);
init_waitqueue_head(&vctrl->wait_queue);
}
@ -977,6 +985,7 @@ void mdp4_primary_vsync_dsi_video(void)
spin_lock(&vctrl->spin_lock);
vctrl->vsync_time = ktime_get();
wake_up_all(&vctrl->wait_queue_internal);
wake_up_interruptible_all(&vctrl->wait_queue);
spin_unlock(&vctrl->spin_lock);
}