]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/radeon/radeon_display.c
Merge tag 'iio-fixes-for-3.14a' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / drivers / gpu / drm / radeon / radeon_display.c
index 567215be4728df769a53fc227218ec709820bc31..d680608f6f5bc9a80e879b4f24769f8a9ffb1e8c 100644 (file)
@@ -1775,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
        if (in_vbl)
                ret |= DRM_SCANOUTPOS_INVBL;
 
+       /* Is vpos outside nominal vblank area, but less than
+        * 1/100 of a frame height away from start of vblank?
+        * If so, assume this isn't a massively delayed vblank
+        * interrupt, but a vblank interrupt that fired a few
+        * microseconds before true start of vblank. Compensate
+        * by adding a full frame duration to the final timestamp.
+        * Happens, e.g., on ATI R500, R600.
+        *
+        * We only do this if DRM_CALLED_FROM_VBLIRQ.
+        */
+       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
+               vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+               vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+
+               if (vbl_start - *vpos < vtotal / 100) {
+                       *vpos -= vtotal;
+
+                       /* Signal this correction as "applied". */
+                       ret |= 0x8;
+               }
+       }
+
        return ret;
 }