.. | .. |
---|
24 | 24 | * OTHER DEALINGS IN THE SOFTWARE. |
---|
25 | 25 | */ |
---|
26 | 26 | |
---|
27 | | -#include <drm/drm_vblank.h> |
---|
28 | | -#include <drm/drmP.h> |
---|
29 | 27 | #include <linux/export.h> |
---|
| 28 | +#include <linux/kthread.h> |
---|
| 29 | +#include <linux/moduleparam.h> |
---|
30 | 30 | |
---|
31 | | -#include "drm_trace.h" |
---|
| 31 | +#include <drm/drm_crtc.h> |
---|
| 32 | +#include <drm/drm_drv.h> |
---|
| 33 | +#include <drm/drm_framebuffer.h> |
---|
| 34 | +#include <drm/drm_managed.h> |
---|
| 35 | +#include <drm/drm_modeset_helper_vtables.h> |
---|
| 36 | +#include <drm/drm_print.h> |
---|
| 37 | +#include <drm/drm_vblank.h> |
---|
| 38 | + |
---|
32 | 39 | #include "drm_internal.h" |
---|
| 40 | +#include "drm_trace.h" |
---|
33 | 41 | |
---|
34 | 42 | /** |
---|
35 | 43 | * DOC: vblank handling |
---|
| 44 | + * |
---|
| 45 | + * From the computer's perspective, every time the monitor displays |
---|
| 46 | + * a new frame the scanout engine has "scanned out" the display image |
---|
| 47 | + * from top to bottom, one row of pixels at a time. The current row |
---|
| 48 | + * of pixels is referred to as the current scanline. |
---|
| 49 | + * |
---|
| 50 | + * In addition to the display's visible area, there's usually a couple of |
---|
| 51 | + * extra scanlines which aren't actually displayed on the screen. |
---|
| 52 | + * These extra scanlines don't contain image data and are occasionally used |
---|
| 53 | + * for features like audio and infoframes. The region made up of these |
---|
| 54 | + * scanlines is referred to as the vertical blanking region, or vblank for |
---|
| 55 | + * short. |
---|
| 56 | + * |
---|
| 57 | + * For historical reference, the vertical blanking period was designed to |
---|
| 58 | + * give the electron gun (on CRTs) enough time to move back to the top of |
---|
| 59 | + * the screen to start scanning out the next frame. Similar for horizontal |
---|
| 60 | + * blanking periods. They were designed to give the electron gun enough |
---|
| 61 | + * time to move back to the other side of the screen to start scanning the |
---|
| 62 | + * next scanline. |
---|
| 63 | + * |
---|
| 64 | + * :: |
---|
| 65 | + * |
---|
| 66 | + * |
---|
| 67 | + * physical → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ |
---|
| 68 | + * top of | | |
---|
| 69 | + * display | | |
---|
| 70 | + * | New frame | |
---|
| 71 | + * | | |
---|
| 72 | + * |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓| |
---|
| 73 | + * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| ← Scanline, |
---|
| 74 | + * |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓| updates the |
---|
| 75 | + * | | frame as it |
---|
| 76 | + * | | travels down |
---|
| 77 | + * | | ("sacn out") |
---|
| 78 | + * | Old frame | |
---|
| 79 | + * | | |
---|
| 80 | + * | | |
---|
| 81 | + * | | |
---|
| 82 | + * | | physical |
---|
| 83 | + * | | bottom of |
---|
| 84 | + * vertical |⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽| ← display |
---|
| 85 | + * blanking ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆ |
---|
| 86 | + * region → ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆ |
---|
| 87 | + * ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆ |
---|
| 88 | + * start of → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ |
---|
| 89 | + * new frame |
---|
| 90 | + * |
---|
| 91 | + * "Physical top of display" is the reference point for the high-precision/ |
---|
| 92 | + * corrected timestamp. |
---|
| 93 | + * |
---|
| 94 | + * On a lot of display hardware, programming needs to take effect during the |
---|
| 95 | + * vertical blanking period so that settings like gamma, the image buffer |
---|
| 96 | + * buffer to be scanned out, etc. can safely be changed without showing |
---|
| 97 | + * any visual artifacts on the screen. In some unforgiving hardware, some of |
---|
| 98 | + * this programming has to both start and end in the same vblank. To help |
---|
| 99 | + * with the timing of the hardware programming, an interrupt is usually |
---|
| 100 | + * available to notify the driver when it can start the updating of registers. |
---|
| 101 | + * The interrupt is in this context named the vblank interrupt. |
---|
| 102 | + * |
---|
| 103 | + * The vblank interrupt may be fired at different points depending on the |
---|
| 104 | + * hardware. Some hardware implementations will fire the interrupt when the |
---|
| 105 | + * new frame start, other implementations will fire the interrupt at different |
---|
| 106 | + * points in time. |
---|
36 | 107 | * |
---|
37 | 108 | * Vertical blanking plays a major role in graphics rendering. To achieve |
---|
38 | 109 | * tear-free display, users must synchronize page flips and/or rendering to |
---|
.. | .. |
---|
48 | 119 | * Drivers must initialize the vertical blanking handling core with a call to |
---|
49 | 120 | * drm_vblank_init(). Minimally, a driver needs to implement |
---|
50 | 121 | * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call |
---|
51 | | - * drm_crtc_handle_vblank() in it's vblank interrupt handler for working vblank |
---|
| 122 | + * drm_crtc_handle_vblank() in its vblank interrupt handler for working vblank |
---|
52 | 123 | * support. |
---|
53 | 124 | * |
---|
54 | 125 | * Vertical blanking interrupts can be enabled by the DRM core or by drivers |
---|
.. | .. |
---|
64 | 135 | * &drm_driver.max_vblank_count. In that case the vblank core only disables the |
---|
65 | 136 | * vblanks after a timer has expired, which can be configured through the |
---|
66 | 137 | * ``vblankoffdelay`` module parameter. |
---|
| 138 | + * |
---|
| 139 | + * Drivers for hardware without support for vertical-blanking interrupts |
---|
| 140 | + * must not call drm_vblank_init(). For such drivers, atomic helpers will |
---|
| 141 | + * automatically generate fake vblank events as part of the display update. |
---|
| 142 | + * This functionality also can be controlled by the driver by enabling and |
---|
| 143 | + * disabling struct drm_crtc_state.no_vblank. |
---|
67 | 144 | */ |
---|
68 | 145 | |
---|
69 | 146 | /* Retry timestamp calculation up to 3 times to satisfy |
---|
.. | .. |
---|
101 | 178 | |
---|
102 | 179 | write_seqlock(&vblank->seqlock); |
---|
103 | 180 | vblank->time = t_vblank; |
---|
104 | | - vblank->count += vblank_count_inc; |
---|
| 181 | + atomic64_add(vblank_count_inc, &vblank->count); |
---|
105 | 182 | write_sequnlock(&vblank->seqlock); |
---|
106 | 183 | } |
---|
107 | 184 | |
---|
.. | .. |
---|
118 | 195 | */ |
---|
119 | 196 | static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe) |
---|
120 | 197 | { |
---|
121 | | - WARN_ON_ONCE(drm_max_vblank_count(dev, pipe) != 0); |
---|
| 198 | + drm_WARN_ON_ONCE(dev, drm_max_vblank_count(dev, pipe) != 0); |
---|
122 | 199 | return 0; |
---|
123 | 200 | } |
---|
124 | 201 | |
---|
.. | .. |
---|
127 | 204 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
---|
128 | 205 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
129 | 206 | |
---|
130 | | - if (WARN_ON(!crtc)) |
---|
| 207 | + if (drm_WARN_ON(dev, !crtc)) |
---|
131 | 208 | return 0; |
---|
132 | 209 | |
---|
133 | 210 | if (crtc->funcs->get_vblank_counter) |
---|
134 | 211 | return crtc->funcs->get_vblank_counter(crtc); |
---|
135 | | - } |
---|
136 | | - |
---|
137 | | - if (dev->driver->get_vblank_counter) |
---|
| 212 | + } else if (dev->driver->get_vblank_counter) { |
---|
138 | 213 | return dev->driver->get_vblank_counter(dev, pipe); |
---|
| 214 | + } |
---|
139 | 215 | |
---|
140 | 216 | return drm_vblank_no_hw_counter(dev, pipe); |
---|
141 | 217 | } |
---|
.. | .. |
---|
235 | 311 | * on the difference in the timestamps and the |
---|
236 | 312 | * frame/field duration. |
---|
237 | 313 | */ |
---|
| 314 | + |
---|
| 315 | + drm_dbg_vbl(dev, "crtc %u: Calculating number of vblanks." |
---|
| 316 | + " diff_ns = %lld, framedur_ns = %d)\n", |
---|
| 317 | + pipe, (long long)diff_ns, framedur_ns); |
---|
| 318 | + |
---|
238 | 319 | diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); |
---|
239 | 320 | |
---|
240 | 321 | if (diff == 0 && in_vblank_irq) |
---|
241 | | - DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." |
---|
242 | | - " diff_ns = %lld, framedur_ns = %d)\n", |
---|
243 | | - pipe, (long long) diff_ns, framedur_ns); |
---|
| 322 | + drm_dbg_vbl(dev, "crtc %u: Redundant vblirq ignored\n", |
---|
| 323 | + pipe); |
---|
244 | 324 | } else { |
---|
245 | 325 | /* some kind of default for drivers w/o accurate vbl timestamping */ |
---|
246 | 326 | diff = in_vblank_irq ? 1 : 0; |
---|
.. | .. |
---|
256 | 336 | * random large forward jumps of the software vblank counter. |
---|
257 | 337 | */ |
---|
258 | 338 | if (diff > 1 && (vblank->inmodeset & 0x2)) { |
---|
259 | | - DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u" |
---|
260 | | - " due to pre-modeset.\n", pipe, diff); |
---|
| 339 | + drm_dbg_vbl(dev, |
---|
| 340 | + "clamping vblank bump to 1 on crtc %u: diffr=%u" |
---|
| 341 | + " due to pre-modeset.\n", pipe, diff); |
---|
261 | 342 | diff = 1; |
---|
262 | 343 | } |
---|
263 | 344 | |
---|
264 | | - DRM_DEBUG_VBL("updating vblank count on crtc %u:" |
---|
265 | | - " current=%llu, diff=%u, hw=%u hw_last=%u\n", |
---|
266 | | - pipe, vblank->count, diff, cur_vblank, vblank->last); |
---|
| 345 | + drm_dbg_vbl(dev, "updating vblank count on crtc %u:" |
---|
| 346 | + " current=%llu, diff=%u, hw=%u hw_last=%u\n", |
---|
| 347 | + pipe, (unsigned long long)atomic64_read(&vblank->count), |
---|
| 348 | + diff, cur_vblank, vblank->last); |
---|
267 | 349 | |
---|
268 | 350 | if (diff == 0) { |
---|
269 | | - WARN_ON_ONCE(cur_vblank != vblank->last); |
---|
| 351 | + drm_WARN_ON_ONCE(dev, cur_vblank != vblank->last); |
---|
270 | 352 | return; |
---|
271 | 353 | } |
---|
272 | 354 | |
---|
.. | .. |
---|
282 | 364 | store_vblank(dev, pipe, diff, t_vblank, cur_vblank); |
---|
283 | 365 | } |
---|
284 | 366 | |
---|
285 | | -static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) |
---|
| 367 | +u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) |
---|
286 | 368 | { |
---|
287 | 369 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
| 370 | + u64 count; |
---|
288 | 371 | |
---|
289 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 372 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
290 | 373 | return 0; |
---|
291 | 374 | |
---|
292 | | - return vblank->count; |
---|
| 375 | + count = atomic64_read(&vblank->count); |
---|
| 376 | + |
---|
| 377 | + /* |
---|
| 378 | + * This read barrier corresponds to the implicit write barrier of the |
---|
| 379 | + * write seqlock in store_vblank(). Note that this is the only place |
---|
| 380 | + * where we need an explicit barrier, since all other access goes |
---|
| 381 | + * through drm_vblank_count_and_time(), which already has the required |
---|
| 382 | + * read barrier curtesy of the read seqlock. |
---|
| 383 | + */ |
---|
| 384 | + smp_rmb(); |
---|
| 385 | + |
---|
| 386 | + return count; |
---|
293 | 387 | } |
---|
294 | 388 | |
---|
295 | 389 | /** |
---|
.. | .. |
---|
310 | 404 | u64 vblank; |
---|
311 | 405 | unsigned long flags; |
---|
312 | 406 | |
---|
313 | | - WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, |
---|
314 | | - "This function requires support for accurate vblank timestamps."); |
---|
| 407 | + drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) && |
---|
| 408 | + !crtc->funcs->get_vblank_timestamp, |
---|
| 409 | + "This function requires support for accurate vblank timestamps."); |
---|
315 | 410 | |
---|
316 | 411 | spin_lock_irqsave(&dev->vblank_time_lock, flags); |
---|
317 | 412 | |
---|
.. | .. |
---|
329 | 424 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
---|
330 | 425 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
331 | 426 | |
---|
332 | | - if (WARN_ON(!crtc)) |
---|
| 427 | + if (drm_WARN_ON(dev, !crtc)) |
---|
333 | 428 | return; |
---|
334 | 429 | |
---|
335 | | - if (crtc->funcs->disable_vblank) { |
---|
| 430 | + if (crtc->funcs->disable_vblank) |
---|
336 | 431 | crtc->funcs->disable_vblank(crtc); |
---|
337 | | - return; |
---|
338 | | - } |
---|
| 432 | + } else { |
---|
| 433 | + dev->driver->disable_vblank(dev, pipe); |
---|
339 | 434 | } |
---|
340 | | - |
---|
341 | | - dev->driver->disable_vblank(dev, pipe); |
---|
342 | 435 | } |
---|
343 | 436 | |
---|
344 | 437 | /* |
---|
.. | .. |
---|
392 | 485 | |
---|
393 | 486 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
---|
394 | 487 | if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) { |
---|
395 | | - DRM_DEBUG("disabling vblank on crtc %u\n", pipe); |
---|
| 488 | + drm_dbg_core(dev, "disabling vblank on crtc %u\n", pipe); |
---|
396 | 489 | drm_vblank_disable_and_save(dev, pipe); |
---|
397 | 490 | } |
---|
398 | 491 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
---|
399 | 492 | } |
---|
400 | 493 | |
---|
401 | | -void drm_vblank_cleanup(struct drm_device *dev) |
---|
| 494 | +static void drm_vblank_init_release(struct drm_device *dev, void *ptr) |
---|
402 | 495 | { |
---|
403 | | - unsigned int pipe; |
---|
| 496 | + struct drm_vblank_crtc *vblank = ptr; |
---|
404 | 497 | |
---|
405 | | - /* Bail if the driver didn't call drm_vblank_init() */ |
---|
406 | | - if (dev->num_crtcs == 0) |
---|
407 | | - return; |
---|
| 498 | + drm_WARN_ON(dev, READ_ONCE(vblank->enabled) && |
---|
| 499 | + drm_core_check_feature(dev, DRIVER_MODESET)); |
---|
408 | 500 | |
---|
409 | | - for (pipe = 0; pipe < dev->num_crtcs; pipe++) { |
---|
410 | | - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
411 | | - |
---|
412 | | - WARN_ON(READ_ONCE(vblank->enabled) && |
---|
413 | | - drm_core_check_feature(dev, DRIVER_MODESET)); |
---|
414 | | - |
---|
415 | | - del_timer_sync(&vblank->disable_timer); |
---|
416 | | - } |
---|
417 | | - |
---|
418 | | - kfree(dev->vblank); |
---|
419 | | - |
---|
420 | | - dev->num_crtcs = 0; |
---|
| 501 | + drm_vblank_destroy_worker(vblank); |
---|
| 502 | + del_timer_sync(&vblank->disable_timer); |
---|
421 | 503 | } |
---|
422 | 504 | |
---|
423 | 505 | /** |
---|
.. | .. |
---|
426 | 508 | * @num_crtcs: number of CRTCs supported by @dev |
---|
427 | 509 | * |
---|
428 | 510 | * This function initializes vblank support for @num_crtcs display pipelines. |
---|
429 | | - * Cleanup is handled by the DRM core, or through calling drm_dev_fini() for |
---|
430 | | - * drivers with a &drm_driver.release callback. |
---|
| 511 | + * Cleanup is handled automatically through a cleanup function added with |
---|
| 512 | + * drmm_add_action_or_reset(). |
---|
431 | 513 | * |
---|
432 | 514 | * Returns: |
---|
433 | 515 | * Zero on success or a negative error code on failure. |
---|
434 | 516 | */ |
---|
435 | 517 | int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) |
---|
436 | 518 | { |
---|
437 | | - int ret = -ENOMEM; |
---|
| 519 | + int ret; |
---|
438 | 520 | unsigned int i; |
---|
439 | 521 | |
---|
440 | 522 | spin_lock_init(&dev->vbl_lock); |
---|
441 | 523 | spin_lock_init(&dev->vblank_time_lock); |
---|
442 | 524 | |
---|
443 | | - dev->num_crtcs = num_crtcs; |
---|
444 | | - |
---|
445 | | - dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
---|
| 525 | + dev->vblank = drmm_kcalloc(dev, num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
---|
446 | 526 | if (!dev->vblank) |
---|
447 | | - goto err; |
---|
| 527 | + return -ENOMEM; |
---|
| 528 | + |
---|
| 529 | + dev->num_crtcs = num_crtcs; |
---|
448 | 530 | |
---|
449 | 531 | for (i = 0; i < num_crtcs; i++) { |
---|
450 | 532 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
---|
.. | .. |
---|
454 | 536 | init_waitqueue_head(&vblank->queue); |
---|
455 | 537 | timer_setup(&vblank->disable_timer, vblank_disable_fn, 0); |
---|
456 | 538 | seqlock_init(&vblank->seqlock); |
---|
457 | | - } |
---|
458 | 539 | |
---|
459 | | - DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
---|
| 540 | + ret = drmm_add_action_or_reset(dev, drm_vblank_init_release, |
---|
| 541 | + vblank); |
---|
| 542 | + if (ret) |
---|
| 543 | + return ret; |
---|
460 | 544 | |
---|
461 | | - /* Driver specific high-precision vblank timestamping supported? */ |
---|
462 | | - if (dev->driver->get_vblank_timestamp) |
---|
463 | | - DRM_INFO("Driver supports precise vblank timestamp query.\n"); |
---|
464 | | - else |
---|
465 | | - DRM_INFO("No driver support for vblank timestamp query.\n"); |
---|
466 | | - |
---|
467 | | - /* Must have precise timestamping for reliable vblank instant disable */ |
---|
468 | | - if (dev->vblank_disable_immediate && !dev->driver->get_vblank_timestamp) { |
---|
469 | | - dev->vblank_disable_immediate = false; |
---|
470 | | - DRM_INFO("Setting vblank_disable_immediate to false because " |
---|
471 | | - "get_vblank_timestamp == NULL\n"); |
---|
| 545 | + ret = drm_vblank_worker_init(vblank); |
---|
| 546 | + if (ret) |
---|
| 547 | + return ret; |
---|
472 | 548 | } |
---|
473 | 549 | |
---|
474 | 550 | return 0; |
---|
475 | | - |
---|
476 | | -err: |
---|
477 | | - dev->num_crtcs = 0; |
---|
478 | | - return ret; |
---|
479 | 551 | } |
---|
480 | 552 | EXPORT_SYMBOL(drm_vblank_init); |
---|
| 553 | + |
---|
| 554 | +/** |
---|
| 555 | + * drm_dev_has_vblank - test if vblanking has been initialized for |
---|
| 556 | + * a device |
---|
| 557 | + * @dev: the device |
---|
| 558 | + * |
---|
| 559 | + * Drivers may call this function to test if vblank support is |
---|
| 560 | + * initialized for a device. For most hardware this means that vblanking |
---|
| 561 | + * can also be enabled. |
---|
| 562 | + * |
---|
| 563 | + * Atomic helpers use this function to initialize |
---|
| 564 | + * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset(). |
---|
| 565 | + * |
---|
| 566 | + * Returns: |
---|
| 567 | + * True if vblanking has been initialized for the given device, false |
---|
| 568 | + * otherwise. |
---|
| 569 | + */ |
---|
| 570 | +bool drm_dev_has_vblank(const struct drm_device *dev) |
---|
| 571 | +{ |
---|
| 572 | + return dev->num_crtcs != 0; |
---|
| 573 | +} |
---|
| 574 | +EXPORT_SYMBOL(drm_dev_has_vblank); |
---|
481 | 575 | |
---|
482 | 576 | /** |
---|
483 | 577 | * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC |
---|
.. | .. |
---|
501 | 595 | * |
---|
502 | 596 | * Calculate and store various constants which are later needed by vblank and |
---|
503 | 597 | * swap-completion timestamping, e.g, by |
---|
504 | | - * drm_calc_vbltimestamp_from_scanoutpos(). They are derived from CRTC's true |
---|
505 | | - * scanout timing, so they take things like panel scaling or other adjustments |
---|
506 | | - * into account. |
---|
| 598 | + * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from |
---|
| 599 | + * CRTC's true scanout timing, so they take things like panel scaling or |
---|
| 600 | + * other adjustments into account. |
---|
507 | 601 | */ |
---|
508 | 602 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
---|
509 | 603 | const struct drm_display_mode *mode) |
---|
.. | .. |
---|
514 | 608 | int linedur_ns = 0, framedur_ns = 0; |
---|
515 | 609 | int dotclock = mode->crtc_clock; |
---|
516 | 610 | |
---|
517 | | - if (!dev->num_crtcs) |
---|
| 611 | + if (!drm_dev_has_vblank(dev)) |
---|
518 | 612 | return; |
---|
519 | 613 | |
---|
520 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 614 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
521 | 615 | return; |
---|
522 | 616 | |
---|
523 | 617 | /* Valid dotclock? */ |
---|
.. | .. |
---|
537 | 631 | */ |
---|
538 | 632 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
---|
539 | 633 | framedur_ns /= 2; |
---|
540 | | - } else |
---|
541 | | - DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", |
---|
542 | | - crtc->base.id); |
---|
| 634 | + } else { |
---|
| 635 | + drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n", |
---|
| 636 | + crtc->base.id); |
---|
| 637 | + } |
---|
543 | 638 | |
---|
544 | 639 | vblank->linedur_ns = linedur_ns; |
---|
545 | 640 | vblank->framedur_ns = framedur_ns; |
---|
546 | 641 | vblank->hwmode = *mode; |
---|
547 | 642 | |
---|
548 | | - DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
---|
549 | | - crtc->base.id, mode->crtc_htotal, |
---|
550 | | - mode->crtc_vtotal, mode->crtc_vdisplay); |
---|
551 | | - DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n", |
---|
552 | | - crtc->base.id, dotclock, framedur_ns, linedur_ns); |
---|
| 643 | + drm_dbg_core(dev, |
---|
| 644 | + "crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
---|
| 645 | + crtc->base.id, mode->crtc_htotal, |
---|
| 646 | + mode->crtc_vtotal, mode->crtc_vdisplay); |
---|
| 647 | + drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n", |
---|
| 648 | + crtc->base.id, dotclock, framedur_ns, linedur_ns); |
---|
553 | 649 | } |
---|
554 | 650 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
---|
555 | 651 | |
---|
556 | 652 | /** |
---|
557 | | - * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper |
---|
558 | | - * @dev: DRM device |
---|
559 | | - * @pipe: index of CRTC whose vblank timestamp to retrieve |
---|
| 653 | + * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank |
---|
| 654 | + * timestamp helper |
---|
| 655 | + * @crtc: CRTC whose vblank timestamp to retrieve |
---|
560 | 656 | * @max_error: Desired maximum allowable error in timestamps (nanosecs) |
---|
561 | 657 | * On return contains true maximum error of timestamp |
---|
562 | 658 | * @vblank_time: Pointer to time which should receive the timestamp |
---|
.. | .. |
---|
564 | 660 | * True when called from drm_crtc_handle_vblank(). Some drivers |
---|
565 | 661 | * need to apply some workarounds for gpu-specific vblank irq quirks |
---|
566 | 662 | * if flag is set. |
---|
| 663 | + * @get_scanout_position: |
---|
| 664 | + * Callback function to retrieve the scanout position. See |
---|
| 665 | + * @struct drm_crtc_helper_funcs.get_scanout_position. |
---|
567 | 666 | * |
---|
568 | 667 | * Implements calculation of exact vblank timestamps from given drm_display_mode |
---|
569 | | - * timings and current video scanout position of a CRTC. This can be directly |
---|
570 | | - * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver |
---|
571 | | - * if &drm_driver.get_scanout_position is implemented. |
---|
| 668 | + * timings and current video scanout position of a CRTC. |
---|
572 | 669 | * |
---|
573 | 670 | * The current implementation only handles standard video modes. For double scan |
---|
574 | 671 | * and interlaced modes the driver is supposed to adjust the hardware mode |
---|
.. | .. |
---|
577 | 674 | * |
---|
578 | 675 | * Note that atomic drivers must call drm_calc_timestamping_constants() before |
---|
579 | 676 | * enabling a CRTC. The atomic helpers already take care of that in |
---|
580 | | - * drm_atomic_helper_update_legacy_modeset_state(). |
---|
| 677 | + * drm_atomic_helper_calc_timestamping_constants(). |
---|
581 | 678 | * |
---|
582 | 679 | * Returns: |
---|
583 | 680 | * |
---|
584 | 681 | * Returns true on success, and false on failure, i.e. when no accurate |
---|
585 | 682 | * timestamp could be acquired. |
---|
586 | 683 | */ |
---|
587 | | -bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, |
---|
588 | | - unsigned int pipe, |
---|
589 | | - int *max_error, |
---|
590 | | - ktime_t *vblank_time, |
---|
591 | | - bool in_vblank_irq) |
---|
| 684 | +bool |
---|
| 685 | +drm_crtc_vblank_helper_get_vblank_timestamp_internal( |
---|
| 686 | + struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, |
---|
| 687 | + bool in_vblank_irq, |
---|
| 688 | + drm_vblank_get_scanout_position_func get_scanout_position) |
---|
592 | 689 | { |
---|
| 690 | + struct drm_device *dev = crtc->dev; |
---|
| 691 | + unsigned int pipe = crtc->index; |
---|
| 692 | + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
593 | 693 | struct timespec64 ts_etime, ts_vblank_time; |
---|
594 | 694 | ktime_t stime, etime; |
---|
595 | 695 | bool vbl_status; |
---|
596 | | - struct drm_crtc *crtc; |
---|
597 | 696 | const struct drm_display_mode *mode; |
---|
598 | | - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
599 | 697 | int vpos, hpos, i; |
---|
600 | 698 | int delta_ns, duration_ns; |
---|
601 | 699 | |
---|
602 | | - if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
---|
603 | | - return false; |
---|
604 | | - |
---|
605 | | - crtc = drm_crtc_from_index(dev, pipe); |
---|
606 | | - |
---|
607 | | - if (pipe >= dev->num_crtcs || !crtc) { |
---|
608 | | - DRM_ERROR("Invalid crtc %u\n", pipe); |
---|
| 700 | + if (pipe >= dev->num_crtcs) { |
---|
| 701 | + drm_err(dev, "Invalid crtc %u\n", pipe); |
---|
609 | 702 | return false; |
---|
610 | 703 | } |
---|
611 | 704 | |
---|
612 | 705 | /* Scanout position query not supported? Should not happen. */ |
---|
613 | | - if (!dev->driver->get_scanout_position) { |
---|
614 | | - DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
---|
| 706 | + if (!get_scanout_position) { |
---|
| 707 | + drm_err(dev, "Called from CRTC w/o get_scanout_position()!?\n"); |
---|
615 | 708 | return false; |
---|
616 | 709 | } |
---|
617 | 710 | |
---|
.. | .. |
---|
624 | 717 | * Happens during initial modesetting of a crtc. |
---|
625 | 718 | */ |
---|
626 | 719 | if (mode->crtc_clock == 0) { |
---|
627 | | - DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); |
---|
628 | | - WARN_ON_ONCE(drm_drv_uses_atomic_modeset(dev)); |
---|
629 | | - |
---|
| 720 | + drm_dbg_core(dev, "crtc %u: Noop due to uninitialized mode.\n", |
---|
| 721 | + pipe); |
---|
| 722 | + drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev)); |
---|
630 | 723 | return false; |
---|
631 | 724 | } |
---|
632 | 725 | |
---|
.. | .. |
---|
642 | 735 | * Get vertical and horizontal scanout position vpos, hpos, |
---|
643 | 736 | * and bounding timestamps stime, etime, pre/post query. |
---|
644 | 737 | */ |
---|
645 | | - vbl_status = dev->driver->get_scanout_position(dev, pipe, |
---|
646 | | - in_vblank_irq, |
---|
647 | | - &vpos, &hpos, |
---|
648 | | - &stime, &etime, |
---|
649 | | - mode); |
---|
| 738 | + vbl_status = get_scanout_position(crtc, in_vblank_irq, |
---|
| 739 | + &vpos, &hpos, |
---|
| 740 | + &stime, &etime, |
---|
| 741 | + mode); |
---|
650 | 742 | |
---|
651 | 743 | /* Return as no-op if scanout query unsupported or failed. */ |
---|
652 | 744 | if (!vbl_status) { |
---|
653 | | - DRM_DEBUG("crtc %u : scanoutpos query failed.\n", |
---|
654 | | - pipe); |
---|
| 745 | + drm_dbg_core(dev, |
---|
| 746 | + "crtc %u : scanoutpos query failed.\n", |
---|
| 747 | + pipe); |
---|
655 | 748 | return false; |
---|
656 | 749 | } |
---|
657 | 750 | |
---|
.. | .. |
---|
665 | 758 | |
---|
666 | 759 | /* Noisy system timing? */ |
---|
667 | 760 | if (i == DRM_TIMESTAMP_MAXRETRIES) { |
---|
668 | | - DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n", |
---|
669 | | - pipe, duration_ns/1000, *max_error/1000, i); |
---|
| 761 | + drm_dbg_core(dev, |
---|
| 762 | + "crtc %u: Noisy timestamp %d us > %d us [%d reps].\n", |
---|
| 763 | + pipe, duration_ns / 1000, *max_error / 1000, i); |
---|
670 | 764 | } |
---|
671 | 765 | |
---|
672 | 766 | /* Return upper bound of timestamp precision error. */ |
---|
.. | .. |
---|
684 | 778 | */ |
---|
685 | 779 | *vblank_time = ktime_sub_ns(etime, delta_ns); |
---|
686 | 780 | |
---|
687 | | - if ((drm_debug & DRM_UT_VBL) == 0) |
---|
| 781 | + if (!drm_debug_enabled(DRM_UT_VBL)) |
---|
688 | 782 | return true; |
---|
689 | 783 | |
---|
690 | 784 | ts_etime = ktime_to_timespec64(etime); |
---|
691 | 785 | ts_vblank_time = ktime_to_timespec64(*vblank_time); |
---|
692 | 786 | |
---|
693 | | - DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n", |
---|
694 | | - pipe, hpos, vpos, |
---|
695 | | - (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000, |
---|
696 | | - (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000, |
---|
697 | | - duration_ns / 1000, i); |
---|
| 787 | + drm_dbg_vbl(dev, |
---|
| 788 | + "crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n", |
---|
| 789 | + pipe, hpos, vpos, |
---|
| 790 | + (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000, |
---|
| 791 | + (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000, |
---|
| 792 | + duration_ns / 1000, i); |
---|
698 | 793 | |
---|
699 | 794 | return true; |
---|
700 | 795 | } |
---|
701 | | -EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
---|
| 796 | +EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal); |
---|
| 797 | + |
---|
| 798 | +/** |
---|
| 799 | + * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp |
---|
| 800 | + * helper |
---|
| 801 | + * @crtc: CRTC whose vblank timestamp to retrieve |
---|
| 802 | + * @max_error: Desired maximum allowable error in timestamps (nanosecs) |
---|
| 803 | + * On return contains true maximum error of timestamp |
---|
| 804 | + * @vblank_time: Pointer to time which should receive the timestamp |
---|
| 805 | + * @in_vblank_irq: |
---|
| 806 | + * True when called from drm_crtc_handle_vblank(). Some drivers |
---|
| 807 | + * need to apply some workarounds for gpu-specific vblank irq quirks |
---|
| 808 | + * if flag is set. |
---|
| 809 | + * |
---|
| 810 | + * Implements calculation of exact vblank timestamps from given drm_display_mode |
---|
| 811 | + * timings and current video scanout position of a CRTC. This can be directly |
---|
| 812 | + * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms |
---|
| 813 | + * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented. |
---|
| 814 | + * |
---|
| 815 | + * The current implementation only handles standard video modes. For double scan |
---|
| 816 | + * and interlaced modes the driver is supposed to adjust the hardware mode |
---|
| 817 | + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to |
---|
| 818 | + * match the scanout position reported. |
---|
| 819 | + * |
---|
| 820 | + * Note that atomic drivers must call drm_calc_timestamping_constants() before |
---|
| 821 | + * enabling a CRTC. The atomic helpers already take care of that in |
---|
| 822 | + * drm_atomic_helper_calc_timestamping_constants(). |
---|
| 823 | + * |
---|
| 824 | + * Returns: |
---|
| 825 | + * |
---|
| 826 | + * Returns true on success, and false on failure, i.e. when no accurate |
---|
| 827 | + * timestamp could be acquired. |
---|
| 828 | + */ |
---|
| 829 | +bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, |
---|
| 830 | + int *max_error, |
---|
| 831 | + ktime_t *vblank_time, |
---|
| 832 | + bool in_vblank_irq) |
---|
| 833 | +{ |
---|
| 834 | + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( |
---|
| 835 | + crtc, max_error, vblank_time, in_vblank_irq, |
---|
| 836 | + crtc->helper_private->get_scanout_position); |
---|
| 837 | +} |
---|
| 838 | +EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); |
---|
702 | 839 | |
---|
703 | 840 | /** |
---|
704 | 841 | * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent |
---|
.. | .. |
---|
725 | 862 | drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, |
---|
726 | 863 | ktime_t *tvblank, bool in_vblank_irq) |
---|
727 | 864 | { |
---|
| 865 | + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
728 | 866 | bool ret = false; |
---|
729 | 867 | |
---|
730 | 868 | /* Define requested maximum error on timestamps (nanoseconds). */ |
---|
731 | 869 | int max_error = (int) drm_timestamp_precision * 1000; |
---|
732 | 870 | |
---|
733 | 871 | /* Query driver if possible and precision timestamping enabled. */ |
---|
734 | | - if (dev->driver->get_vblank_timestamp && (max_error > 0)) |
---|
735 | | - ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, |
---|
| 872 | + if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) { |
---|
| 873 | + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
| 874 | + |
---|
| 875 | + ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, |
---|
736 | 876 | tvblank, in_vblank_irq); |
---|
| 877 | + } |
---|
737 | 878 | |
---|
738 | 879 | /* GPU high precision timestamp query unsupported or failed. |
---|
739 | 880 | * Return current monotonic/gettimeofday timestamp as best estimate. |
---|
.. | .. |
---|
753 | 894 | * modesetting activity. Note that this timer isn't correct against a racing |
---|
754 | 895 | * vblank interrupt (since it only reports the software vblank counter), see |
---|
755 | 896 | * drm_crtc_accurate_vblank_count() for such use-cases. |
---|
| 897 | + * |
---|
| 898 | + * Note that for a given vblank counter value drm_crtc_handle_vblank() |
---|
| 899 | + * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() |
---|
| 900 | + * provide a barrier: Any writes done before calling |
---|
| 901 | + * drm_crtc_handle_vblank() will be visible to callers of the later |
---|
| 902 | + * functions, iff the vblank count is the same or a later one. |
---|
| 903 | + * |
---|
| 904 | + * See also &drm_vblank_crtc.count. |
---|
756 | 905 | * |
---|
757 | 906 | * Returns: |
---|
758 | 907 | * The software vblank counter. |
---|
.. | .. |
---|
784 | 933 | u64 vblank_count; |
---|
785 | 934 | unsigned int seq; |
---|
786 | 935 | |
---|
787 | | - if (WARN_ON(pipe >= dev->num_crtcs)) { |
---|
| 936 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) { |
---|
788 | 937 | *vblanktime = 0; |
---|
789 | 938 | return 0; |
---|
790 | 939 | } |
---|
791 | 940 | |
---|
792 | 941 | do { |
---|
793 | 942 | seq = read_seqbegin(&vblank->seqlock); |
---|
794 | | - vblank_count = vblank->count; |
---|
| 943 | + vblank_count = atomic64_read(&vblank->count); |
---|
795 | 944 | *vblanktime = vblank->time; |
---|
796 | 945 | } while (read_seqretry(&vblank->seqlock, seq)); |
---|
797 | 946 | |
---|
.. | .. |
---|
808 | 957 | * vblank events since the system was booted, including lost events due to |
---|
809 | 958 | * modesetting activity. Returns corresponding system timestamp of the time |
---|
810 | 959 | * of the vblank interval that corresponds to the current vblank counter value. |
---|
| 960 | + * |
---|
| 961 | + * Note that for a given vblank counter value drm_crtc_handle_vblank() |
---|
| 962 | + * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() |
---|
| 963 | + * provide a barrier: Any writes done before calling |
---|
| 964 | + * drm_crtc_handle_vblank() will be visible to callers of the later |
---|
| 965 | + * functions, iff the vblank count is the same or a later one. |
---|
| 966 | + * |
---|
| 967 | + * See also &drm_vblank_crtc.count. |
---|
811 | 968 | */ |
---|
812 | 969 | u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, |
---|
813 | 970 | ktime_t *vblanktime) |
---|
.. | .. |
---|
843 | 1000 | break; |
---|
844 | 1001 | } |
---|
845 | 1002 | trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq); |
---|
846 | | - drm_send_event_locked(dev, &e->base); |
---|
| 1003 | + /* |
---|
| 1004 | + * Use the same timestamp for any associated fence signal to avoid |
---|
| 1005 | + * mismatch in timestamps for vsync & fence events triggered by the |
---|
| 1006 | + * same HW event. Frameworks like SurfaceFlinger in Android expects the |
---|
| 1007 | + * retire-fence timestamp to match exactly with HW vsync as it uses it |
---|
| 1008 | + * for its software vsync modeling. |
---|
| 1009 | + */ |
---|
| 1010 | + drm_send_event_timestamp_locked(dev, &e->base, now); |
---|
847 | 1011 | } |
---|
848 | 1012 | |
---|
849 | 1013 | /** |
---|
.. | .. |
---|
881 | 1045 | * handler by calling drm_crtc_send_vblank_event() and make sure that there's no |
---|
882 | 1046 | * possible race with the hardware committing the atomic update. |
---|
883 | 1047 | * |
---|
884 | | - * Caller must hold a vblank reference for the event @e, which will be dropped |
---|
885 | | - * when the next vblank arrives. |
---|
| 1048 | + * Caller must hold a vblank reference for the event @e acquired by a |
---|
| 1049 | + * drm_crtc_vblank_get(), which will be dropped when the next vblank arrives. |
---|
886 | 1050 | */ |
---|
887 | 1051 | void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, |
---|
888 | 1052 | struct drm_pending_vblank_event *e) |
---|
.. | .. |
---|
917 | 1081 | unsigned int pipe = drm_crtc_index(crtc); |
---|
918 | 1082 | ktime_t now; |
---|
919 | 1083 | |
---|
920 | | - if (dev->num_crtcs > 0) { |
---|
| 1084 | + if (drm_dev_has_vblank(dev)) { |
---|
921 | 1085 | seq = drm_vblank_count_and_time(dev, pipe, &now); |
---|
922 | 1086 | } else { |
---|
923 | 1087 | seq = 0; |
---|
.. | .. |
---|
934 | 1098 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
---|
935 | 1099 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
936 | 1100 | |
---|
937 | | - if (WARN_ON(!crtc)) |
---|
| 1101 | + if (drm_WARN_ON(dev, !crtc)) |
---|
938 | 1102 | return 0; |
---|
939 | 1103 | |
---|
940 | 1104 | if (crtc->funcs->enable_vblank) |
---|
941 | 1105 | return crtc->funcs->enable_vblank(crtc); |
---|
| 1106 | + } else if (dev->driver->enable_vblank) { |
---|
| 1107 | + return dev->driver->enable_vblank(dev, pipe); |
---|
942 | 1108 | } |
---|
943 | 1109 | |
---|
944 | | - return dev->driver->enable_vblank(dev, pipe); |
---|
| 1110 | + return -EINVAL; |
---|
945 | 1111 | } |
---|
946 | 1112 | |
---|
947 | 1113 | static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) |
---|
.. | .. |
---|
962 | 1128 | * prevent double-accounting of same vblank interval. |
---|
963 | 1129 | */ |
---|
964 | 1130 | ret = __enable_vblank(dev, pipe); |
---|
965 | | - DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); |
---|
| 1131 | + drm_dbg_core(dev, "enabling vblank on crtc %u, ret: %d\n", |
---|
| 1132 | + pipe, ret); |
---|
966 | 1133 | if (ret) { |
---|
967 | 1134 | atomic_dec(&vblank->refcount); |
---|
968 | 1135 | } else { |
---|
.. | .. |
---|
981 | 1148 | return ret; |
---|
982 | 1149 | } |
---|
983 | 1150 | |
---|
984 | | -static int drm_vblank_get(struct drm_device *dev, unsigned int pipe) |
---|
| 1151 | +int drm_vblank_get(struct drm_device *dev, unsigned int pipe) |
---|
985 | 1152 | { |
---|
986 | 1153 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
987 | 1154 | unsigned long irqflags; |
---|
988 | 1155 | int ret = 0; |
---|
989 | 1156 | |
---|
990 | | - if (!dev->num_crtcs) |
---|
| 1157 | + if (!drm_dev_has_vblank(dev)) |
---|
991 | 1158 | return -EINVAL; |
---|
992 | 1159 | |
---|
993 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1160 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
994 | 1161 | return -EINVAL; |
---|
995 | 1162 | |
---|
996 | 1163 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
---|
.. | .. |
---|
1024 | 1191 | } |
---|
1025 | 1192 | EXPORT_SYMBOL(drm_crtc_vblank_get); |
---|
1026 | 1193 | |
---|
1027 | | -static void drm_vblank_put(struct drm_device *dev, unsigned int pipe) |
---|
| 1194 | +void drm_vblank_put(struct drm_device *dev, unsigned int pipe) |
---|
1028 | 1195 | { |
---|
1029 | 1196 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1030 | 1197 | |
---|
1031 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1198 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1032 | 1199 | return; |
---|
1033 | 1200 | |
---|
1034 | | - if (WARN_ON(atomic_read(&vblank->refcount) == 0)) |
---|
| 1201 | + if (drm_WARN_ON(dev, atomic_read(&vblank->refcount) == 0)) |
---|
1035 | 1202 | return; |
---|
1036 | 1203 | |
---|
1037 | 1204 | /* Last user schedules interrupt disable */ |
---|
.. | .. |
---|
1076 | 1243 | int ret; |
---|
1077 | 1244 | u64 last; |
---|
1078 | 1245 | |
---|
1079 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1246 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1080 | 1247 | return; |
---|
1081 | 1248 | |
---|
1082 | 1249 | ret = drm_vblank_get(dev, pipe); |
---|
1083 | | - if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret)) |
---|
| 1250 | + if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n", |
---|
| 1251 | + pipe, ret)) |
---|
1084 | 1252 | return; |
---|
1085 | 1253 | |
---|
1086 | 1254 | last = drm_vblank_count(dev, pipe); |
---|
.. | .. |
---|
1089 | 1257 | last != drm_vblank_count(dev, pipe), |
---|
1090 | 1258 | msecs_to_jiffies(100)); |
---|
1091 | 1259 | |
---|
1092 | | - WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe); |
---|
| 1260 | + drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe); |
---|
1093 | 1261 | |
---|
1094 | 1262 | drm_vblank_put(dev, pipe); |
---|
1095 | 1263 | } |
---|
.. | .. |
---|
1126 | 1294 | unsigned int pipe = drm_crtc_index(crtc); |
---|
1127 | 1295 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1128 | 1296 | struct drm_pending_vblank_event *e, *t; |
---|
1129 | | - |
---|
1130 | 1297 | ktime_t now; |
---|
1131 | | - unsigned long irqflags; |
---|
1132 | 1298 | u64 seq; |
---|
1133 | 1299 | |
---|
1134 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1300 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1135 | 1301 | return; |
---|
1136 | 1302 | |
---|
1137 | | - spin_lock_irqsave(&dev->event_lock, irqflags); |
---|
| 1303 | + /* |
---|
| 1304 | + * Grab event_lock early to prevent vblank work from being scheduled |
---|
| 1305 | + * while we're in the middle of shutting down vblank interrupts |
---|
| 1306 | + */ |
---|
| 1307 | + spin_lock_irq(&dev->event_lock); |
---|
1138 | 1308 | |
---|
1139 | 1309 | spin_lock(&dev->vbl_lock); |
---|
1140 | | - DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n", |
---|
1141 | | - pipe, vblank->enabled, vblank->inmodeset); |
---|
| 1310 | + drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n", |
---|
| 1311 | + pipe, vblank->enabled, vblank->inmodeset); |
---|
1142 | 1312 | |
---|
1143 | 1313 | /* Avoid redundant vblank disables without previous |
---|
1144 | 1314 | * drm_crtc_vblank_on(). */ |
---|
.. | .. |
---|
1163 | 1333 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { |
---|
1164 | 1334 | if (e->pipe != pipe) |
---|
1165 | 1335 | continue; |
---|
1166 | | - DRM_DEBUG("Sending premature vblank event on disable: " |
---|
1167 | | - "wanted %llu, current %llu\n", |
---|
1168 | | - e->sequence, seq); |
---|
| 1336 | + drm_dbg_core(dev, "Sending premature vblank event on disable: " |
---|
| 1337 | + "wanted %llu, current %llu\n", |
---|
| 1338 | + e->sequence, seq); |
---|
1169 | 1339 | list_del(&e->base.link); |
---|
1170 | 1340 | drm_vblank_put(dev, pipe); |
---|
1171 | 1341 | send_vblank_event(dev, e, seq, now); |
---|
1172 | 1342 | } |
---|
1173 | | - spin_unlock_irqrestore(&dev->event_lock, irqflags); |
---|
| 1343 | + |
---|
| 1344 | + /* Cancel any leftover pending vblank work */ |
---|
| 1345 | + drm_vblank_cancel_pending_works(vblank); |
---|
| 1346 | + |
---|
| 1347 | + spin_unlock_irq(&dev->event_lock); |
---|
1174 | 1348 | |
---|
1175 | 1349 | /* Will be reset by the modeset helpers when re-enabling the crtc by |
---|
1176 | 1350 | * calling drm_calc_timestamping_constants(). */ |
---|
1177 | 1351 | vblank->hwmode.crtc_clock = 0; |
---|
| 1352 | + |
---|
| 1353 | + /* Wait for any vblank work that's still executing to finish */ |
---|
| 1354 | + drm_vblank_flush_worker(vblank); |
---|
1178 | 1355 | } |
---|
1179 | 1356 | EXPORT_SYMBOL(drm_crtc_vblank_off); |
---|
1180 | 1357 | |
---|
.. | .. |
---|
1193 | 1370 | void drm_crtc_vblank_reset(struct drm_crtc *crtc) |
---|
1194 | 1371 | { |
---|
1195 | 1372 | struct drm_device *dev = crtc->dev; |
---|
1196 | | - unsigned long irqflags; |
---|
1197 | 1373 | unsigned int pipe = drm_crtc_index(crtc); |
---|
1198 | 1374 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1199 | 1375 | |
---|
1200 | | - spin_lock_irqsave(&dev->vbl_lock, irqflags); |
---|
| 1376 | + spin_lock_irq(&dev->vbl_lock); |
---|
1201 | 1377 | /* |
---|
1202 | 1378 | * Prevent subsequent drm_vblank_get() from enabling the vblank |
---|
1203 | 1379 | * interrupt by bumping the refcount. |
---|
.. | .. |
---|
1206 | 1382 | atomic_inc(&vblank->refcount); |
---|
1207 | 1383 | vblank->inmodeset = 1; |
---|
1208 | 1384 | } |
---|
1209 | | - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
---|
| 1385 | + spin_unlock_irq(&dev->vbl_lock); |
---|
1210 | 1386 | |
---|
1211 | | - WARN_ON(!list_empty(&dev->vblank_event_list)); |
---|
| 1387 | + drm_WARN_ON(dev, !list_empty(&dev->vblank_event_list)); |
---|
| 1388 | + drm_WARN_ON(dev, !list_empty(&vblank->pending_work)); |
---|
1212 | 1389 | } |
---|
1213 | 1390 | EXPORT_SYMBOL(drm_crtc_vblank_reset); |
---|
1214 | 1391 | |
---|
.. | .. |
---|
1236 | 1413 | unsigned int pipe = drm_crtc_index(crtc); |
---|
1237 | 1414 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1238 | 1415 | |
---|
1239 | | - WARN_ON(dev->max_vblank_count); |
---|
1240 | | - WARN_ON(!READ_ONCE(vblank->inmodeset)); |
---|
| 1416 | + drm_WARN_ON(dev, dev->max_vblank_count); |
---|
| 1417 | + drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset)); |
---|
1241 | 1418 | |
---|
1242 | 1419 | vblank->max_vblank_count = max_vblank_count; |
---|
1243 | 1420 | } |
---|
.. | .. |
---|
1258 | 1435 | struct drm_device *dev = crtc->dev; |
---|
1259 | 1436 | unsigned int pipe = drm_crtc_index(crtc); |
---|
1260 | 1437 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1261 | | - unsigned long irqflags; |
---|
1262 | 1438 | |
---|
1263 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1439 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1264 | 1440 | return; |
---|
1265 | 1441 | |
---|
1266 | | - spin_lock_irqsave(&dev->vbl_lock, irqflags); |
---|
1267 | | - DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n", |
---|
1268 | | - pipe, vblank->enabled, vblank->inmodeset); |
---|
| 1442 | + spin_lock_irq(&dev->vbl_lock); |
---|
| 1443 | + drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n", |
---|
| 1444 | + pipe, vblank->enabled, vblank->inmodeset); |
---|
1269 | 1445 | |
---|
1270 | 1446 | /* Drop our private "prevent drm_vblank_get" refcount */ |
---|
1271 | 1447 | if (vblank->inmodeset) { |
---|
.. | .. |
---|
1280 | 1456 | * user wishes vblank interrupts to be enabled all the time. |
---|
1281 | 1457 | */ |
---|
1282 | 1458 | if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0) |
---|
1283 | | - WARN_ON(drm_vblank_enable(dev, pipe)); |
---|
1284 | | - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
---|
| 1459 | + drm_WARN_ON(dev, drm_vblank_enable(dev, pipe)); |
---|
| 1460 | + spin_unlock_irq(&dev->vbl_lock); |
---|
1285 | 1461 | } |
---|
1286 | 1462 | EXPORT_SYMBOL(drm_crtc_vblank_on); |
---|
1287 | 1463 | |
---|
.. | .. |
---|
1307 | 1483 | u32 cur_vblank, diff = 1; |
---|
1308 | 1484 | int count = DRM_TIMESTAMP_MAXRETRIES; |
---|
1309 | 1485 | |
---|
1310 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1486 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1311 | 1487 | return; |
---|
1312 | 1488 | |
---|
1313 | 1489 | assert_spin_locked(&dev->vbl_lock); |
---|
1314 | 1490 | assert_spin_locked(&dev->vblank_time_lock); |
---|
1315 | 1491 | |
---|
1316 | 1492 | vblank = &dev->vblank[pipe]; |
---|
1317 | | - WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, |
---|
1318 | | - "Cannot compute missed vblanks without frame duration\n"); |
---|
| 1493 | + drm_WARN_ONCE(dev, |
---|
| 1494 | + drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns, |
---|
| 1495 | + "Cannot compute missed vblanks without frame duration\n"); |
---|
1319 | 1496 | framedur_ns = vblank->framedur_ns; |
---|
1320 | 1497 | |
---|
1321 | 1498 | do { |
---|
.. | .. |
---|
1328 | 1505 | diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); |
---|
1329 | 1506 | |
---|
1330 | 1507 | |
---|
1331 | | - DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", |
---|
1332 | | - diff, diff_ns, framedur_ns, cur_vblank - vblank->last); |
---|
| 1508 | + drm_dbg_vbl(dev, |
---|
| 1509 | + "missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", |
---|
| 1510 | + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); |
---|
1333 | 1511 | store_vblank(dev, pipe, diff, t_vblank, cur_vblank); |
---|
1334 | 1512 | } |
---|
1335 | 1513 | EXPORT_SYMBOL(drm_vblank_restore); |
---|
.. | .. |
---|
1356 | 1534 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1357 | 1535 | |
---|
1358 | 1536 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
---|
1359 | | - if (!dev->num_crtcs) |
---|
| 1537 | + if (!drm_dev_has_vblank(dev)) |
---|
1360 | 1538 | return; |
---|
1361 | 1539 | |
---|
1362 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1540 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1363 | 1541 | return; |
---|
1364 | 1542 | |
---|
1365 | 1543 | /* |
---|
.. | .. |
---|
1380 | 1558 | unsigned int pipe) |
---|
1381 | 1559 | { |
---|
1382 | 1560 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1383 | | - unsigned long irqflags; |
---|
1384 | 1561 | |
---|
1385 | 1562 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
---|
1386 | | - if (!dev->num_crtcs) |
---|
| 1563 | + if (!drm_dev_has_vblank(dev)) |
---|
1387 | 1564 | return; |
---|
1388 | 1565 | |
---|
1389 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1566 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1390 | 1567 | return; |
---|
1391 | 1568 | |
---|
1392 | 1569 | if (vblank->inmodeset) { |
---|
1393 | | - spin_lock_irqsave(&dev->vbl_lock, irqflags); |
---|
| 1570 | + spin_lock_irq(&dev->vbl_lock); |
---|
1394 | 1571 | drm_reset_vblank_timestamp(dev, pipe); |
---|
1395 | | - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
---|
| 1572 | + spin_unlock_irq(&dev->vbl_lock); |
---|
1396 | 1573 | |
---|
1397 | 1574 | if (vblank->inmodeset & 0x2) |
---|
1398 | 1575 | drm_vblank_put(dev, pipe); |
---|
.. | .. |
---|
1408 | 1585 | unsigned int pipe; |
---|
1409 | 1586 | |
---|
1410 | 1587 | /* If drm_vblank_init() hasn't been called yet, just no-op */ |
---|
1411 | | - if (!dev->num_crtcs) |
---|
| 1588 | + if (!drm_dev_has_vblank(dev)) |
---|
1412 | 1589 | return 0; |
---|
1413 | 1590 | |
---|
1414 | 1591 | /* KMS drivers handle this internally */ |
---|
.. | .. |
---|
1433 | 1610 | return 0; |
---|
1434 | 1611 | } |
---|
1435 | 1612 | |
---|
1436 | | -static inline bool vblank_passed(u64 seq, u64 ref) |
---|
1437 | | -{ |
---|
1438 | | - return (seq - ref) <= (1 << 23); |
---|
1439 | | -} |
---|
1440 | | - |
---|
1441 | 1613 | static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, |
---|
1442 | 1614 | u64 req_seq, |
---|
1443 | 1615 | union drm_wait_vblank *vblwait, |
---|
.. | .. |
---|
1446 | 1618 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
---|
1447 | 1619 | struct drm_pending_vblank_event *e; |
---|
1448 | 1620 | ktime_t now; |
---|
1449 | | - unsigned long flags; |
---|
1450 | 1621 | u64 seq; |
---|
1451 | 1622 | int ret; |
---|
1452 | 1623 | |
---|
.. | .. |
---|
1463 | 1634 | e->event.vbl.crtc_id = 0; |
---|
1464 | 1635 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
---|
1465 | 1636 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
| 1637 | + |
---|
1466 | 1638 | if (crtc) |
---|
1467 | 1639 | e->event.vbl.crtc_id = crtc->base.id; |
---|
1468 | 1640 | } |
---|
1469 | 1641 | |
---|
1470 | | - spin_lock_irqsave(&dev->event_lock, flags); |
---|
| 1642 | + spin_lock_irq(&dev->event_lock); |
---|
1471 | 1643 | |
---|
1472 | 1644 | /* |
---|
1473 | 1645 | * drm_crtc_vblank_off() might have been called after we called |
---|
.. | .. |
---|
1488 | 1660 | |
---|
1489 | 1661 | seq = drm_vblank_count_and_time(dev, pipe, &now); |
---|
1490 | 1662 | |
---|
1491 | | - DRM_DEBUG("event on vblank count %llu, current %llu, crtc %u\n", |
---|
1492 | | - req_seq, seq, pipe); |
---|
| 1663 | + drm_dbg_core(dev, "event on vblank count %llu, current %llu, crtc %u\n", |
---|
| 1664 | + req_seq, seq, pipe); |
---|
1493 | 1665 | |
---|
1494 | 1666 | trace_drm_vblank_event_queued(file_priv, pipe, req_seq); |
---|
1495 | 1667 | |
---|
1496 | 1668 | e->sequence = req_seq; |
---|
1497 | | - if (vblank_passed(seq, req_seq)) { |
---|
| 1669 | + if (drm_vblank_passed(seq, req_seq)) { |
---|
1498 | 1670 | drm_vblank_put(dev, pipe); |
---|
1499 | 1671 | send_vblank_event(dev, e, seq, now); |
---|
1500 | 1672 | vblwait->reply.sequence = seq; |
---|
.. | .. |
---|
1504 | 1676 | vblwait->reply.sequence = req_seq; |
---|
1505 | 1677 | } |
---|
1506 | 1678 | |
---|
1507 | | - spin_unlock_irqrestore(&dev->event_lock, flags); |
---|
| 1679 | + spin_unlock_irq(&dev->event_lock); |
---|
1508 | 1680 | |
---|
1509 | 1681 | return 0; |
---|
1510 | 1682 | |
---|
1511 | 1683 | err_unlock: |
---|
1512 | | - spin_unlock_irqrestore(&dev->event_lock, flags); |
---|
| 1684 | + spin_unlock_irq(&dev->event_lock); |
---|
1513 | 1685 | kfree(e); |
---|
1514 | 1686 | err_put: |
---|
1515 | 1687 | drm_vblank_put(dev, pipe); |
---|
.. | .. |
---|
1580 | 1752 | if (vblwait->request.type & |
---|
1581 | 1753 | ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | |
---|
1582 | 1754 | _DRM_VBLANK_HIGH_CRTC_MASK)) { |
---|
1583 | | - DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", |
---|
1584 | | - vblwait->request.type, |
---|
1585 | | - (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | |
---|
1586 | | - _DRM_VBLANK_HIGH_CRTC_MASK)); |
---|
| 1755 | + drm_dbg_core(dev, |
---|
| 1756 | + "Unsupported type value 0x%x, supported mask 0x%x\n", |
---|
| 1757 | + vblwait->request.type, |
---|
| 1758 | + (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | |
---|
| 1759 | + _DRM_VBLANK_HIGH_CRTC_MASK)); |
---|
1587 | 1760 | return -EINVAL; |
---|
1588 | 1761 | } |
---|
1589 | 1762 | |
---|
.. | .. |
---|
1626 | 1799 | |
---|
1627 | 1800 | ret = drm_vblank_get(dev, pipe); |
---|
1628 | 1801 | if (ret) { |
---|
1629 | | - DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); |
---|
| 1802 | + drm_dbg_core(dev, |
---|
| 1803 | + "crtc %d failed to acquire vblank counter, %d\n", |
---|
| 1804 | + pipe, ret); |
---|
1630 | 1805 | return ret; |
---|
1631 | 1806 | } |
---|
1632 | 1807 | seq = drm_vblank_count(dev, pipe); |
---|
.. | .. |
---|
1646 | 1821 | } |
---|
1647 | 1822 | |
---|
1648 | 1823 | if ((flags & _DRM_VBLANK_NEXTONMISS) && |
---|
1649 | | - vblank_passed(seq, req_seq)) { |
---|
| 1824 | + drm_vblank_passed(seq, req_seq)) { |
---|
1650 | 1825 | req_seq = seq + 1; |
---|
1651 | 1826 | vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS; |
---|
1652 | 1827 | vblwait->request.sequence = req_seq; |
---|
.. | .. |
---|
1660 | 1835 | } |
---|
1661 | 1836 | |
---|
1662 | 1837 | if (req_seq != seq) { |
---|
1663 | | - DRM_DEBUG("waiting on vblank count %llu, crtc %u\n", |
---|
1664 | | - req_seq, pipe); |
---|
1665 | | - DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, |
---|
1666 | | - vblank_passed(drm_vblank_count(dev, pipe), |
---|
1667 | | - req_seq) || |
---|
1668 | | - !READ_ONCE(vblank->enabled)); |
---|
| 1838 | + int wait; |
---|
| 1839 | + |
---|
| 1840 | + drm_dbg_core(dev, "waiting on vblank count %llu, crtc %u\n", |
---|
| 1841 | + req_seq, pipe); |
---|
| 1842 | + wait = wait_event_interruptible_timeout(vblank->queue, |
---|
| 1843 | + drm_vblank_passed(drm_vblank_count(dev, pipe), req_seq) || |
---|
| 1844 | + !READ_ONCE(vblank->enabled), |
---|
| 1845 | + msecs_to_jiffies(3000)); |
---|
| 1846 | + |
---|
| 1847 | + switch (wait) { |
---|
| 1848 | + case 0: |
---|
| 1849 | + /* timeout */ |
---|
| 1850 | + ret = -EBUSY; |
---|
| 1851 | + break; |
---|
| 1852 | + case -ERESTARTSYS: |
---|
| 1853 | + /* interrupted by signal */ |
---|
| 1854 | + ret = -EINTR; |
---|
| 1855 | + break; |
---|
| 1856 | + default: |
---|
| 1857 | + ret = 0; |
---|
| 1858 | + break; |
---|
| 1859 | + } |
---|
1669 | 1860 | } |
---|
1670 | 1861 | |
---|
1671 | 1862 | if (ret != -EINTR) { |
---|
1672 | 1863 | drm_wait_vblank_reply(dev, pipe, &vblwait->reply); |
---|
1673 | 1864 | |
---|
1674 | | - DRM_DEBUG("crtc %d returning %u to client\n", |
---|
1675 | | - pipe, vblwait->reply.sequence); |
---|
| 1865 | + drm_dbg_core(dev, "crtc %d returning %u to client\n", |
---|
| 1866 | + pipe, vblwait->reply.sequence); |
---|
1676 | 1867 | } else { |
---|
1677 | | - DRM_DEBUG("crtc %d vblank wait interrupted by signal\n", pipe); |
---|
| 1868 | + drm_dbg_core(dev, "crtc %d vblank wait interrupted by signal\n", |
---|
| 1869 | + pipe); |
---|
1678 | 1870 | } |
---|
1679 | 1871 | |
---|
1680 | 1872 | done: |
---|
.. | .. |
---|
1684 | 1876 | |
---|
1685 | 1877 | static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) |
---|
1686 | 1878 | { |
---|
| 1879 | + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
---|
| 1880 | + bool high_prec = false; |
---|
1687 | 1881 | struct drm_pending_vblank_event *e, *t; |
---|
1688 | 1882 | ktime_t now; |
---|
1689 | 1883 | u64 seq; |
---|
.. | .. |
---|
1695 | 1889 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { |
---|
1696 | 1890 | if (e->pipe != pipe) |
---|
1697 | 1891 | continue; |
---|
1698 | | - if (!vblank_passed(seq, e->sequence)) |
---|
| 1892 | + if (!drm_vblank_passed(seq, e->sequence)) |
---|
1699 | 1893 | continue; |
---|
1700 | 1894 | |
---|
1701 | | - DRM_DEBUG("vblank event on %llu, current %llu\n", |
---|
1702 | | - e->sequence, seq); |
---|
| 1895 | + drm_dbg_core(dev, "vblank event on %llu, current %llu\n", |
---|
| 1896 | + e->sequence, seq); |
---|
1703 | 1897 | |
---|
1704 | 1898 | list_del(&e->base.link); |
---|
1705 | 1899 | drm_vblank_put(dev, pipe); |
---|
1706 | 1900 | send_vblank_event(dev, e, seq, now); |
---|
1707 | 1901 | } |
---|
1708 | 1902 | |
---|
1709 | | - trace_drm_vblank_event(pipe, seq); |
---|
| 1903 | + if (crtc && crtc->funcs->get_vblank_timestamp) |
---|
| 1904 | + high_prec = true; |
---|
| 1905 | + |
---|
| 1906 | + trace_drm_vblank_event(pipe, seq, now, high_prec); |
---|
1710 | 1907 | } |
---|
1711 | 1908 | |
---|
1712 | 1909 | /** |
---|
.. | .. |
---|
1725 | 1922 | unsigned long irqflags; |
---|
1726 | 1923 | bool disable_irq; |
---|
1727 | 1924 | |
---|
1728 | | - if (WARN_ON_ONCE(!dev->num_crtcs)) |
---|
| 1925 | + if (drm_WARN_ON_ONCE(dev, !drm_dev_has_vblank(dev))) |
---|
1729 | 1926 | return false; |
---|
1730 | 1927 | |
---|
1731 | | - if (WARN_ON(pipe >= dev->num_crtcs)) |
---|
| 1928 | + if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) |
---|
1732 | 1929 | return false; |
---|
1733 | 1930 | |
---|
1734 | 1931 | spin_lock_irqsave(&dev->event_lock, irqflags); |
---|
.. | .. |
---|
1762 | 1959 | !atomic_read(&vblank->refcount)); |
---|
1763 | 1960 | |
---|
1764 | 1961 | drm_handle_vblank_events(dev, pipe); |
---|
| 1962 | + drm_handle_vblank_works(vblank); |
---|
1765 | 1963 | |
---|
1766 | 1964 | spin_unlock_irqrestore(&dev->event_lock, irqflags); |
---|
1767 | 1965 | |
---|
.. | .. |
---|
1780 | 1978 | * update the vblank counter and send any signals that may be pending. |
---|
1781 | 1979 | * |
---|
1782 | 1980 | * This is the native KMS version of drm_handle_vblank(). |
---|
| 1981 | + * |
---|
| 1982 | + * Note that for a given vblank counter value drm_crtc_handle_vblank() |
---|
| 1983 | + * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() |
---|
| 1984 | + * provide a barrier: Any writes done before calling |
---|
| 1985 | + * drm_crtc_handle_vblank() will be visible to callers of the later |
---|
| 1986 | + * functions, iff the vblank count is the same or a later one. |
---|
| 1987 | + * |
---|
| 1988 | + * See also &drm_vblank_crtc.count. |
---|
1783 | 1989 | * |
---|
1784 | 1990 | * Returns: |
---|
1785 | 1991 | * True if the event was successfully handled, false on failure. |
---|
.. | .. |
---|
1810 | 2016 | int ret; |
---|
1811 | 2017 | |
---|
1812 | 2018 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
---|
1813 | | - return -EINVAL; |
---|
| 2019 | + return -EOPNOTSUPP; |
---|
1814 | 2020 | |
---|
1815 | 2021 | if (!dev->irq_enabled) |
---|
1816 | 2022 | return -EOPNOTSUPP; |
---|
.. | .. |
---|
1827 | 2033 | if (!vblank_enabled) { |
---|
1828 | 2034 | ret = drm_crtc_vblank_get(crtc); |
---|
1829 | 2035 | if (ret) { |
---|
1830 | | - DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); |
---|
| 2036 | + drm_dbg_core(dev, |
---|
| 2037 | + "crtc %d failed to acquire vblank counter, %d\n", |
---|
| 2038 | + pipe, ret); |
---|
1831 | 2039 | return ret; |
---|
1832 | 2040 | } |
---|
1833 | 2041 | } |
---|
.. | .. |
---|
1865 | 2073 | u64 seq; |
---|
1866 | 2074 | u64 req_seq; |
---|
1867 | 2075 | int ret; |
---|
1868 | | - unsigned long spin_flags; |
---|
1869 | 2076 | |
---|
1870 | 2077 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
---|
1871 | | - return -EINVAL; |
---|
| 2078 | + return -EOPNOTSUPP; |
---|
1872 | 2079 | |
---|
1873 | 2080 | if (!dev->irq_enabled) |
---|
1874 | 2081 | return -EOPNOTSUPP; |
---|
.. | .. |
---|
1893 | 2100 | |
---|
1894 | 2101 | ret = drm_crtc_vblank_get(crtc); |
---|
1895 | 2102 | if (ret) { |
---|
1896 | | - DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); |
---|
| 2103 | + drm_dbg_core(dev, |
---|
| 2104 | + "crtc %d failed to acquire vblank counter, %d\n", |
---|
| 2105 | + pipe, ret); |
---|
1897 | 2106 | goto err_free; |
---|
1898 | 2107 | } |
---|
1899 | 2108 | |
---|
.. | .. |
---|
1903 | 2112 | if (flags & DRM_CRTC_SEQUENCE_RELATIVE) |
---|
1904 | 2113 | req_seq += seq; |
---|
1905 | 2114 | |
---|
1906 | | - if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && vblank_passed(seq, req_seq)) |
---|
| 2115 | + if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && drm_vblank_passed(seq, req_seq)) |
---|
1907 | 2116 | req_seq = seq + 1; |
---|
1908 | 2117 | |
---|
1909 | 2118 | e->pipe = pipe; |
---|
.. | .. |
---|
1911 | 2120 | e->event.base.length = sizeof(e->event.seq); |
---|
1912 | 2121 | e->event.seq.user_data = queue_seq->user_data; |
---|
1913 | 2122 | |
---|
1914 | | - spin_lock_irqsave(&dev->event_lock, spin_flags); |
---|
| 2123 | + spin_lock_irq(&dev->event_lock); |
---|
1915 | 2124 | |
---|
1916 | 2125 | /* |
---|
1917 | 2126 | * drm_crtc_vblank_off() might have been called after we called |
---|
.. | .. |
---|
1932 | 2141 | |
---|
1933 | 2142 | e->sequence = req_seq; |
---|
1934 | 2143 | |
---|
1935 | | - if (vblank_passed(seq, req_seq)) { |
---|
| 2144 | + if (drm_vblank_passed(seq, req_seq)) { |
---|
1936 | 2145 | drm_crtc_vblank_put(crtc); |
---|
1937 | 2146 | send_vblank_event(dev, e, seq, now); |
---|
1938 | 2147 | queue_seq->sequence = seq; |
---|
.. | .. |
---|
1942 | 2151 | queue_seq->sequence = req_seq; |
---|
1943 | 2152 | } |
---|
1944 | 2153 | |
---|
1945 | | - spin_unlock_irqrestore(&dev->event_lock, spin_flags); |
---|
| 2154 | + spin_unlock_irq(&dev->event_lock); |
---|
1946 | 2155 | return 0; |
---|
1947 | 2156 | |
---|
1948 | 2157 | err_unlock: |
---|
1949 | | - spin_unlock_irqrestore(&dev->event_lock, spin_flags); |
---|
| 2158 | + spin_unlock_irq(&dev->event_lock); |
---|
1950 | 2159 | drm_crtc_vblank_put(crtc); |
---|
1951 | 2160 | err_free: |
---|
1952 | 2161 | kfree(e); |
---|
1953 | 2162 | return ret; |
---|
1954 | 2163 | } |
---|
| 2164 | + |
---|