diff options
author | Mario Kleiner <mario.kleiner@tuebingen.mpg.de> | 2010-12-07 22:07:19 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-16 16:02:24 -0500 |
commit | 0af7e4dff50454905092d468e91c1ef92e10e6b4 (patch) | |
tree | 6c1c9542720c6cf3b6de7a9ac6e8216ba55aebbc /drivers/gpu/drm/i915/intel_display.c | |
parent | d8c58fabd75021cdd99abcd96513cb088d41092b (diff) |
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) | |||
5252 | } | 5252 | } |
5253 | 5253 | ||
5254 | static void do_intel_finish_page_flip(struct drm_device *dev, | 5254 | static void do_intel_finish_page_flip(struct drm_device *dev, |
5255 | struct drm_crtc *crtc) | 5255 | struct drm_crtc *crtc, |
5256 | int called_before_vblirq) | ||
5256 | { | 5257 | { |
5257 | drm_i915_private_t *dev_priv = dev->dev_private; | 5258 | drm_i915_private_t *dev_priv = dev->dev_private; |
5258 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5259 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
@@ -5274,19 +5275,33 @@ static void do_intel_finish_page_flip(struct drm_device *dev, | |||
5274 | } | 5275 | } |
5275 | 5276 | ||
5276 | intel_crtc->unpin_work = NULL; | 5277 | intel_crtc->unpin_work = NULL; |
5277 | drm_vblank_put(dev, intel_crtc->pipe); | ||
5278 | 5278 | ||
5279 | if (work->event) { | 5279 | if (work->event) { |
5280 | e = work->event; | 5280 | e = work->event; |
5281 | do_gettimeofday(&now); | 5281 | e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &now); |
5282 | e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe); | 5282 | |
5283 | /* Called before vblank count and timestamps have | ||
5284 | * been updated for the vblank interval of flip | ||
5285 | * completion? Need to increment vblank count and | ||
5286 | * add one videorefresh duration to returned timestamp | ||
5287 | * to account for this. | ||
5288 | */ | ||
5289 | if (called_before_vblirq) { | ||
5290 | e->event.sequence++; | ||
5291 | now = ns_to_timeval(timeval_to_ns(&now) + | ||
5292 | crtc->framedur_ns); | ||
5293 | } | ||
5294 | |||
5283 | e->event.tv_sec = now.tv_sec; | 5295 | e->event.tv_sec = now.tv_sec; |
5284 | e->event.tv_usec = now.tv_usec; | 5296 | e->event.tv_usec = now.tv_usec; |
5297 | |||
5285 | list_add_tail(&e->base.link, | 5298 | list_add_tail(&e->base.link, |
5286 | &e->base.file_priv->event_list); | 5299 | &e->base.file_priv->event_list); |
5287 | wake_up_interruptible(&e->base.file_priv->event_wait); | 5300 | wake_up_interruptible(&e->base.file_priv->event_wait); |
5288 | } | 5301 | } |
5289 | 5302 | ||
5303 | drm_vblank_put(dev, intel_crtc->pipe); | ||
5304 | |||
5290 | spin_unlock_irqrestore(&dev->event_lock, flags); | 5305 | spin_unlock_irqrestore(&dev->event_lock, flags); |
5291 | 5306 | ||
5292 | obj = work->old_fb_obj; | 5307 | obj = work->old_fb_obj; |
@@ -5306,7 +5321,8 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
5306 | drm_i915_private_t *dev_priv = dev->dev_private; | 5321 | drm_i915_private_t *dev_priv = dev->dev_private; |
5307 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | 5322 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; |
5308 | 5323 | ||
5309 | do_intel_finish_page_flip(dev, crtc); | 5324 | /* Called after drm_handle_vblank has run for finish vblank. */ |
5325 | do_intel_finish_page_flip(dev, crtc, 0); | ||
5310 | } | 5326 | } |
5311 | 5327 | ||
5312 | void intel_finish_page_flip_plane(struct drm_device *dev, int plane) | 5328 | 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) | |||
5314 | drm_i915_private_t *dev_priv = dev->dev_private; | 5330 | drm_i915_private_t *dev_priv = dev->dev_private; |
5315 | struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; | 5331 | struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; |
5316 | 5332 | ||
5317 | do_intel_finish_page_flip(dev, crtc); | 5333 | /* Called before drm_handle_vblank has run for finish vblank. */ |
5334 | do_intel_finish_page_flip(dev, crtc, 1); | ||
5318 | } | 5335 | } |
5319 | 5336 | ||
5320 | void intel_prepare_page_flip(struct drm_device *dev, int plane) | 5337 | void intel_prepare_page_flip(struct drm_device *dev, int plane) |