diff options
author | Mario Kleiner <mario.kleiner@tuebingen.mpg.de> | 2010-12-08 04:07:19 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-16 21:02:24 +0000 |
commit | 0af7e4dff50454905092d468e91c1ef92e10e6b4 (patch) | |
tree | 6c1c9542720c6cf3b6de7a9ac6e8216ba55aebbc /drivers/gpu/drm/i915/intel_display.c | |
parent | d8c58fabd75021cdd99abcd96513cb088d41092b (diff) | |
download | lwn-0af7e4dff50454905092d468e91c1ef92e10e6b4.tar.gz lwn-0af7e4dff50454905092d468e91c1ef92e10e6b4.zip |
drm/i915: Add support for precise vblank timestamping (v2)
v2: Change IS_IRONLAKE to IS_GEN5 to adapt to 2.6.37
This patch adds new functions for use by the drm core:
.get_vblank_timestamp() provides a precise timestamp
for the end of the most recent (or current) vblank
interval of a given crtc, as needed for the DRI2
implementation of the OML_sync_control extension.
It is a thin wrapper around the drm function
drm_calc_vbltimestamp_from_scanoutpos() which does
almost all the work.
.get_scanout_position() provides the current horizontal
and vertical video scanout position and "in vblank"
status of a given crtc, as needed by the drm for use by
drm_calc_vbltimestamp_from_scanoutpos().
The patch modifies the pageflip completion routine
to use these precise vblank timestamps as the timestamps
for pageflip completion events.
This code has been only tested on a HP-Mini Netbook with
Atom processor and Intel 945GME gpu. The codepath for
(IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev)) gpu's
has not been tested so far due to lack of hardware.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8645a974a499..0c201d684584 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5252,7 +5252,8 @@ static void intel_unpin_work_fn(struct work_struct *__work) } static void do_intel_finish_page_flip(struct drm_device *dev, - struct drm_crtc *crtc) + struct drm_crtc *crtc, + int called_before_vblirq) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -5274,19 +5275,33 @@ static void do_intel_finish_page_flip(struct drm_device *dev, } intel_crtc->unpin_work = NULL; - drm_vblank_put(dev, intel_crtc->pipe); if (work->event) { e = work->event; - do_gettimeofday(&now); - e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe); + e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &now); + + /* Called before vblank count and timestamps have + * been updated for the vblank interval of flip + * completion? Need to increment vblank count and + * add one videorefresh duration to returned timestamp + * to account for this. + */ + if (called_before_vblirq) { + e->event.sequence++; + now = ns_to_timeval(timeval_to_ns(&now) + + crtc->framedur_ns); + } + 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); } + drm_vblank_put(dev, intel_crtc->pipe); + spin_unlock_irqrestore(&dev->event_lock, flags); obj = work->old_fb_obj; @@ -5306,7 +5321,8 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - do_intel_finish_page_flip(dev, crtc); + /* Called after drm_handle_vblank has run for finish vblank. */ + do_intel_finish_page_flip(dev, crtc, 0); } void intel_finish_page_flip_plane(struct drm_device *dev, int plane) @@ -5314,7 +5330,8 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; - do_intel_finish_page_flip(dev, crtc); + /* Called before drm_handle_vblank has run for finish vblank. */ + do_intel_finish_page_flip(dev, crtc, 1); } void intel_prepare_page_flip(struct drm_device *dev, int plane) |