From da1d4b1251f63a43e2f590a480fd74dfcb09d1b5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 26 Oct 2012 10:03:47 -0400 Subject: [PATCH] drm/radeon: further fixes for evergreen_mc_stop/resume Take the crtc hw lock when updating the crtc registers. This forces updates to be atomic rather than double buffered. May fix: https://bugs.freedesktop.org/show_bug.cgi?id=56139 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 14313ad..6922705 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1308,6 +1308,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; if (crtc_enabled) { save->crtc_enabled[i] = true; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { @@ -1323,6 +1324,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); } } + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); /* wait for the next frame */ frame_count = radeon_get_vblank_counter(rdev, i); for (j = 0; j < rdev->usec_timeout; j++) { @@ -1352,6 +1354,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s /* update crtc base addresses */ for (i = 0; i < rdev->num_crtc; i++) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], @@ -1360,6 +1363,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s (u32)rdev->mc.vram_start); WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); @@ -1373,6 +1377,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s for (i = 0; i < rdev->num_crtc; i++) { if (save->crtc_enabled) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; @@ -1382,6 +1387,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); } + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); /* wait for the next frame */ frame_count = radeon_get_vblank_counter(rdev, i); for (j = 0; j < rdev->usec_timeout; j++) { -- 1.7.7.5