summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2010-12-09 07:00:07 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-12-16 21:02:26 +0000
commit49b14a5ca26fc18bafe33bd9704a1a1cea681fbf (patch)
tree0186100e398c5837040b3b994e3531fee9906d3c
parent0af7e4dff50454905092d468e91c1ef92e10e6b4 (diff)
downloadop-kernel-dev-49b14a5ca26fc18bafe33bd9704a1a1cea681fbf.zip
op-kernel-dev-49b14a5ca26fc18bafe33bd9704a1a1cea681fbf.tar.gz
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>
-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 0c201d6..fe65382 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)
}
static void do_intel_finish_page_flip(struct drm_device *dev,
- struct drm_crtc *crtc,
- int called_before_vblirq)
+ struct drm_crtc *crtc)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_unpin_work *work;
struct drm_i915_gem_object *obj;
struct drm_pending_vblank_event *e;
- struct timeval now;
+ struct timeval tnow, tvbl;
unsigned long flags;
/* Ignore early vblank irqs */
if (intel_crtc == NULL)
return;
+ do_gettimeofday(&tnow);
+
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) {
@@ -5278,22 +5279,29 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
if (work->event) {
e = work->event;
- e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &now);
+ e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);
/* 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.
+ * to account for this. We assume this happened if we
+ * get called over 0.9 frame durations after the last
+ * timestamped vblank.
+ *
+ * This calculation can not be used with vrefresh rates
+ * below 5Hz (10Hz to be on the safe side) without
+ * promoting to 64 integers.
*/
- if (called_before_vblirq) {
+ if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
+ 9 * crtc->framedur_ns) {
e->event.sequence++;
- now = ns_to_timeval(timeval_to_ns(&now) +
- crtc->framedur_ns);
+ tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
+ crtc->framedur_ns);
}
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
+ e->event.tv_sec = tvbl.tv_sec;
+ e->event.tv_usec = tvbl.tv_usec;
list_add_tail(&e->base.link,
&e->base.file_priv->event_list);
@@ -5321,8 +5329,7 @@ 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];
- /* Called after drm_handle_vblank has run for finish vblank. */
- do_intel_finish_page_flip(dev, crtc, 0);
+ do_intel_finish_page_flip(dev, crtc);
}
void 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)
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
- /* Called before drm_handle_vblank has run for finish vblank. */
- do_intel_finish_page_flip(dev, crtc, 1);
+ do_intel_finish_page_flip(dev, crtc);
}
void intel_prepare_page_flip(struct drm_device *dev, int plane)
OpenPOWER on IntegriCloud