mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: mdp: Use a waitqueue for vsync notifications
Use a waitqueue instead of completions and make sure the vsync show event always returns the timestamp except when it is interrupted. This simplifies the vsync wait mechanism both here and in userspace and avoids any unnecessary locking. Signed-off-by: Naseer Ahmed <naseer@codeaurora.org>
This commit is contained in:
parent
0f16f59916
commit
2d97d587c2
2 changed files with 34 additions and 82 deletions
|
@ -57,7 +57,6 @@ static struct vsycn_ctrl {
|
|||
uint32 rdptr_intr_tot;
|
||||
uint32 rdptr_sirq_tot;
|
||||
atomic_t suspend;
|
||||
int wait_vsync_cnt;
|
||||
int blt_change;
|
||||
int blt_free;
|
||||
int blt_end;
|
||||
|
@ -65,7 +64,6 @@ static struct vsycn_ctrl {
|
|||
struct mutex update_lock;
|
||||
struct completion ov_comp;
|
||||
struct completion dmap_comp;
|
||||
struct completion vsync_comp;
|
||||
spinlock_t spin_lock;
|
||||
struct msm_fb_data_type *mfd;
|
||||
struct mdp4_overlay_pipe *base_pipe;
|
||||
|
@ -76,6 +74,7 @@ static struct vsycn_ctrl {
|
|||
ktime_t vsync_time;
|
||||
u32 last_vsync_ms;
|
||||
struct work_struct clk_work;
|
||||
wait_queue_head_t wait_queue;
|
||||
} vsync_ctrl_db[MAX_CONTROLLER];
|
||||
|
||||
static void vsync_irq_enable(int intr, int term)
|
||||
|
@ -474,7 +473,7 @@ void mdp4_dsi_cmd_wait4vsync(int cndx)
|
|||
{
|
||||
struct vsycn_ctrl *vctrl;
|
||||
struct mdp4_overlay_pipe *pipe;
|
||||
unsigned long flags;
|
||||
ktime_t timestamp;
|
||||
|
||||
if (cndx >= MAX_CONTROLLER) {
|
||||
pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
|
||||
|
@ -487,13 +486,12 @@ void mdp4_dsi_cmd_wait4vsync(int cndx)
|
|||
if (atomic_read(&vctrl->suspend) > 0)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
if (vctrl->wait_vsync_cnt == 0)
|
||||
INIT_COMPLETION(vctrl->vsync_comp);
|
||||
vctrl->wait_vsync_cnt++;
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
timestamp = vctrl->vsync_time;
|
||||
wait_event_interruptible_timeout(vctrl->wait_queue,
|
||||
!ktime_equal(timestamp, vctrl->vsync_time)&&
|
||||
vctrl->vsync_enabled,
|
||||
msecs_to_jiffies(VSYNC_PERIOD * 8));
|
||||
|
||||
wait_for_completion(&vctrl->vsync_comp);
|
||||
mdp4_stat.wait4vsync0++;
|
||||
}
|
||||
|
||||
|
@ -558,8 +556,7 @@ static void primary_rdptr_isr(int cndx)
|
|||
}
|
||||
|
||||
vctrl->last_vsync_ms = cur_vsync_ms;
|
||||
complete_all(&vctrl->vsync_comp);
|
||||
vctrl->wait_vsync_cnt = 0;
|
||||
wake_up_interruptible_all(&vctrl->wait_queue);
|
||||
|
||||
if (vctrl->expire_tick) {
|
||||
vctrl->expire_tick--;
|
||||
|
@ -695,33 +692,21 @@ ssize_t mdp4_dsi_cmd_show_event(struct device *dev,
|
|||
int cndx;
|
||||
struct vsycn_ctrl *vctrl;
|
||||
ssize_t ret = 0;
|
||||
unsigned long flags;
|
||||
u64 vsync_tick;
|
||||
ktime_t timestamp;
|
||||
|
||||
cndx = 0;
|
||||
vctrl = &vsync_ctrl_db[0];
|
||||
timestamp = vctrl->vsync_time;
|
||||
|
||||
if (atomic_read(&vctrl->suspend) > 0)
|
||||
return 0;
|
||||
ret = wait_event_interruptible(vctrl->wait_queue,
|
||||
!ktime_equal(timestamp, vctrl->vsync_time) &&
|
||||
vctrl->vsync_enabled);
|
||||
if (ret == -ERESTARTSYS)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
if (vctrl->wait_vsync_cnt == 0)
|
||||
INIT_COMPLETION(vctrl->vsync_comp);
|
||||
vctrl->wait_vsync_cnt++;
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(&vctrl->vsync_comp,
|
||||
msecs_to_jiffies(VSYNC_PERIOD * 4));
|
||||
if (ret <= 0) {
|
||||
vctrl->wait_vsync_cnt = 0;
|
||||
vctrl->vsync_time = ktime_get();
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
vsync_tick = ktime_to_ns(vctrl->vsync_time);
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
|
||||
buf[strlen(buf) + 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
@ -744,8 +729,8 @@ void mdp4_dsi_rdptr_init(int cndx)
|
|||
mutex_init(&vctrl->update_lock);
|
||||
init_completion(&vctrl->ov_comp);
|
||||
init_completion(&vctrl->dmap_comp);
|
||||
init_completion(&vctrl->vsync_comp);
|
||||
spin_lock_init(&vctrl->spin_lock);
|
||||
init_waitqueue_head(&vctrl->wait_queue);
|
||||
atomic_set(&vctrl->suspend, 1);
|
||||
INIT_WORK(&vctrl->clk_work, clk_ctrl_work);
|
||||
}
|
||||
|
@ -1104,8 +1089,6 @@ int mdp4_dsi_cmd_off(struct platform_device *pdev)
|
|||
need_wait = 0;
|
||||
mutex_lock(&vctrl->update_lock);
|
||||
|
||||
complete_all(&vctrl->vsync_comp);
|
||||
|
||||
pr_debug("%s: clk=%d pan=%d\n", __func__,
|
||||
vctrl->clk_enabled, vctrl->pan_display);
|
||||
if (vctrl->clk_enabled)
|
||||
|
|
|
@ -53,8 +53,6 @@ static struct vsycn_ctrl {
|
|||
int ov_koff;
|
||||
int ov_done;
|
||||
atomic_t suspend;
|
||||
atomic_t vsync_resume;
|
||||
int wait_vsync_cnt;
|
||||
int blt_change;
|
||||
int blt_free;
|
||||
int blt_ctrl;
|
||||
|
@ -62,13 +60,13 @@ static struct vsycn_ctrl {
|
|||
struct mutex update_lock;
|
||||
struct completion ov_comp;
|
||||
struct completion dmap_comp;
|
||||
struct completion vsync_comp;
|
||||
spinlock_t spin_lock;
|
||||
struct msm_fb_data_type *mfd;
|
||||
struct mdp4_overlay_pipe *base_pipe;
|
||||
struct vsync_update vlist[2];
|
||||
int vsync_irq_enabled;
|
||||
ktime_t vsync_time;
|
||||
wait_queue_head_t wait_queue;
|
||||
} vsync_ctrl_db[MAX_CONTROLLER];
|
||||
|
||||
static void vsync_irq_enable(int intr, int term)
|
||||
|
@ -326,17 +324,14 @@ void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
|
|||
vctrl->vsync_irq_enabled = enable;
|
||||
|
||||
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)
|
||||
{
|
||||
struct vsycn_ctrl *vctrl;
|
||||
struct mdp4_overlay_pipe *pipe;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
ktime_t timestamp;
|
||||
|
||||
if (cndx >= MAX_CONTROLLER) {
|
||||
pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
|
||||
|
@ -351,15 +346,12 @@ void mdp4_dsi_video_wait4vsync(int cndx)
|
|||
|
||||
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);
|
||||
|
||||
vctrl->wait_vsync_cnt++;
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
/* double the timeout in vsync time stamp generation */
|
||||
ret = wait_for_completion_interruptible_timeout(&vctrl->vsync_comp,
|
||||
timestamp = vctrl->vsync_time;
|
||||
ret = wait_event_interruptible_timeout(vctrl->wait_queue,
|
||||
!ktime_equal(timestamp, vctrl->vsync_time)&&
|
||||
vctrl->vsync_irq_enabled,
|
||||
msecs_to_jiffies(VSYNC_PERIOD * 8));
|
||||
|
||||
if (ret <= 0)
|
||||
pr_err("%s timeout ret=%d", __func__, ret);
|
||||
|
||||
|
@ -427,33 +419,21 @@ ssize_t mdp4_dsi_video_show_event(struct device *dev,
|
|||
int cndx;
|
||||
struct vsycn_ctrl *vctrl;
|
||||
ssize_t ret = 0;
|
||||
unsigned long flags;
|
||||
u64 vsync_tick;
|
||||
ktime_t timestamp;
|
||||
|
||||
cndx = 0;
|
||||
vctrl = &vsync_ctrl_db[0];
|
||||
timestamp = vctrl->vsync_time;
|
||||
|
||||
if (atomic_read(&vctrl->suspend) > 0 ||
|
||||
atomic_read(&vctrl->vsync_resume) == 0)
|
||||
return 0;
|
||||
ret = wait_event_interruptible(vctrl->wait_queue,
|
||||
!ktime_equal(timestamp, vctrl->vsync_time) &&
|
||||
vctrl->vsync_irq_enabled);
|
||||
if (ret == -ERESTARTSYS)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
if (vctrl->wait_vsync_cnt == 0)
|
||||
INIT_COMPLETION(vctrl->vsync_comp);
|
||||
vctrl->wait_vsync_cnt++;
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
ret = wait_for_completion_interruptible_timeout(&vctrl->vsync_comp,
|
||||
msecs_to_jiffies(VSYNC_PERIOD * 4));
|
||||
if (ret <= 0) {
|
||||
vctrl->wait_vsync_cnt = 0;
|
||||
vctrl->vsync_time = ktime_get();
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
vsync_tick = ktime_to_ns(vctrl->vsync_time);
|
||||
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
|
||||
ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
|
||||
buf[strlen(buf) + 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
@ -476,12 +456,11 @@ void mdp4_dsi_vsync_init(int cndx)
|
|||
vctrl->inited = 1;
|
||||
vctrl->update_ndx = 0;
|
||||
mutex_init(&vctrl->update_lock);
|
||||
init_completion(&vctrl->vsync_comp);
|
||||
init_completion(&vctrl->dmap_comp);
|
||||
init_completion(&vctrl->ov_comp);
|
||||
atomic_set(&vctrl->suspend, 1);
|
||||
atomic_set(&vctrl->vsync_resume, 1);
|
||||
spin_lock_init(&vctrl->spin_lock);
|
||||
init_waitqueue_head(&vctrl->wait_queue);
|
||||
}
|
||||
|
||||
void mdp4_dsi_video_free_base_pipe(struct msm_fb_data_type *mfd)
|
||||
|
@ -524,8 +503,6 @@ 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);
|
||||
|
||||
|
@ -782,10 +759,6 @@ int mdp4_dsi_video_off(struct platform_device *pdev)
|
|||
|
||||
mdp4_dsi_video_wait4vsync(cndx);
|
||||
|
||||
atomic_set(&vctrl->vsync_resume, 0);
|
||||
|
||||
complete_all(&vctrl->vsync_comp);
|
||||
|
||||
if (pipe->ov_blt_addr) {
|
||||
spin_lock_irqsave(&vctrl->spin_lock, flags);
|
||||
if (vctrl->ov_koff != vctrl->ov_done)
|
||||
|
@ -1008,11 +981,7 @@ void mdp4_primary_vsync_dsi_video(void)
|
|||
|
||||
spin_lock(&vctrl->spin_lock);
|
||||
vctrl->vsync_time = ktime_get();
|
||||
|
||||
if (vctrl->wait_vsync_cnt) {
|
||||
complete_all(&vctrl->vsync_comp);
|
||||
vctrl->wait_vsync_cnt = 0;
|
||||
}
|
||||
wake_up_interruptible_all(&vctrl->wait_queue);
|
||||
spin_unlock(&vctrl->spin_lock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue