3.6.11.4 stable review patch. If anyone has any objections, please let me know. ------------------ From: Alex Deucher [ Upstream commit bea5497bfc1067620c8c8e9d37a42e0bb6d7d7fa ] Properly wait for the next vblank region. The previous code didn't always wait long enough depending on the timing. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Steven Rostedt --- drivers/gpu/drm/radeon/rs600.c | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5301b3d..78aa835 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -46,21 +46,61 @@ void rs600_gpu_init(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev); +static bool avivo_is_in_vblank(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + + if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK) + return true; + else + return false; +} + +static bool avivo_is_counter_moving(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + u32 pos1, pos2; + + pos1 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + radeon_crtc->crtc_offset); + pos2 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + radeon_crtc->crtc_offset); + + if (pos1 != pos2) + return true; + else + return false; +} + +/** + * avivo_wait_for_vblank - vblank wait asic callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to wait for vblank on + * + * Wait for vblank on the requested crtc (r5xx-r7xx). + */ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - int i; + unsigned i = 0; + + if (!(RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN)) + return; - if (RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN) { - for (i = 0; i < rdev->usec_timeout; i++) { - if (!(RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK)) + /* depending on when we hit vblank, we may be close to active; if so, + * wait for another frame. + */ + while (avivo_is_in_vblank(rdev, crtc)) { + if (i++ % 100 == 0) { + if (!avivo_is_counter_moving(rdev, crtc)) break; udelay(1); } - for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK) + } + + while (!avivo_is_in_vblank(rdev, crtc)) { + if (i++ % 100 == 0) { + if (!avivo_is_counter_moving(rdev, crtc)) break; - udelay(1); } } } -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/