aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2010-10-22 22:20:23 -0400
committerDave Airlie <airlied@redhat.com>2010-11-21 20:45:05 -0500
commit27641c3f003e7f3b6585c01d8a788883603eb262 (patch)
treee26eb639c4b5f429d30033d598544f82479d1ea3
parent3561d43fd289f590fdae672e5eb831b8d5cf0bf6 (diff)
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise vblank counts and precise timestamps corresponding to those vblank counts. For conformance to the OpenML OML_sync_control extension specification the DRM timestamp associated with a vblank count should correspond to the start of video scanout of the first scanline of the video frame following the vblank interval for that vblank count. Therefore we need to carry around precise timestamps for vblanks. Currently the DRM and KMS drivers generate timestamps ad-hoc via do_gettimeofday() in some places. The resulting timestamps are sometimes not very precise due to interrupt handling delays, they don't conform to OML_sync_control and some are wrong, as they aren't taken synchronized to the vblank. This patch implements support inside the drm core for precise and robust timestamping. It consists of the following interrelated pieces. 1. Vblank timestamp caching: A per-crtc ringbuffer stores the most recent vblank timestamps corresponding to vblank counts. The ringbuffer can be read out lock-free via the accessor function: struct timeval timestamp; vblankcount = drm_vblank_count_and_time(dev, crtcid, &timestamp). The function returns the current vblank count and the corresponding timestamp for start of video scanout following the vblank interval. It can be used anywhere between enclosing drm_vblank_get(dev, crtcid) and drm_vblank_put(dev,crtcid) statements. It is used inside the drmWaitVblank ioctl and in the vblank event queueing and handling. It should be used by kms drivers for timestamping of bufferswap completion. The timestamp ringbuffer is reinitialized each time vblank irq's get reenabled in drm_vblank_get()/ drm_update_vblank_count(). It is invalidated when vblank irq's get disabled. The ringbuffer is updated inside drm_handle_vblank() at each vblank irq. 2. Calculation of precise vblank timestamps: drm_get_last_vbltimestamp() is used to compute the timestamp for the end of the most recent vblank (if inside active scanout), or the expected end of the current vblank interval (if called inside a vblank interval). The function calls into a new optional kms driver entry point dev->driver->get_vblank_timestamp() which is supposed to provide the precise timestamp. If a kms driver doesn't implement the entry point or if the call fails, a simple do_gettimeofday() timestamp is returned as crude approximation of the true vblank time. A new drm module parameter drm.timestamp_precision_usec allows to disable high precision timestamps (if set to zero) or to specify the maximum acceptable error in the timestamps in microseconds. Kms drivers could implement their get_vblank_timestamp() function in a gpu specific way, as long as returned timestamps conform to OML_sync_control, e.g., by use of gpu specific hardware timestamps. Optionally, kms drivers can simply wrap and use the new utility function drm_calc_vbltimestamp_from_scanoutpos(). This function calls a new optional kms driver function dev->driver->get_scanout_position() which returns the current horizontal and vertical video scanout position of the crtc. The scanout position together with the drm_display_timing of the current video mode is used to calculate elapsed time relative to start of active scanout for the current video frame. This elapsed time is subtracted from the current do_gettimeofday() time to get the timestamp corresponding to start of video scanout. Currently non-interlaced, non-doublescan video modes, with or without panel scaling are handled correctly. Interlaced/ doublescan modes are tbd in a future patch. 3. Filtering of redundant vblank irq's and removal of some race-conditions in the vblank irq enable/disable path: Some gpu's (e.g., Radeon R500/R600) send spurious vblank irq's outside the vblank if vblank irq's get reenabled. These get detected by use of the vblank timestamps and filtered out to avoid miscounting of vblanks. Some race-conditions between the vblank irq enable/disable functions, the vblank irq handler and the gpu itself (updating its hardware vblank counter in the "wrong" moment) are fixed inside vblank_disable_and_save() and drm_update_vblank_count() by use of the vblank timestamps and a new spinlock dev->vblank_time_lock. The time until vblank irq disable is now configurable via a new drm module parameter drm.vblankoffdelay to allow experimentation with timeouts that are much shorter than the current 5 seconds and should allow longer vblank off periods for better power savings. Followup patches will use these new functions to implement precise timestamping for the intel and radeon kms drivers. Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c13
-rw-r--r--drivers/gpu/drm/drm_irq.c563
-rw-r--r--drivers/gpu/drm/drm_stub.c10
-rw-r--r--include/drm/drmP.h93
-rw-r--r--include/drm/drm_crtc.h9
5 files changed, 662 insertions, 26 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f7af91cb273d..4c200931a6bc 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -336,7 +336,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
336 struct drm_framebuffer *old_fb) 336 struct drm_framebuffer *old_fb)
337{ 337{
338 struct drm_device *dev = crtc->dev; 338 struct drm_device *dev = crtc->dev;
339 struct drm_display_mode *adjusted_mode, saved_mode; 339 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
340 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 340 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
341 struct drm_encoder_helper_funcs *encoder_funcs; 341 struct drm_encoder_helper_funcs *encoder_funcs;
342 int saved_x, saved_y; 342 int saved_x, saved_y;
@@ -350,6 +350,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
350 if (!crtc->enabled) 350 if (!crtc->enabled)
351 return true; 351 return true;
352 352
353 saved_hwmode = crtc->hwmode;
353 saved_mode = crtc->mode; 354 saved_mode = crtc->mode;
354 saved_x = crtc->x; 355 saved_x = crtc->x;
355 saved_y = crtc->y; 356 saved_y = crtc->y;
@@ -427,11 +428,21 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
427 428
428 } 429 }
429 430
431 /* Store real post-adjustment hardware mode. */
432 crtc->hwmode = *adjusted_mode;
433
434 /* Calculate and store various constants which
435 * are later needed by vblank and swap-completion
436 * timestamping. They are derived from true hwmode.
437 */
438 drm_calc_timestamping_constants(crtc);
439
430 /* XXX free adjustedmode */ 440 /* XXX free adjustedmode */
431 drm_mode_destroy(dev, adjusted_mode); 441 drm_mode_destroy(dev, adjusted_mode);
432 /* FIXME: add subpixel order */ 442 /* FIXME: add subpixel order */
433done: 443done:
434 if (!ret) { 444 if (!ret) {
445 crtc->hwmode = saved_hwmode;
435 crtc->mode = saved_mode; 446 crtc->mode = saved_mode;
436 crtc->x = saved_x; 447 crtc->x = saved_x;
437 crtc->y = saved_y; 448 crtc->y = saved_y;
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 9d3a5030b6e1..4e82d0d3c378 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -40,6 +40,22 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41 41
42#include <linux/vgaarb.h> 42#include <linux/vgaarb.h>
43
44/* Access macro for slots in vblank timestamp ringbuffer. */
45#define vblanktimestamp(dev, crtc, count) ( \
46 (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \
47 ((count) % DRM_VBLANKTIME_RBSIZE)])
48
49/* Retry timestamp calculation up to 3 times to satisfy
50 * drm_timestamp_precision before giving up.
51 */
52#define DRM_TIMESTAMP_MAXRETRIES 3
53
54/* Threshold in nanoseconds for detection of redundant
55 * vblank irq in drm_handle_vblank(). 1 msec should be ok.
56 */
57#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
58
43/** 59/**
44 * Get interrupt from bus id. 60 * Get interrupt from bus id.
45 * 61 *
@@ -77,6 +93,87 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
77 return 0; 93 return 0;
78} 94}
79 95
96/*
97 * Clear vblank timestamp buffer for a crtc.
98 */
99static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
100{
101 memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0,
102 DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval));
103}
104
105/*
106 * Disable vblank irq's on crtc, make sure that last vblank count
107 * of hardware and corresponding consistent software vblank counter
108 * are preserved, even if there are any spurious vblank irq's after
109 * disable.
110 */
111static void vblank_disable_and_save(struct drm_device *dev, int crtc)
112{
113 unsigned long irqflags;
114 u32 vblcount;
115 s64 diff_ns;
116 int vblrc;
117 struct timeval tvblank;
118
119 /* Prevent vblank irq processing while disabling vblank irqs,
120 * so no updates of timestamps or count can happen after we've
121 * disabled. Needed to prevent races in case of delayed irq's.
122 * Disable preemption, so vblank_time_lock is held as short as
123 * possible, even under a kernel with PREEMPT_RT patches.
124 */
125 preempt_disable();
126 spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
127
128 dev->driver->disable_vblank(dev, crtc);
129 dev->vblank_enabled[crtc] = 0;
130
131 /* No further vblank irq's will be processed after
132 * this point. Get current hardware vblank count and
133 * vblank timestamp, repeat until they are consistent.
134 *
135 * FIXME: There is still a race condition here and in
136 * drm_update_vblank_count() which can cause off-by-one
137 * reinitialization of software vblank counter. If gpu
138 * vblank counter doesn't increment exactly at the leading
139 * edge of a vblank interval, then we can lose 1 count if
140 * we happen to execute between start of vblank and the
141 * delayed gpu counter increment.
142 */
143 do {
144 dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
145 vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
146 } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc));
147
148 /* Compute time difference to stored timestamp of last vblank
149 * as updated by last invocation of drm_handle_vblank() in vblank irq.
150 */
151 vblcount = atomic_read(&dev->_vblank_count[crtc]);
152 diff_ns = timeval_to_ns(&tvblank) -
153 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
154
155 /* If there is at least 1 msec difference between the last stored
156 * timestamp and tvblank, then we are currently executing our
157 * disable inside a new vblank interval, the tvblank timestamp
158 * corresponds to this new vblank interval and the irq handler
159 * for this vblank didn't run yet and won't run due to our disable.
160 * Therefore we need to do the job of drm_handle_vblank() and
161 * increment the vblank counter by one to account for this vblank.
162 *
163 * Skip this step if there isn't any high precision timestamp
164 * available. In that case we can't account for this and just
165 * hope for the best.
166 */
167 if ((vblrc > 0) && (abs(diff_ns) > 1000000))
168 atomic_inc(&dev->_vblank_count[crtc]);
169
170 /* Invalidate all timestamps while vblank irq's are off. */
171 clear_vblank_timestamps(dev, crtc);
172
173 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
174 preempt_enable();
175}
176
80static void vblank_disable_fn(unsigned long arg) 177static void vblank_disable_fn(unsigned long arg)
81{ 178{
82 struct drm_device *dev = (struct drm_device *)arg; 179 struct drm_device *dev = (struct drm_device *)arg;
@@ -91,10 +188,7 @@ static void vblank_disable_fn(unsigned long arg)
91 if (atomic_read(&dev->vblank_refcount[i]) == 0 && 188 if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
92 dev->vblank_enabled[i]) { 189 dev->vblank_enabled[i]) {
93 DRM_DEBUG("disabling vblank on crtc %d\n", i); 190 DRM_DEBUG("disabling vblank on crtc %d\n", i);
94 dev->last_vblank[i] = 191 vblank_disable_and_save(dev, i);
95 dev->driver->get_vblank_counter(dev, i);
96 dev->driver->disable_vblank(dev, i);
97 dev->vblank_enabled[i] = 0;
98 } 192 }
99 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 193 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
100 } 194 }
@@ -117,6 +211,7 @@ void drm_vblank_cleanup(struct drm_device *dev)
117 kfree(dev->last_vblank); 211 kfree(dev->last_vblank);
118 kfree(dev->last_vblank_wait); 212 kfree(dev->last_vblank_wait);
119 kfree(dev->vblank_inmodeset); 213 kfree(dev->vblank_inmodeset);
214 kfree(dev->_vblank_time);
120 215
121 dev->num_crtcs = 0; 216 dev->num_crtcs = 0;
122} 217}
@@ -129,6 +224,8 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
129 setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, 224 setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
130 (unsigned long)dev); 225 (unsigned long)dev);
131 spin_lock_init(&dev->vbl_lock); 226 spin_lock_init(&dev->vbl_lock);
227 spin_lock_init(&dev->vblank_time_lock);
228
132 dev->num_crtcs = num_crtcs; 229 dev->num_crtcs = num_crtcs;
133 230
134 dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, 231 dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
@@ -161,6 +258,19 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
161 if (!dev->vblank_inmodeset) 258 if (!dev->vblank_inmodeset)
162 goto err; 259 goto err;
163 260
261 dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE,
262 sizeof(struct timeval), GFP_KERNEL);
263 if (!dev->_vblank_time)
264 goto err;
265
266 DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
267
268 /* Driver specific high-precision vblank timestamping supported? */
269 if (dev->driver->get_vblank_timestamp)
270 DRM_INFO("Driver supports precise vblank timestamp query.\n");
271 else
272 DRM_INFO("No driver support for vblank timestamp query.\n");
273
164 /* Zero per-crtc vblank stuff */ 274 /* Zero per-crtc vblank stuff */
165 for (i = 0; i < num_crtcs; i++) { 275 for (i = 0; i < num_crtcs; i++) {
166 init_waitqueue_head(&dev->vbl_queue[i]); 276 init_waitqueue_head(&dev->vbl_queue[i]);
@@ -279,7 +389,7 @@ EXPORT_SYMBOL(drm_irq_install);
279 * 389 *
280 * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. 390 * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
281 */ 391 */
282int drm_irq_uninstall(struct drm_device * dev) 392int drm_irq_uninstall(struct drm_device *dev)
283{ 393{
284 unsigned long irqflags; 394 unsigned long irqflags;
285 int irq_enabled, i; 395 int irq_enabled, i;
@@ -335,7 +445,9 @@ int drm_control(struct drm_device *dev, void *data,
335{ 445{
336 struct drm_control *ctl = data; 446 struct drm_control *ctl = data;
337 447
338 /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ 448 /* if we haven't irq we fallback for compatibility reasons -
449 * this used to be a separate function in drm_dma.h
450 */
339 451
340 452
341 switch (ctl->func) { 453 switch (ctl->func) {
@@ -360,6 +472,287 @@ int drm_control(struct drm_device *dev, void *data,
360} 472}
361 473
362/** 474/**
475 * drm_calc_timestamping_constants - Calculate and
476 * store various constants which are later needed by
477 * vblank and swap-completion timestamping, e.g, by
478 * drm_calc_vbltimestamp_from_scanoutpos().
479 * They are derived from crtc's true scanout timing,
480 * so they take things like panel scaling or other
481 * adjustments into account.
482 *
483 * @crtc drm_crtc whose timestamp constants should be updated.
484 *
485 */
486void drm_calc_timestamping_constants(struct drm_crtc *crtc)
487{
488 s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
489 u64 dotclock;
490
491 /* Dot clock in Hz: */
492 dotclock = (u64) crtc->hwmode.clock * 1000;
493
494 /* Valid dotclock? */
495 if (dotclock > 0) {
496 /* Convert scanline length in pixels and video dot clock to
497 * line duration, frame duration and pixel duration in
498 * nanoseconds:
499 */
500 pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
501 linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
502 1000000000), dotclock);
503 framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns;
504 } else
505 DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
506 crtc->base.id);
507
508 crtc->pixeldur_ns = pixeldur_ns;
509 crtc->linedur_ns = linedur_ns;
510 crtc->framedur_ns = framedur_ns;
511
512 DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
513 crtc->base.id, crtc->hwmode.crtc_htotal,
514 crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay);
515 DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
516 crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
517 (int) linedur_ns, (int) pixeldur_ns);
518}
519EXPORT_SYMBOL(drm_calc_timestamping_constants);
520
521/**
522 * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms
523 * drivers. Implements calculation of exact vblank timestamps from
524 * given drm_display_mode timings and current video scanout position
525 * of a crtc. This can be called from within get_vblank_timestamp()
526 * implementation of a kms driver to implement the actual timestamping.
527 *
528 * Should return timestamps conforming to the OML_sync_control OpenML
529 * extension specification. The timestamp corresponds to the end of
530 * the vblank interval, aka start of scanout of topmost-leftmost display
531 * pixel in the following video frame.
532 *
533 * Requires support for optional dev->driver->get_scanout_position()
534 * in kms driver, plus a bit of setup code to provide a drm_display_mode
535 * that corresponds to the true scanout timing.
536 *
537 * The current implementation only handles standard video modes. It
538 * returns as no operation if a doublescan or interlaced video mode is
539 * active. Higher level code is expected to handle this.
540 *
541 * @dev: DRM device.
542 * @crtc: Which crtc's vblank timestamp to retrieve.
543 * @max_error: Desired maximum allowable error in timestamps (nanosecs).
544 * On return contains true maximum error of timestamp.
545 * @vblank_time: Pointer to struct timeval which should receive the timestamp.
546 * @flags: Flags to pass to driver:
547 * 0 = Default.
548 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
549 * @refcrtc: drm_crtc* of crtc which defines scanout timing.
550 *
551 * Returns negative value on error, failure or if not supported in current
552 * video mode:
553 *
554 * -EINVAL - Invalid crtc.
555 * -EAGAIN - Temporary unavailable, e.g., called before initial modeset.
556 * -ENOTSUPP - Function not supported in current display mode.
557 * -EIO - Failed, e.g., due to failed scanout position query.
558 *
559 * Returns or'ed positive status flags on success:
560 *
561 * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping.
562 * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
563 *
564 */
565int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
566 int *max_error,
567 struct timeval *vblank_time,
568 unsigned flags,
569 struct drm_crtc *refcrtc)
570{
571 struct timeval stime, raw_time;
572 struct drm_display_mode *mode;
573 int vbl_status, vtotal, vdisplay;
574 int vpos, hpos, i;
575 s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
576 bool invbl;
577
578 if (crtc < 0 || crtc >= dev->num_crtcs) {
579 DRM_ERROR("Invalid crtc %d\n", crtc);
580 return -EINVAL;
581 }
582
583 /* Scanout position query not supported? Should not happen. */
584 if (!dev->driver->get_scanout_position) {
585 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
586 return -EIO;
587 }
588
589 mode = &refcrtc->hwmode;
590 vtotal = mode->crtc_vtotal;
591 vdisplay = mode->crtc_vdisplay;
592
593 /* Durations of frames, lines, pixels in nanoseconds. */
594 framedur_ns = refcrtc->framedur_ns;
595 linedur_ns = refcrtc->linedur_ns;
596 pixeldur_ns = refcrtc->pixeldur_ns;
597
598 /* If mode timing undefined, just return as no-op:
599 * Happens during initial modesetting of a crtc.
600 */
601 if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) {
602 DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
603 return -EAGAIN;
604 }
605
606 /* Don't know yet how to handle interlaced or
607 * double scan modes. Just no-op for now.
608 */
609 if (mode->flags & (DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN)) {
610 DRM_DEBUG("crtc %d: Noop due to unsupported mode.\n", crtc);
611 return -ENOTSUPP;
612 }
613
614 /* Get current scanout position with system timestamp.
615 * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
616 * if single query takes longer than max_error nanoseconds.
617 *
618 * This guarantees a tight bound on maximum error if
619 * code gets preempted or delayed for some reason.
620 */
621 for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
622 /* Disable preemption to make it very likely to
623 * succeed in the first iteration even on PREEMPT_RT kernel.
624 */
625 preempt_disable();
626
627 /* Get system timestamp before query. */
628 do_gettimeofday(&stime);
629
630 /* Get vertical and horizontal scanout pos. vpos, hpos. */
631 vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos);
632
633 /* Get system timestamp after query. */
634 do_gettimeofday(&raw_time);
635
636 preempt_enable();
637
638 /* Return as no-op if scanout query unsupported or failed. */
639 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
640 DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
641 crtc, vbl_status);
642 return -EIO;
643 }
644
645 duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime);
646
647 /* Accept result with < max_error nsecs timing uncertainty. */
648 if (duration_ns <= (s64) *max_error)
649 break;
650 }
651
652 /* Noisy system timing? */
653 if (i == DRM_TIMESTAMP_MAXRETRIES) {
654 DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
655 crtc, (int) duration_ns/1000, *max_error/1000, i);
656 }
657
658 /* Return upper bound of timestamp precision error. */
659 *max_error = (int) duration_ns;
660
661 /* Check if in vblank area:
662 * vpos is >=0 in video scanout area, but negative
663 * within vblank area, counting down the number of lines until
664 * start of scanout.
665 */
666 invbl = vbl_status & DRM_SCANOUTPOS_INVBL;
667
668 /* Convert scanout position into elapsed time at raw_time query
669 * since start of scanout at first display scanline. delta_ns
670 * can be negative if start of scanout hasn't happened yet.
671 */
672 delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
673
674 /* Is vpos outside nominal vblank area, but less than
675 * 1/100 of a frame height away from start of vblank?
676 * If so, assume this isn't a massively delayed vblank
677 * interrupt, but a vblank interrupt that fired a few
678 * microseconds before true start of vblank. Compensate
679 * by adding a full frame duration to the final timestamp.
680 * Happens, e.g., on ATI R500, R600.
681 *
682 * We only do this if DRM_CALLED_FROM_VBLIRQ.
683 */
684 if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
685 ((vdisplay - vpos) < vtotal / 100)) {
686 delta_ns = delta_ns - framedur_ns;
687
688 /* Signal this correction as "applied". */
689 vbl_status |= 0x8;
690 }
691
692 /* Subtract time delta from raw timestamp to get final
693 * vblank_time timestamp for end of vblank.
694 */
695 *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns);
696
697 DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %d.%d -> %d.%d [e %d us, %d rep]\n",
698 crtc, (int) vbl_status, hpos, vpos, raw_time.tv_sec,
699 raw_time.tv_usec, vblank_time->tv_sec, vblank_time->tv_usec,
700 (int) duration_ns/1000, i);
701
702 vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
703 if (invbl)
704 vbl_status |= DRM_VBLANKTIME_INVBL;
705
706 return vbl_status;
707}
708EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
709
710/**
711 * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
712 * vblank interval.
713 *
714 * @dev: DRM device
715 * @crtc: which crtc's vblank timestamp to retrieve
716 * @tvblank: Pointer to target struct timeval which should receive the timestamp
717 * @flags: Flags to pass to driver:
718 * 0 = Default.
719 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
720 *
721 * Fetches the system timestamp corresponding to the time of the most recent
722 * vblank interval on specified crtc. May call into kms-driver to
723 * compute the timestamp with a high-precision GPU specific method.
724 *
725 * Returns zero if timestamp originates from uncorrected do_gettimeofday()
726 * call, i.e., it isn't very precisely locked to the true vblank.
727 *
728 * Returns non-zero if timestamp is considered to be very precise.
729 */
730u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
731 struct timeval *tvblank, unsigned flags)
732{
733 int ret = 0;
734
735 /* Define requested maximum error on timestamps (nanoseconds). */
736 int max_error = (int) drm_timestamp_precision * 1000;
737
738 /* Query driver if possible and precision timestamping enabled. */
739 if (dev->driver->get_vblank_timestamp && (max_error > 0)) {
740 ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
741 tvblank, flags);
742 if (ret > 0)
743 return (u32) ret;
744 }
745
746 /* GPU high precision timestamp query unsupported or failed.
747 * Return gettimeofday timestamp as best estimate.
748 */
749 do_gettimeofday(tvblank);
750
751 return 0;
752}
753EXPORT_SYMBOL(drm_get_last_vbltimestamp);
754
755/**
363 * drm_vblank_count - retrieve "cooked" vblank counter value 756 * drm_vblank_count - retrieve "cooked" vblank counter value
364 * @dev: DRM device 757 * @dev: DRM device
365 * @crtc: which counter to retrieve 758 * @crtc: which counter to retrieve
@@ -375,6 +768,40 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc)
375EXPORT_SYMBOL(drm_vblank_count); 768EXPORT_SYMBOL(drm_vblank_count);
376 769
377/** 770/**
771 * drm_vblank_count_and_time - retrieve "cooked" vblank counter value
772 * and the system timestamp corresponding to that vblank counter value.
773 *
774 * @dev: DRM device
775 * @crtc: which counter to retrieve
776 * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
777 *
778 * Fetches the "cooked" vblank count value that represents the number of
779 * vblank events since the system was booted, including lost events due to
780 * modesetting activity. Returns corresponding system timestamp of the time
781 * of the vblank interval that corresponds to the current value vblank counter
782 * value.
783 */
784u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
785 struct timeval *vblanktime)
786{
787 u32 cur_vblank;
788
789 /* Read timestamp from slot of _vblank_time ringbuffer
790 * that corresponds to current vblank count. Retry if
791 * count has incremented during readout. This works like
792 * a seqlock.
793 */
794 do {
795 cur_vblank = atomic_read(&dev->_vblank_count[crtc]);
796 *vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
797 smp_rmb();
798 } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc]));
799
800 return cur_vblank;
801}
802EXPORT_SYMBOL(drm_vblank_count_and_time);
803
804/**
378 * drm_update_vblank_count - update the master vblank counter 805 * drm_update_vblank_count - update the master vblank counter
379 * @dev: DRM device 806 * @dev: DRM device
380 * @crtc: counter to update 807 * @crtc: counter to update
@@ -392,7 +819,8 @@ EXPORT_SYMBOL(drm_vblank_count);
392 */ 819 */
393static void drm_update_vblank_count(struct drm_device *dev, int crtc) 820static void drm_update_vblank_count(struct drm_device *dev, int crtc)
394{ 821{
395 u32 cur_vblank, diff; 822 u32 cur_vblank, diff, tslot, rc;
823 struct timeval t_vblank;
396 824
397 /* 825 /*
398 * Interrupts were disabled prior to this call, so deal with counter 826 * Interrupts were disabled prior to this call, so deal with counter
@@ -400,8 +828,18 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
400 * NOTE! It's possible we lost a full dev->max_vblank_count events 828 * NOTE! It's possible we lost a full dev->max_vblank_count events
401 * here if the register is small or we had vblank interrupts off for 829 * here if the register is small or we had vblank interrupts off for
402 * a long time. 830 * a long time.
831 *
832 * We repeat the hardware vblank counter & timestamp query until
833 * we get consistent results. This to prevent races between gpu
834 * updating its hardware counter while we are retrieving the
835 * corresponding vblank timestamp.
403 */ 836 */
404 cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 837 do {
838 cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
839 rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
840 } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
841
842 /* Deal with counter wrap */
405 diff = cur_vblank - dev->last_vblank[crtc]; 843 diff = cur_vblank - dev->last_vblank[crtc];
406 if (cur_vblank < dev->last_vblank[crtc]) { 844 if (cur_vblank < dev->last_vblank[crtc]) {
407 diff += dev->max_vblank_count; 845 diff += dev->max_vblank_count;
@@ -413,6 +851,16 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
413 DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 851 DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
414 crtc, diff); 852 crtc, diff);
415 853
854 /* Reinitialize corresponding vblank timestamp if high-precision query
855 * available. Skip this step if query unsupported or failed. Will
856 * reinitialize delayed at next vblank interrupt in that case.
857 */
858 if (rc) {
859 tslot = atomic_read(&dev->_vblank_count[crtc]) + diff;
860 vblanktimestamp(dev, crtc, tslot) = t_vblank;
861 smp_wmb();
862 }
863
416 atomic_add(diff, &dev->_vblank_count[crtc]); 864 atomic_add(diff, &dev->_vblank_count[crtc]);
417} 865}
418 866
@@ -429,15 +877,27 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
429 */ 877 */
430int drm_vblank_get(struct drm_device *dev, int crtc) 878int drm_vblank_get(struct drm_device *dev, int crtc)
431{ 879{
432 unsigned long irqflags; 880 unsigned long irqflags, irqflags2;
433 int ret = 0; 881 int ret = 0;
434 882
435 spin_lock_irqsave(&dev->vbl_lock, irqflags); 883 spin_lock_irqsave(&dev->vbl_lock, irqflags);
436 /* Going from 0->1 means we have to enable interrupts again */ 884 /* Going from 0->1 means we have to enable interrupts again */
437 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { 885 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
886 /* Disable preemption while holding vblank_time_lock. Do
887 * it explicitely to guard against PREEMPT_RT kernel.
888 */
889 preempt_disable();
890 spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
438 if (!dev->vblank_enabled[crtc]) { 891 if (!dev->vblank_enabled[crtc]) {
892 /* Enable vblank irqs under vblank_time_lock protection.
893 * All vblank count & timestamp updates are held off
894 * until we are done reinitializing master counter and
895 * timestamps. Filtercode in drm_handle_vblank() will
896 * prevent double-accounting of same vblank interval.
897 */
439 ret = dev->driver->enable_vblank(dev, crtc); 898 ret = dev->driver->enable_vblank(dev, crtc);
440 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); 899 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n",
900 crtc, ret);
441 if (ret) 901 if (ret)
442 atomic_dec(&dev->vblank_refcount[crtc]); 902 atomic_dec(&dev->vblank_refcount[crtc]);
443 else { 903 else {
@@ -445,6 +905,8 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
445 drm_update_vblank_count(dev, crtc); 905 drm_update_vblank_count(dev, crtc);
446 } 906 }
447 } 907 }
908 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
909 preempt_enable();
448 } else { 910 } else {
449 if (!dev->vblank_enabled[crtc]) { 911 if (!dev->vblank_enabled[crtc]) {
450 atomic_dec(&dev->vblank_refcount[crtc]); 912 atomic_dec(&dev->vblank_refcount[crtc]);
@@ -463,15 +925,17 @@ EXPORT_SYMBOL(drm_vblank_get);
463 * @crtc: which counter to give up 925 * @crtc: which counter to give up
464 * 926 *
465 * Release ownership of a given vblank counter, turning off interrupts 927 * Release ownership of a given vblank counter, turning off interrupts
466 * if possible. 928 * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
467 */ 929 */
468void drm_vblank_put(struct drm_device *dev, int crtc) 930void drm_vblank_put(struct drm_device *dev, int crtc)
469{ 931{
470 BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); 932 BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0);
471 933
472 /* Last user schedules interrupt disable */ 934 /* Last user schedules interrupt disable */
473 if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) 935 if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) &&
474 mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); 936 (drm_vblank_offdelay > 0))
937 mod_timer(&dev->vblank_disable_timer,
938 jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
475} 939}
476EXPORT_SYMBOL(drm_vblank_put); 940EXPORT_SYMBOL(drm_vblank_put);
477 941
@@ -480,10 +944,8 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
480 unsigned long irqflags; 944 unsigned long irqflags;
481 945
482 spin_lock_irqsave(&dev->vbl_lock, irqflags); 946 spin_lock_irqsave(&dev->vbl_lock, irqflags);
483 dev->driver->disable_vblank(dev, crtc); 947 vblank_disable_and_save(dev, crtc);
484 DRM_WAKEUP(&dev->vbl_queue[crtc]); 948 DRM_WAKEUP(&dev->vbl_queue[crtc]);
485 dev->vblank_enabled[crtc] = 0;
486 dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
487 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 949 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
488} 950}
489EXPORT_SYMBOL(drm_vblank_off); 951EXPORT_SYMBOL(drm_vblank_off);
@@ -599,7 +1061,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
599 e->base.file_priv = file_priv; 1061 e->base.file_priv = file_priv;
600 e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; 1062 e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
601 1063
602 do_gettimeofday(&now);
603 spin_lock_irqsave(&dev->event_lock, flags); 1064 spin_lock_irqsave(&dev->event_lock, flags);
604 1065
605 if (file_priv->event_space < sizeof e->event) { 1066 if (file_priv->event_space < sizeof e->event) {
@@ -609,7 +1070,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
609 } 1070 }
610 1071
611 file_priv->event_space -= sizeof e->event; 1072 file_priv->event_space -= sizeof e->event;
612 seq = drm_vblank_count(dev, pipe); 1073 seq = drm_vblank_count_and_time(dev, pipe, &now);
1074
613 if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && 1075 if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
614 (seq - vblwait->request.sequence) <= (1 << 23)) { 1076 (seq - vblwait->request.sequence) <= (1 << 23)) {
615 vblwait->request.sequence = seq + 1; 1077 vblwait->request.sequence = seq + 1;
@@ -718,11 +1180,10 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
718 if (ret != -EINTR) { 1180 if (ret != -EINTR) {
719 struct timeval now; 1181 struct timeval now;
720 1182
721 do_gettimeofday(&now); 1183 vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now);
722
723 vblwait->reply.tval_sec = now.tv_sec; 1184 vblwait->reply.tval_sec = now.tv_sec;
724 vblwait->reply.tval_usec = now.tv_usec; 1185 vblwait->reply.tval_usec = now.tv_usec;
725 vblwait->reply.sequence = drm_vblank_count(dev, crtc); 1186
726 DRM_DEBUG("returning %d to client\n", 1187 DRM_DEBUG("returning %d to client\n",
727 vblwait->reply.sequence); 1188 vblwait->reply.sequence);
728 } else { 1189 } else {
@@ -741,8 +1202,7 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
741 unsigned long flags; 1202 unsigned long flags;
742 unsigned int seq; 1203 unsigned int seq;
743 1204
744 do_gettimeofday(&now); 1205 seq = drm_vblank_count_and_time(dev, crtc, &now);
745 seq = drm_vblank_count(dev, crtc);
746 1206
747 spin_lock_irqsave(&dev->event_lock, flags); 1207 spin_lock_irqsave(&dev->event_lock, flags);
748 1208
@@ -780,11 +1240,64 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
780 */ 1240 */
781void drm_handle_vblank(struct drm_device *dev, int crtc) 1241void drm_handle_vblank(struct drm_device *dev, int crtc)
782{ 1242{
1243 u32 vblcount;
1244 s64 diff_ns;
1245 struct timeval tvblank;
1246 unsigned long irqflags;
1247
783 if (!dev->num_crtcs) 1248 if (!dev->num_crtcs)
784 return; 1249 return;
785 1250
786 atomic_inc(&dev->_vblank_count[crtc]); 1251 /* Need timestamp lock to prevent concurrent execution with
1252 * vblank enable/disable, as this would cause inconsistent
1253 * or corrupted timestamps and vblank counts.
1254 */
1255 spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
1256
1257 /* Vblank irq handling disabled. Nothing to do. */
1258 if (!dev->vblank_enabled[crtc]) {
1259 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
1260 return;
1261 }
1262
1263 /* Fetch corresponding timestamp for this vblank interval from
1264 * driver and store it in proper slot of timestamp ringbuffer.
1265 */
1266
1267 /* Get current timestamp and count. */
1268 vblcount = atomic_read(&dev->_vblank_count[crtc]);
1269 drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
1270
1271 /* Compute time difference to timestamp of last vblank */
1272 diff_ns = timeval_to_ns(&tvblank) -
1273 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
1274
1275 /* Update vblank timestamp and count if at least
1276 * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
1277 * difference between last stored timestamp and current
1278 * timestamp. A smaller difference means basically
1279 * identical timestamps. Happens if this vblank has
1280 * been already processed and this is a redundant call,
1281 * e.g., due to spurious vblank interrupts. We need to
1282 * ignore those for accounting.
1283 */
1284 if (abs(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) {
1285 /* Store new timestamp in ringbuffer. */
1286 vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
1287 smp_wmb();
1288
1289 /* Increment cooked vblank count. This also atomically commits
1290 * the timestamp computed above.
1291 */
1292 atomic_inc(&dev->_vblank_count[crtc]);
1293 } else {
1294 DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
1295 crtc, (int) diff_ns);
1296 }
1297
787 DRM_WAKEUP(&dev->vbl_queue[crtc]); 1298 DRM_WAKEUP(&dev->vbl_queue[crtc]);
788 drm_handle_vblank_events(dev, crtc); 1299 drm_handle_vblank_events(dev, crtc);
1300
1301 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
789} 1302}
790EXPORT_SYMBOL(drm_handle_vblank); 1303EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index cdc89ee042cc..d59edc18301f 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -40,12 +40,22 @@
40unsigned int drm_debug = 0; /* 1 to enable debug output */ 40unsigned int drm_debug = 0; /* 1 to enable debug output */
41EXPORT_SYMBOL(drm_debug); 41EXPORT_SYMBOL(drm_debug);
42 42
43unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
44EXPORT_SYMBOL(drm_vblank_offdelay);
45
46unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
47EXPORT_SYMBOL(drm_timestamp_precision);
48
43MODULE_AUTHOR(CORE_AUTHOR); 49MODULE_AUTHOR(CORE_AUTHOR);
44MODULE_DESCRIPTION(CORE_DESC); 50MODULE_DESCRIPTION(CORE_DESC);
45MODULE_LICENSE("GPL and additional rights"); 51MODULE_LICENSE("GPL and additional rights");
46MODULE_PARM_DESC(debug, "Enable debug output"); 52MODULE_PARM_DESC(debug, "Enable debug output");
53MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
54MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
47 55
48module_param_named(debug, drm_debug, int, 0600); 56module_param_named(debug, drm_debug, int, 0600);
57module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
58module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
49 59
50struct idr drm_minors_idr; 60struct idr drm_minors_idr;
51 61
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 274eaaa15c36..2b3398004aa5 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -683,6 +683,21 @@ struct drm_master {
683 void *driver_priv; /**< Private structure for driver to use */ 683 void *driver_priv; /**< Private structure for driver to use */
684}; 684};
685 685
686/* Size of ringbuffer for vblank timestamps. Just double-buffer
687 * in initial implementation.
688 */
689#define DRM_VBLANKTIME_RBSIZE 2
690
691/* Flags and return codes for get_vblank_timestamp() driver function. */
692#define DRM_CALLED_FROM_VBLIRQ 1
693#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
694#define DRM_VBLANKTIME_INVBL (1 << 1)
695
696/* get_scanout_position() return flags */
697#define DRM_SCANOUTPOS_VALID (1 << 0)
698#define DRM_SCANOUTPOS_INVBL (1 << 1)
699#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
700
686/** 701/**
687 * DRM driver structure. This structure represent the common code for 702 * DRM driver structure. This structure represent the common code for
688 * a family of cards. There will one drm_device for each card present 703 * a family of cards. There will one drm_device for each card present
@@ -760,6 +775,68 @@ struct drm_driver {
760 */ 775 */
761 int (*device_is_agp) (struct drm_device *dev); 776 int (*device_is_agp) (struct drm_device *dev);
762 777
778 /**
779 * Called by vblank timestamping code.
780 *
781 * Return the current display scanout position from a crtc.
782 *
783 * \param dev DRM device.
784 * \param crtc Id of the crtc to query.
785 * \param *vpos Target location for current vertical scanout position.
786 * \param *hpos Target location for current horizontal scanout position.
787 *
788 * Returns vpos as a positive number while in active scanout area.
789 * Returns vpos as a negative number inside vblank, counting the number
790 * of scanlines to go until end of vblank, e.g., -1 means "one scanline
791 * until start of active scanout / end of vblank."
792 *
793 * \return Flags, or'ed together as follows:
794 *
795 * DRM_SCANOUTPOS_VALID = Query successfull.
796 * DRM_SCANOUTPOS_INVBL = Inside vblank.
797 * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
798 * this flag means that returned position may be offset by a constant
799 * but unknown small number of scanlines wrt. real scanout position.
800 *
801 */
802 int (*get_scanout_position) (struct drm_device *dev, int crtc,
803 int *vpos, int *hpos);
804
805 /**
806 * Called by \c drm_get_last_vbltimestamp. Should return a precise
807 * timestamp when the most recent VBLANK interval ended or will end.
808 *
809 * Specifically, the timestamp in @vblank_time should correspond as
810 * closely as possible to the time when the first video scanline of
811 * the video frame after the end of VBLANK will start scanning out,
812 * the time immmediately after end of the VBLANK interval. If the
813 * @crtc is currently inside VBLANK, this will be a time in the future.
814 * If the @crtc is currently scanning out a frame, this will be the
815 * past start time of the current scanout. This is meant to adhere
816 * to the OpenML OML_sync_control extension specification.
817 *
818 * \param dev dev DRM device handle.
819 * \param crtc crtc for which timestamp should be returned.
820 * \param *max_error Maximum allowable timestamp error in nanoseconds.
821 * Implementation should strive to provide timestamp
822 * with an error of at most *max_error nanoseconds.
823 * Returns true upper bound on error for timestamp.
824 * \param *vblank_time Target location for returned vblank timestamp.
825 * \param flags 0 = Defaults, no special treatment needed.
826 * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
827 * irq handler. Some drivers need to apply some workarounds
828 * for gpu-specific vblank irq quirks if flag is set.
829 *
830 * \returns
831 * Zero if timestamping isn't supported in current display mode or a
832 * negative number on failure. A positive status code on success,
833 * which describes how the vblank_time timestamp was computed.
834 */
835 int (*get_vblank_timestamp) (struct drm_device *dev, int crtc,
836 int *max_error,
837 struct timeval *vblank_time,
838 unsigned flags);
839
763 /* these have to be filled in */ 840 /* these have to be filled in */
764 841
765 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); 842 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
@@ -983,6 +1060,8 @@ struct drm_device {
983 1060
984 wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ 1061 wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */
985 atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ 1062 atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
1063 struct timeval *_vblank_time; /**< timestamp of current vblank_count (drivers must alloc right number of fields) */
1064 spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
986 spinlock_t vbl_lock; 1065 spinlock_t vbl_lock;
987 atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */ 1066 atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */
988 u32 *last_vblank; /* protected by dev->vbl_lock, used */ 1067 u32 *last_vblank; /* protected by dev->vbl_lock, used */
@@ -1284,11 +1363,22 @@ extern int drm_wait_vblank(struct drm_device *dev, void *data,
1284 struct drm_file *filp); 1363 struct drm_file *filp);
1285extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); 1364extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
1286extern u32 drm_vblank_count(struct drm_device *dev, int crtc); 1365extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
1366extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
1367 struct timeval *vblanktime);
1287extern void drm_handle_vblank(struct drm_device *dev, int crtc); 1368extern void drm_handle_vblank(struct drm_device *dev, int crtc);
1288extern int drm_vblank_get(struct drm_device *dev, int crtc); 1369extern int drm_vblank_get(struct drm_device *dev, int crtc);
1289extern void drm_vblank_put(struct drm_device *dev, int crtc); 1370extern void drm_vblank_put(struct drm_device *dev, int crtc);
1290extern void drm_vblank_off(struct drm_device *dev, int crtc); 1371extern void drm_vblank_off(struct drm_device *dev, int crtc);
1291extern void drm_vblank_cleanup(struct drm_device *dev); 1372extern void drm_vblank_cleanup(struct drm_device *dev);
1373extern u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
1374 struct timeval *tvblank, unsigned flags);
1375extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
1376 int crtc, int *max_error,
1377 struct timeval *vblank_time,
1378 unsigned flags,
1379 struct drm_crtc *refcrtc);
1380extern void drm_calc_timestamping_constants(struct drm_crtc *crtc);
1381
1292/* Modesetting support */ 1382/* Modesetting support */
1293extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); 1383extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
1294extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); 1384extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
@@ -1340,6 +1430,9 @@ extern void drm_put_dev(struct drm_device *dev);
1340extern int drm_put_minor(struct drm_minor **minor); 1430extern int drm_put_minor(struct drm_minor **minor);
1341extern unsigned int drm_debug; 1431extern unsigned int drm_debug;
1342 1432
1433extern unsigned int drm_vblank_offdelay;
1434extern unsigned int drm_timestamp_precision;
1435
1343extern struct class *drm_class; 1436extern struct class *drm_class;
1344extern struct proc_dir_entry *drm_proc_root; 1437extern struct proc_dir_entry *drm_proc_root;
1345extern struct dentry *drm_debugfs_root; 1438extern struct dentry *drm_debugfs_root;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 029aa688e787..acd7fade160d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -351,8 +351,14 @@ struct drm_crtc {
351 351
352 bool enabled; 352 bool enabled;
353 353
354 /* Requested mode from modesetting. */
354 struct drm_display_mode mode; 355 struct drm_display_mode mode;
355 356
357 /* Programmed mode in hw, after adjustments for encoders,
358 * crtc, panel scaling etc. Needed for timestamping etc.
359 */
360 struct drm_display_mode hwmode;
361
356 int x, y; 362 int x, y;
357 const struct drm_crtc_funcs *funcs; 363 const struct drm_crtc_funcs *funcs;
358 364
@@ -360,6 +366,9 @@ struct drm_crtc {
360 uint32_t gamma_size; 366 uint32_t gamma_size;
361 uint16_t *gamma_store; 367 uint16_t *gamma_store;
362 368
369 /* Constants needed for precise vblank and swap timestamping. */
370 s64 framedur_ns, linedur_ns, pixeldur_ns;
371
363 /* if you are using the helper */ 372 /* if you are using the helper */
364 void *helper_private; 373 void *helper_private;
365}; 374};