aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2010-12-07 22:07:19 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-12-16 16:02:24 -0500
commit0af7e4dff50454905092d468e91c1ef92e10e6b4 (patch)
tree6c1c9542720c6cf3b6de7a9ac6e8216ba55aebbc /drivers/gpu/drm/i915/intel_display.c
parentd8c58fabd75021cdd99abcd96513cb088d41092b (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.c29
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
5254static void do_intel_finish_page_flip(struct drm_device *dev, 5254static 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
5312void intel_finish_page_flip_plane(struct drm_device *dev, int plane) 5328void 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
5320void intel_prepare_page_flip(struct drm_device *dev, int plane) 5337void intel_prepare_page_flip(struct drm_device *dev, int plane)