aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 7ea647b84733..d680608f6f5b 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -306,7 +306,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
306 * to complete in this vblank? 306 * to complete in this vblank?
307 */ 307 */
308 if (update_pending && 308 if (update_pending &&
309 (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 309 (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
310 &vpos, &hpos, NULL, NULL)) && 310 &vpos, &hpos, NULL, NULL)) &&
311 ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || 311 ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
312 (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { 312 (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
@@ -1610,6 +1610,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
1610 * 1610 *
1611 * \param dev Device to query. 1611 * \param dev Device to query.
1612 * \param crtc Crtc to query. 1612 * \param crtc Crtc to query.
1613 * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
1613 * \param *vpos Location where vertical scanout position should be stored. 1614 * \param *vpos Location where vertical scanout position should be stored.
1614 * \param *hpos Location where horizontal scanout position should go. 1615 * \param *hpos Location where horizontal scanout position should go.
1615 * \param *stime Target location for timestamp taken immediately before 1616 * \param *stime Target location for timestamp taken immediately before
@@ -1631,8 +1632,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
1631 * unknown small number of scanlines wrt. real scanout position. 1632 * unknown small number of scanlines wrt. real scanout position.
1632 * 1633 *
1633 */ 1634 */
1634int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos, 1635int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
1635 ktime_t *stime, ktime_t *etime) 1636 int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
1636{ 1637{
1637 u32 stat_crtc = 0, vbl = 0, position = 0; 1638 u32 stat_crtc = 0, vbl = 0, position = 0;
1638 int vbl_start, vbl_end, vtotal, ret = 0; 1639 int vbl_start, vbl_end, vtotal, ret = 0;
@@ -1774,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int
1774 if (in_vbl) 1775 if (in_vbl)
1775 ret |= DRM_SCANOUTPOS_INVBL; 1776 ret |= DRM_SCANOUTPOS_INVBL;
1776 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
1777 return ret; 1800 return ret;
1778} 1801}