| .. | .. |
|---|
| 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 | + |
|---|