Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: Move the early vblank IRQ fixup to radeon_get_crtc_scanoutpos()

i915 doesn't need this kludge for most platforms. Although we do
appear to need something similar on certain platforms, but we can
be more accurate when we apply the adjustment since we know exactly
why the scanline counter doesn't always quite match the vblank
status.

Also the current code doesn't handle interlaced modes correctly,
and we already deal with interlaced modes in i915 code.

So let's just move the current code to radeon_get_crtc_scanoutpos()
since that's why it was added. For i915 we'll add a more finely
targeted variant.

v2: Fix vpos vs. *vpos bug (Mario)

Reviewed-by: mario.kleiner.de@gmail.com
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

+24 -23
+2 -23
drivers/gpu/drm/drm_irq.c
··· 542 542 { 543 543 ktime_t stime, etime, mono_time_offset; 544 544 struct timeval tv_etime; 545 - int vbl_status, vtotal, vdisplay; 545 + int vbl_status; 546 546 int vpos, hpos, i; 547 547 int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; 548 548 bool invbl; ··· 558 558 return -EIO; 559 559 } 560 560 561 - vtotal = mode->crtc_vtotal; 562 - vdisplay = mode->crtc_vdisplay; 563 - 564 561 /* Durations of frames, lines, pixels in nanoseconds. */ 565 562 framedur_ns = refcrtc->framedur_ns; 566 563 linedur_ns = refcrtc->linedur_ns; ··· 566 569 /* If mode timing undefined, just return as no-op: 567 570 * Happens during initial modesetting of a crtc. 568 571 */ 569 - if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { 572 + if (framedur_ns == 0) { 570 573 DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); 571 574 return -EAGAIN; 572 575 } ··· 629 632 * can be negative if start of scanout hasn't happened yet. 630 633 */ 631 634 delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; 632 - 633 - /* Is vpos outside nominal vblank area, but less than 634 - * 1/100 of a frame height away from start of vblank? 635 - * If so, assume this isn't a massively delayed vblank 636 - * interrupt, but a vblank interrupt that fired a few 637 - * microseconds before true start of vblank. Compensate 638 - * by adding a full frame duration to the final timestamp. 639 - * Happens, e.g., on ATI R500, R600. 640 - * 641 - * We only do this if DRM_CALLED_FROM_VBLIRQ. 642 - */ 643 - if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl && 644 - ((vdisplay - vpos) < vtotal / 100)) { 645 - delta_ns = delta_ns - framedur_ns; 646 - 647 - /* Signal this correction as "applied". */ 648 - vbl_status |= 0x8; 649 - } 650 635 651 636 if (!drm_timestamp_monotonic) 652 637 etime = ktime_sub(etime, mono_time_offset);
+22
drivers/gpu/drm/radeon/radeon_display.c
··· 1775 1775 if (in_vbl) 1776 1776 ret |= DRM_SCANOUTPOS_INVBL; 1777 1777 1778 + /* Is vpos outside nominal vblank area, but less than 1779 + * 1/100 of a frame height away from start of vblank? 1780 + * If so, assume this isn't a massively delayed vblank 1781 + * interrupt, but a vblank interrupt that fired a few 1782 + * microseconds before true start of vblank. Compensate 1783 + * by adding a full frame duration to the final timestamp. 1784 + * Happens, e.g., on ATI R500, R600. 1785 + * 1786 + * We only do this if DRM_CALLED_FROM_VBLIRQ. 1787 + */ 1788 + if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { 1789 + vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; 1790 + vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; 1791 + 1792 + if (vbl_start - *vpos < vtotal / 100) { 1793 + *vpos -= vtotal; 1794 + 1795 + /* Signal this correction as "applied". */ 1796 + ret |= 0x8; 1797 + } 1798 + } 1799 + 1778 1800 return ret; 1779 1801 }