On Thu, Oct 11, 2012 at 07:29:15PM -0500, Rob Clark wrote:
From: Rob Clark rob@ti.com
A helper that drivers can use to send vblank event after a pageflip. If the driver doesn't support proper vblank irq based time/seqn then just pass -1 for the pipe # to get do_gettimestamp() behavior (since there are a lot of drivers that don't use drm_vblank_count_and_time())
Also an internal send_vblank_event() helper for the various other code paths within drm_irq that also need to send vblank events.
v1: original v2: add back 'vblwait->reply.sequence = seq' which should not have been deleted v3: add WARN_ON() in case lock is not held and comments
Signed-off-by: Rob Clark rob@ti.com
drivers/gpu/drm/drm_irq.c | 74 +++++++++++++++++++++++++++++++-------------- include/drm/drmP.h | 2 ++ 2 files changed, 54 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 076c4a8..d623a06 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -802,6 +802,46 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, } EXPORT_SYMBOL(drm_vblank_count_and_time);
+static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e,
unsigned long seq, struct timeval *now)
+{
- WARN_ON(!spin_is_locked(&dev->event_lock));
This should be WARN_ON_SMP - on !SMP && !DEBUG_SPINLOCK spin_is_locked always returns 0.
- e->event.sequence = seq;
- e->event.tv_sec = now->tv_sec;
- e->event.tv_usec = now->tv_usec;
- list_add_tail(&e->base.link,
&e->base.file_priv->event_list);
- wake_up_interruptible(&e->base.file_priv->event_wait);
- trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
e->event.sequence);
+}
+/**
- drm_send_vblank_event - helper to send vblank event after pageflip
- @dev: DRM device
- @crtc: CRTC in question
- @e: the event to send
- Updates sequence # and timestamp on event, and sends it to userspace.
- Caller must hold event lock.
- */
+void drm_send_vblank_event(struct drm_device *dev, int crtc,
struct drm_pending_vblank_event *e)
+{
- struct timeval now;
- unsigned int seq;
- if (crtc >= 0) {
seq = drm_vblank_count_and_time(dev, crtc, &now);
- } else {
seq = 0;
do_gettimeofday(&now);
- }
- send_vblank_event(dev, e, seq, &now);
+} +EXPORT_SYMBOL(drm_send_vblank_event);
/**
- drm_update_vblank_count - update the master vblank counter
- @dev: DRM device
@@ -936,6 +976,13 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put);
+/**
- drm_vblank_off - disable vblank events on a CRTC
- @dev: DRM device
- @crtc: CRTC in question
- Caller must hold event lock.
- */
void drm_vblank_off(struct drm_device *dev, int crtc) { struct drm_pending_vblank_event *e, *t; @@ -955,15 +1002,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc) DRM_DEBUG("Sending premature vblank event on disable: \ wanted %d, current %d\n", e->event.sequence, seq);
e->event.sequence = seq;
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);list_del(&e->base.link);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
e->event.sequence);
send_vblank_event(dev, e, seq, &now);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -1107,15 +1148,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) {
e->event.sequence = seq;
e->event.tv_sec = now.tv_sec;
drm_vblank_put(dev, pipe);e->event.tv_usec = now.tv_usec;
list_add_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
vblwait->reply.sequence = seq;send_vblank_event(dev, e, seq, &now);
trace_drm_vblank_event_delivered(current->pid, pipe,
} else { /* drm_handle_vblank_events will call drm_vblank_put */ list_add_tail(&e->base.link, &dev->vblank_event_list);vblwait->request.sequence);
@@ -1256,14 +1291,9 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) DRM_DEBUG("vblank event on %d, current %d\n", e->event.sequence, seq);
e->event.sequence = seq;
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);list_del(&e->base.link);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
e->event.sequence);
send_vblank_event(dev, e, seq, &now);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 05af0e7..ee8f927 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1437,6 +1437,8 @@ extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, struct timeval *vblanktime); +extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
struct drm_pending_vblank_event *e);
extern bool drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); --