Skip to content

Commit

Permalink
drm/i915: Add Guess-o-matic for pageflip timestamping.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mario Kleiner authored and Chris Wilson committed Dec 16, 2010
1 parent 0af7e4d commit 49b14a5
Showing 1 changed file with 20 additions and 14 deletions.
34 changes: 20 additions & 14 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -5321,17 +5329,15 @@ 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)
{
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)
Expand Down

0 comments on commit 49b14a5

Please sign in to comment.