Rev 5060 | Rev 6084 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 5271 | ||
---|---|---|---|
Line 31... | Line 31... | ||
31 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
31 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
32 | * OTHER DEALINGS IN THE SOFTWARE. |
32 | * OTHER DEALINGS IN THE SOFTWARE. |
33 | */ |
33 | */ |
Line 34... | Line 34... | ||
34 | 34 | ||
35 | #include |
- | |
36 | #include |
35 | #include |
- | 36 | //#include "drm_trace.h" |
|
Line 37... | Line 37... | ||
37 | //#include "drm_trace.h" |
37 | #include "drm_internal.h" |
38 | 38 | ||
Line 39... | Line 39... | ||
39 | //#include |
39 | //#include |
40 | #include |
40 | #include |
Line 41... | Line 41... | ||
41 | 41 | ||
42 | //#include |
42 | #include |
43 | #include |
43 | #include |
Line 54... | Line 54... | ||
54 | /* Threshold in nanoseconds for detection of redundant |
54 | /* Threshold in nanoseconds for detection of redundant |
55 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
55 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
56 | */ |
56 | */ |
57 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
57 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
Line -... | Line 58... | ||
- | 58 | ||
- | 59 | static bool |
|
- | 60 | drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, |
|
- | 61 | struct timeval *tvblank, unsigned flags); |
|
- | 62 | ||
- | 63 | static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ |
|
58 | 64 | ||
59 | /* |
65 | /* |
60 | * Clear vblank timestamp buffer for a crtc. |
66 | * Clear vblank timestamp buffer for a crtc. |
Line 84... | Line 90... | ||
84 | dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
90 | dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
85 | if (!dev->vblank) |
91 | if (!dev->vblank) |
86 | goto err; |
92 | goto err; |
Line 87... | Line 93... | ||
87 | 93 | ||
- | 94 | for (i = 0; i < num_crtcs; i++) { |
|
- | 95 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
|
88 | for (i = 0; i < num_crtcs; i++) { |
96 | |
89 | dev->vblank[i].dev = dev; |
97 | vblank->dev = dev; |
90 | dev->vblank[i].crtc = i; |
98 | vblank->crtc = i; |
91 | init_waitqueue_head(&dev->vblank[i].queue); |
99 | init_waitqueue_head(&vblank->queue); |
92 | setup_timer(&dev->vblank[i].disable_timer, vblank_disable_fn, |
100 | setup_timer(&vblank->disable_timer, vblank_disable_fn, |
93 | (unsigned long)&dev->vblank[i]); |
101 | (unsigned long)vblank); |
Line 94... | Line 102... | ||
94 | } |
102 | } |
Line 95... | Line 103... | ||
95 | 103 | ||
Line 104... | Line 112... | ||
104 | dev->vblank_disable_allowed = false; |
112 | dev->vblank_disable_allowed = false; |
Line 105... | Line 113... | ||
105 | 113 | ||
Line 106... | Line 114... | ||
106 | return 0; |
114 | return 0; |
107 | 115 | ||
108 | err: |
116 | err: |
109 | drm_vblank_cleanup(dev); |
117 | dev->num_crtcs = 0; |
110 | return ret; |
118 | return ret; |
Line 111... | Line 119... | ||
111 | } |
119 | } |
Line 176... | Line 184... | ||
176 | DRM_ERROR(__FUNCTION__); |
184 | DRM_ERROR(__FUNCTION__); |
177 | } else { |
185 | } else { |
178 | dev->irq = irq; |
186 | dev->irq = irq; |
179 | } |
187 | } |
Line 180... | Line 188... | ||
180 | 188 | ||
181 | u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4); |
189 | u16 cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4); |
182 | cmd&= ~(1<<10); |
190 | cmd&= ~(1<<10); |
Line 183... | Line 191... | ||
183 | PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd); |
191 | PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd); |
184 | 192 | ||
Line 343... | Line 351... | ||
343 | return -EIO; |
351 | return -EIO; |
344 | } |
352 | } |
345 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
353 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
Line 346... | Line 354... | ||
346 | 354 | ||
- | 355 | /** |
|
- | 356 | * drm_vblank_get - get a reference count on vblank events |
|
- | 357 | * @dev: DRM device |
|
- | 358 | * @crtc: which CRTC to own |
|
- | 359 | * |
|
- | 360 | * Acquire a reference count on vblank events to avoid having them disabled |
|
- | 361 | * while in use. |
|
- | 362 | * |
|
- | 363 | * This is the legacy version of drm_crtc_vblank_get(). |
|
- | 364 | * |
|
- | 365 | * Returns: |
|
- | 366 | * Zero on success, nonzero on failure. |
|
- | 367 | */ |
|
- | 368 | int drm_vblank_get(struct drm_device *dev, int crtc) |
|
- | 369 | { |
|
- | 370 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
|
- | 371 | unsigned long irqflags; |
|
- | 372 | int ret = 0; |
|
- | 373 | #if 0 |
|
- | 374 | ||
- | 375 | if (WARN_ON(crtc >= dev->num_crtcs)) |
|
- | 376 | return -EINVAL; |
|
- | 377 | ||
- | 378 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
|
- | 379 | /* Going from 0->1 means we have to enable interrupts again */ |
|
- | 380 | if (atomic_add_return(1, &vblank->refcount) == 1) { |
|
- | 381 | ret = drm_vblank_enable(dev, crtc); |
|
- | 382 | } else { |
|
- | 383 | if (!vblank->enabled) { |
|
- | 384 | atomic_dec(&vblank->refcount); |
|
- | 385 | ret = -EINVAL; |
|
- | 386 | } |
|
- | 387 | } |
|
- | 388 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
|
- | 389 | #endif |
|
- | 390 | return ret; |
|
- | 391 | } |
|
- | 392 | EXPORT_SYMBOL(drm_vblank_get); |
|
- | 393 | ||
- | 394 | /** |
|
- | 395 | * drm_crtc_vblank_get - get a reference count on vblank events |
|
- | 396 | * @crtc: which CRTC to own |
|
- | 397 | * |
|
- | 398 | * Acquire a reference count on vblank events to avoid having them disabled |
|
- | 399 | * while in use. |
|
- | 400 | * |
|
- | 401 | * This is the native kms version of drm_vblank_off(). |
|
- | 402 | * |
|
- | 403 | * Returns: |
|
- | 404 | * Zero on success, nonzero on failure. |
|
- | 405 | */ |
|
- | 406 | int drm_crtc_vblank_get(struct drm_crtc *crtc) |
|
- | 407 | { |
|
- | 408 | return drm_vblank_get(crtc->dev, drm_crtc_index(crtc)); |
|
- | 409 | } |
|
- | 410 | EXPORT_SYMBOL(drm_crtc_vblank_get); |
|
- | 411 | ||
- | 412 | /** |
|
- | 413 | * drm_vblank_put - give up ownership of vblank events |
|
- | 414 | * @dev: DRM device |
|
- | 415 | * @crtc: which counter to give up |
|
- | 416 | * |
|
- | 417 | * Release ownership of a given vblank counter, turning off interrupts |
|
- | 418 | * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. |
|
- | 419 | * |
|
- | 420 | * This is the legacy version of drm_crtc_vblank_put(). |
|
- | 421 | */ |
|
- | 422 | void drm_vblank_put(struct drm_device *dev, int crtc) |
|
- | 423 | { |
|
- | 424 | #if 0 |
|
- | 425 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
|
- | 426 | ||
- | 427 | if (WARN_ON(atomic_read(&vblank->refcount) == 0)) |
|
- | 428 | return; |
|
- | 429 | ||
- | 430 | if (WARN_ON(crtc >= dev->num_crtcs)) |
|
- | 431 | return; |
|
- | 432 | ||
- | 433 | /* Last user schedules interrupt disable */ |
|
- | 434 | if (atomic_dec_and_test(&vblank->refcount)) { |
|
- | 435 | if (drm_vblank_offdelay == 0) |
|
- | 436 | return; |
|
- | 437 | else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0) |
|
- | 438 | vblank_disable_fn((unsigned long)vblank); |
|
- | 439 | else |
|
- | 440 | mod_timer(&vblank->disable_timer, |
|
- | 441 | jiffies + ((drm_vblank_offdelay * HZ)/1000)); |
|
- | 442 | } |
|
- | 443 | #endif |
|
- | 444 | } |
|
- | 445 | EXPORT_SYMBOL(drm_vblank_put); |
|
- | 446 | ||
- | 447 | /** |
|
- | 448 | * drm_crtc_vblank_put - give up ownership of vblank events |
|
- | 449 | * @crtc: which counter to give up |
|
- | 450 | * |
|
- | 451 | * Release ownership of a given vblank counter, turning off interrupts |
|
- | 452 | * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. |
|
- | 453 | * |
|
- | 454 | * This is the native kms version of drm_vblank_put(). |
|
- | 455 | */ |
|
- | 456 | void drm_crtc_vblank_put(struct drm_crtc *crtc) |
|
- | 457 | { |
|
- | 458 | drm_vblank_put(crtc->dev, drm_crtc_index(crtc)); |
|
- | 459 | } |
|
- | 460 | EXPORT_SYMBOL(drm_crtc_vblank_put); |
|
- | 461 | ||
- | 462 | /** |
|
- | 463 | * drm_wait_one_vblank - wait for one vblank |
|
- | 464 | * @dev: DRM device |
|
- | 465 | * @crtc: crtc index |
|
- | 466 | * |
|
- | 467 | * This waits for one vblank to pass on @crtc, using the irq driver interfaces. |
|
- | 468 | * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. |
|
- | 469 | * due to lack of driver support or because the crtc is off. |
|
- | 470 | */ |
|
- | 471 | void drm_wait_one_vblank(struct drm_device *dev, int crtc) |
|
- | 472 | { |
|
- | 473 | #if 0 |
|
- | 474 | int ret; |
|
- | 475 | u32 last; |
|
- | 476 | ||
- | 477 | ret = drm_vblank_get(dev, crtc); |
|
- | 478 | if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret)) |
|
- | 479 | return; |
|
- | 480 | ||
- | 481 | last = drm_vblank_count(dev, crtc); |
|
- | 482 | ||
- | 483 | ret = wait_event_timeout(dev->vblank[crtc].queue, |
|
- | 484 | last != drm_vblank_count(dev, crtc), |
|
- | 485 | msecs_to_jiffies(100)); |
|
- | 486 | ||
- | 487 | WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc); |
|
- | 488 | ||
- | 489 | drm_vblank_put(dev, crtc); |
|
- | 490 | #endif |
|
- | 491 | } |
|
- | 492 | EXPORT_SYMBOL(drm_wait_one_vblank); |
|
- | 493 | ||
- | 494 | /** |
|
- | 495 | * drm_crtc_wait_one_vblank - wait for one vblank |
|
- | 496 | * @crtc: DRM crtc |
|
- | 497 | * |
|
- | 498 | * This waits for one vblank to pass on @crtc, using the irq driver interfaces. |
|
- | 499 | * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. |
|
- | 500 | * due to lack of driver support or because the crtc is off. |
|
- | 501 | */ |
|
- | 502 | void drm_crtc_wait_one_vblank(struct drm_crtc *crtc) |
|
- | 503 | { |
|
- | 504 | drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc)); |
|
- | 505 | } |
|
- | 506 | EXPORT_SYMBOL(drm_crtc_wait_one_vblank); |
|
- | 507 | ||
347 | /** |
508 | /** |
348 | * drm_vblank_off - disable vblank events on a CRTC |
509 | * drm_vblank_off - disable vblank events on a CRTC |
349 | * @dev: DRM device |
510 | * @dev: DRM device |
350 | * @crtc: CRTC in question |
511 | * @crtc: CRTC in question |
351 | * |
512 | * |
Line 358... | Line 519... | ||
358 | * |
519 | * |
359 | * This is the legacy version of drm_crtc_vblank_off(). |
520 | * This is the legacy version of drm_crtc_vblank_off(). |
360 | */ |
521 | */ |
361 | void drm_vblank_off(struct drm_device *dev, int crtc) |
522 | void drm_vblank_off(struct drm_device *dev, int crtc) |
362 | { |
523 | { |
- | 524 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
|
363 | struct drm_pending_vblank_event *e, *t; |
525 | struct drm_pending_vblank_event *e, *t; |
364 | struct timeval now; |
526 | struct timeval now; |
365 | unsigned long irqflags; |
527 | unsigned long irqflags; |
366 | unsigned int seq; |
528 | unsigned int seq; |
Line 393... | Line 555... | ||
393 | * @dev: DRM device |
555 | * @dev: DRM device |
394 | * @crtc: CRTC in question |
556 | * @crtc: CRTC in question |
395 | * |
557 | * |
396 | * This functions restores the vblank interrupt state captured with |
558 | * This functions restores the vblank interrupt state captured with |
397 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
559 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
398 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called |
560 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
399 | * in driver load code to reflect the current hardware state of the crtc. |
561 | * in driver load code to reflect the current hardware state of the crtc. |
400 | * |
562 | * |
401 | * This is the legacy version of drm_crtc_vblank_on(). |
563 | * This is the legacy version of drm_crtc_vblank_on(). |
402 | */ |
564 | */ |
403 | void drm_vblank_on(struct drm_device *dev, int crtc) |
565 | void drm_vblank_on(struct drm_device *dev, int crtc) |
404 | { |
566 | { |
- | 567 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
|
405 | unsigned long irqflags; |
568 | unsigned long irqflags; |
Line 406... | Line 569... | ||
406 | 569 | ||
407 | } |
570 | } |
Line 411... | Line 574... | ||
411 | * drm_crtc_vblank_on - enable vblank events on a CRTC |
574 | * drm_crtc_vblank_on - enable vblank events on a CRTC |
412 | * @crtc: CRTC in question |
575 | * @crtc: CRTC in question |
413 | * |
576 | * |
414 | * This functions restores the vblank interrupt state captured with |
577 | * This functions restores the vblank interrupt state captured with |
415 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
578 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
416 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called |
579 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
417 | * in driver load code to reflect the current hardware state of the crtc. |
580 | * in driver load code to reflect the current hardware state of the crtc. |
418 | * |
581 | * |
419 | * This is the native kms version of drm_vblank_on(). |
582 | * This is the native kms version of drm_vblank_on(). |
420 | */ |
583 | */ |
421 | void drm_crtc_vblank_on(struct drm_crtc *crtc) |
584 | void drm_crtc_vblank_on(struct drm_crtc *crtc) |
Line 451... | Line 614... | ||
451 | { |
614 | { |
452 | #if 0 |
615 | #if 0 |
453 | /* vblank is not initialized (IRQ not installed ?) */ |
616 | /* vblank is not initialized (IRQ not installed ?) */ |
454 | if (!dev->num_crtcs) |
617 | if (!dev->num_crtcs) |
455 | return; |
618 | return; |
- | 619 | ||
- | 620 | if (WARN_ON(crtc >= dev->num_crtcs)) |
|
- | 621 | return; |
|
- | 622 | ||
456 | /* |
623 | /* |
457 | * To avoid all the problems that might happen if interrupts |
624 | * To avoid all the problems that might happen if interrupts |
458 | * were enabled/disabled around or between these calls, we just |
625 | * were enabled/disabled around or between these calls, we just |
459 | * have the kernel take a reference on the CRTC (just once though |
626 | * have the kernel take a reference on the CRTC (just once though |
460 | * to avoid corrupting the count if multiple, mismatch calls occur), |
627 | * to avoid corrupting the count if multiple, mismatch calls occur), |
461 | * so that interrupts remain enabled in the interim. |
628 | * so that interrupts remain enabled in the interim. |
462 | */ |
629 | */ |
463 | if (!dev->vblank[crtc].inmodeset) { |
630 | if (!vblank->inmodeset) { |
464 | dev->vblank[crtc].inmodeset = 0x1; |
631 | vblank->inmodeset = 0x1; |
465 | if (drm_vblank_get(dev, crtc) == 0) |
632 | if (drm_vblank_get(dev, crtc) == 0) |
466 | dev->vblank[crtc].inmodeset |= 0x2; |
633 | vblank->inmodeset |= 0x2; |
467 | } |
634 | } |
468 | #endif |
635 | #endif |
469 | } |
636 | } |
470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
637 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
Line 484... | Line 651... | ||
484 | 651 | ||
485 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
652 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
486 | if (!dev->num_crtcs) |
653 | if (!dev->num_crtcs) |
Line 487... | Line 654... | ||
487 | return; |
654 | return; |
488 | 655 | ||
489 | if (dev->vblank[crtc].inmodeset) { |
656 | if (vblank->inmodeset) { |
490 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
657 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
Line 491... | Line 658... | ||
491 | dev->vblank_disable_allowed = true; |
658 | dev->vblank_disable_allowed = true; |
492 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
659 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
Line 493... | Line 660... | ||
493 | 660 | ||
494 | if (dev->vblank[crtc].inmodeset & 0x2) |
661 | if (vblank->inmodeset & 0x2) |
495 | drm_vblank_put(dev, crtc); |
662 | drm_vblank_put(dev, crtc); |
496 | 663 | ||
497 | dev->vblank[crtc].inmodeset = 0; |
664 | vblank->inmodeset = 0; |
- | 665 | } |
|
- | 666 | #endif |