aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2010-12-09 01:00:07 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-12-16 16:02:26 -0500
commit49b14a5ca26fc18bafe33bd9704a1a1cea681fbf (patch)
tree0186100e398c5837040b3b994e3531fee9906d3c /drivers/gpu/drm/i915/intel_display.c
parent0af7e4dff50454905092d468e91c1ef92e10e6b4 (diff)
drm/i915: Add Guess-o-matic for pageflip timestamping.
This patch changes the strategy for pageflip completion timestamping. It detects if the pageflip completion routine gets executed before or after drm_handle_vblank, and thereby decides if the returned vblank count and timestamp must be incremented by 1 frame(duration) or not. It compares the current system time at invocation against the current vblank timestamp. If the difference is more than 0.9 video refresh interval durations then it assumes the vblank timestamp and count are outdated and need to be incremented and does so. Otherwise it assumes a delayed pageflip irq and doesn't correct the timestamp and count. Advantage of this patch: Pageflip timestamping becomes more robust against implementation errors and is maintenance free for future GPU's. Disadvantage: A few dozen (hundred?) nsecs extra time spent in pageflip irq handler for each flip, compared to hard-coded per-gpu settings? 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.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0c201d684584..fe6538297872 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5252,21 +5252,22 @@ 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)
5257{ 5256{
5258 drm_i915_private_t *dev_priv = dev->dev_private; 5257 drm_i915_private_t *dev_priv = dev->dev_private;
5259 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 5258 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
5260 struct intel_unpin_work *work; 5259 struct intel_unpin_work *work;
5261 struct drm_i915_gem_object *obj; 5260 struct drm_i915_gem_object *obj;
5262 struct drm_pending_vblank_event *e; 5261 struct drm_pending_vblank_event *e;
5263 struct timeval now; 5262 struct timeval tnow, tvbl;
5264 unsigned long flags; 5263 unsigned long flags;
5265 5264
5266 /* Ignore early vblank irqs */ 5265 /* Ignore early vblank irqs */
5267 if (intel_crtc == NULL) 5266 if (intel_crtc == NULL)
5268 return; 5267 return;
5269 5268
5269 do_gettimeofday(&tnow);
5270
5270 spin_lock_irqsave(&dev->event_lock, flags); 5271 spin_lock_irqsave(&dev->event_lock, flags);
5271 work = intel_crtc->unpin_work; 5272 work = intel_crtc->unpin_work;
5272 if (work == NULL || !work->pending) { 5273 if (work == NULL || !work->pending) {
@@ -5278,22 +5279,29 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
5278 5279
5279 if (work->event) { 5280 if (work->event) {
5280 e = work->event; 5281 e = work->event;
5281 e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &now); 5282 e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);
5282 5283
5283 /* Called before vblank count and timestamps have 5284 /* Called before vblank count and timestamps have
5284 * been updated for the vblank interval of flip 5285 * been updated for the vblank interval of flip
5285 * completion? Need to increment vblank count and 5286 * completion? Need to increment vblank count and
5286 * add one videorefresh duration to returned timestamp 5287 * add one videorefresh duration to returned timestamp
5287 * to account for this. 5288 * to account for this. We assume this happened if we
5289 * get called over 0.9 frame durations after the last
5290 * timestamped vblank.
5291 *
5292 * This calculation can not be used with vrefresh rates
5293 * below 5Hz (10Hz to be on the safe side) without
5294 * promoting to 64 integers.
5288 */ 5295 */
5289 if (called_before_vblirq) { 5296 if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
5297 9 * crtc->framedur_ns) {
5290 e->event.sequence++; 5298 e->event.sequence++;
5291 now = ns_to_timeval(timeval_to_ns(&now) + 5299 tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
5292 crtc->framedur_ns); 5300 crtc->framedur_ns);
5293 } 5301 }
5294 5302
5295 e->event.tv_sec = now.tv_sec; 5303 e->event.tv_sec = tvbl.tv_sec;
5296 e->event.tv_usec = now.tv_usec; 5304 e->event.tv_usec = tvbl.tv_usec;
5297 5305
5298 list_add_tail(&e->base.link, 5306 list_add_tail(&e->base.link,
5299 &e->base.file_priv->event_list); 5307 &e->base.file_priv->event_list);
@@ -5321,8 +5329,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
5321 drm_i915_private_t *dev_priv = dev->dev_private; 5329 drm_i915_private_t *dev_priv = dev->dev_private;
5322 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; 5330 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
5323 5331
5324 /* Called after drm_handle_vblank has run for finish vblank. */ 5332 do_intel_finish_page_flip(dev, crtc);
5325 do_intel_finish_page_flip(dev, crtc, 0);
5326} 5333}
5327 5334
5328void intel_finish_page_flip_plane(struct drm_device *dev, int plane) 5335void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
@@ -5330,8 +5337,7 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
5330 drm_i915_private_t *dev_priv = dev->dev_private; 5337 drm_i915_private_t *dev_priv = dev->dev_private;
5331 struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; 5338 struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
5332 5339
5333 /* Called before drm_handle_vblank has run for finish vblank. */ 5340 do_intel_finish_page_flip(dev, crtc);
5334 do_intel_finish_page_flip(dev, crtc, 1);
5335} 5341}
5336 5342
5337void intel_prepare_page_flip(struct drm_device *dev, int plane) 5343void intel_prepare_page_flip(struct drm_device *dev, int plane)