diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-08-15 17:18:42 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 13:10:33 -0400 |
commit | 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 (patch) | |
tree | 818b15a0c9503e39210967c1d7adc021c5cfe53a /drivers/gpu/drm/radeon/evergreen.c | |
parent | 75104fa4f98cdac5e97be5cb59463d49eb08da85 (diff) |
drm/radeon: properly handle mc_stop/mc_resume on evergreen+ (v2)
- Stop the displays from accessing the FB
- Block CPU access
- Turn off MC client access
This should fix issues some users have seen, especially
with UEFI, when changing the MC FB location that result
in hangs or display corruption.
v2: fix crtc enabled check noticed by Luca Tettamanti
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 169 |
1 files changed, 78 insertions, 91 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 585c11741d02..bea39e7d9a51 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1241,116 +1241,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) | |||
1241 | 1241 | ||
1242 | void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1242 | void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) |
1243 | { | 1243 | { |
1244 | u32 crtc_enabled, tmp, frame_count, blackout; | ||
1245 | int i, j; | ||
1246 | |||
1244 | save->vga_render_control = RREG32(VGA_RENDER_CONTROL); | 1247 | save->vga_render_control = RREG32(VGA_RENDER_CONTROL); |
1245 | save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); | 1248 | save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); |
1246 | 1249 | ||
1247 | /* Stop all video */ | 1250 | /* disable VGA render */ |
1248 | WREG32(VGA_RENDER_CONTROL, 0); | 1251 | WREG32(VGA_RENDER_CONTROL, 0); |
1249 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); | 1252 | /* blank the display controllers */ |
1250 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); | 1253 | for (i = 0; i < rdev->num_crtc; i++) { |
1251 | if (rdev->num_crtc >= 4) { | 1254 | crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; |
1252 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); | 1255 | if (crtc_enabled) { |
1253 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); | 1256 | save->crtc_enabled[i] = true; |
1254 | } | 1257 | if (ASIC_IS_DCE6(rdev)) { |
1255 | if (rdev->num_crtc >= 6) { | 1258 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); |
1256 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); | 1259 | if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { |
1257 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); | 1260 | radeon_wait_for_vblank(rdev, i); |
1258 | } | 1261 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
1259 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); | 1262 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
1260 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); | 1263 | } |
1261 | if (rdev->num_crtc >= 4) { | 1264 | } else { |
1262 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); | 1265 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
1263 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); | 1266 | if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { |
1264 | } | 1267 | radeon_wait_for_vblank(rdev, i); |
1265 | if (rdev->num_crtc >= 6) { | 1268 | tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
1266 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); | 1269 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
1267 | WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); | 1270 | } |
1268 | } | 1271 | } |
1269 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); | 1272 | /* wait for the next frame */ |
1270 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); | 1273 | frame_count = radeon_get_vblank_counter(rdev, i); |
1271 | if (rdev->num_crtc >= 4) { | 1274 | for (j = 0; j < rdev->usec_timeout; j++) { |
1272 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); | 1275 | if (radeon_get_vblank_counter(rdev, i) != frame_count) |
1273 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); | 1276 | break; |
1274 | } | 1277 | udelay(1); |
1275 | if (rdev->num_crtc >= 6) { | 1278 | } |
1276 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); | 1279 | } |
1277 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); | ||
1278 | } | 1280 | } |
1279 | 1281 | ||
1280 | WREG32(D1VGA_CONTROL, 0); | 1282 | radeon_mc_wait_for_idle(rdev); |
1281 | WREG32(D2VGA_CONTROL, 0); | 1283 | |
1282 | if (rdev->num_crtc >= 4) { | 1284 | blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); |
1283 | WREG32(EVERGREEN_D3VGA_CONTROL, 0); | 1285 | if ((blackout & BLACKOUT_MODE_MASK) != 1) { |
1284 | WREG32(EVERGREEN_D4VGA_CONTROL, 0); | 1286 | /* Block CPU access */ |
1285 | } | 1287 | WREG32(BIF_FB_EN, 0); |
1286 | if (rdev->num_crtc >= 6) { | 1288 | /* blackout the MC */ |
1287 | WREG32(EVERGREEN_D5VGA_CONTROL, 0); | 1289 | blackout &= ~BLACKOUT_MODE_MASK; |
1288 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); | 1290 | WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); |
1289 | } | 1291 | } |
1290 | } | 1292 | } |
1291 | 1293 | ||
1292 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1294 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
1293 | { | 1295 | { |
1294 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, | 1296 | u32 tmp, frame_count; |
1295 | upper_32_bits(rdev->mc.vram_start)); | 1297 | int i, j; |
1296 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, | ||
1297 | upper_32_bits(rdev->mc.vram_start)); | ||
1298 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, | ||
1299 | (u32)rdev->mc.vram_start); | ||
1300 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, | ||
1301 | (u32)rdev->mc.vram_start); | ||
1302 | |||
1303 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, | ||
1304 | upper_32_bits(rdev->mc.vram_start)); | ||
1305 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, | ||
1306 | upper_32_bits(rdev->mc.vram_start)); | ||
1307 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, | ||
1308 | (u32)rdev->mc.vram_start); | ||
1309 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, | ||
1310 | (u32)rdev->mc.vram_start); | ||
1311 | |||
1312 | if (rdev->num_crtc >= 4) { | ||
1313 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, | ||
1314 | upper_32_bits(rdev->mc.vram_start)); | ||
1315 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, | ||
1316 | upper_32_bits(rdev->mc.vram_start)); | ||
1317 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, | ||
1318 | (u32)rdev->mc.vram_start); | ||
1319 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, | ||
1320 | (u32)rdev->mc.vram_start); | ||
1321 | |||
1322 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, | ||
1323 | upper_32_bits(rdev->mc.vram_start)); | ||
1324 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, | ||
1325 | upper_32_bits(rdev->mc.vram_start)); | ||
1326 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, | ||
1327 | (u32)rdev->mc.vram_start); | ||
1328 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, | ||
1329 | (u32)rdev->mc.vram_start); | ||
1330 | } | ||
1331 | if (rdev->num_crtc >= 6) { | ||
1332 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, | ||
1333 | upper_32_bits(rdev->mc.vram_start)); | ||
1334 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, | ||
1335 | upper_32_bits(rdev->mc.vram_start)); | ||
1336 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, | ||
1337 | (u32)rdev->mc.vram_start); | ||
1338 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, | ||
1339 | (u32)rdev->mc.vram_start); | ||
1340 | 1298 | ||
1341 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, | 1299 | /* update crtc base addresses */ |
1300 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1301 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], | ||
1342 | upper_32_bits(rdev->mc.vram_start)); | 1302 | upper_32_bits(rdev->mc.vram_start)); |
1343 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, | 1303 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], |
1344 | upper_32_bits(rdev->mc.vram_start)); | 1304 | upper_32_bits(rdev->mc.vram_start)); |
1345 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, | 1305 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], |
1346 | (u32)rdev->mc.vram_start); | 1306 | (u32)rdev->mc.vram_start); |
1347 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, | 1307 | WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], |
1348 | (u32)rdev->mc.vram_start); | 1308 | (u32)rdev->mc.vram_start); |
1349 | } | 1309 | } |
1350 | |||
1351 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); | 1310 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); |
1352 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); | 1311 | WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); |
1353 | /* Unlock host access */ | 1312 | |
1313 | /* unblackout the MC */ | ||
1314 | tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); | ||
1315 | tmp &= ~BLACKOUT_MODE_MASK; | ||
1316 | WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); | ||
1317 | /* allow CPU access */ | ||
1318 | WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); | ||
1319 | |||
1320 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1321 | if (save->crtc_enabled) { | ||
1322 | if (ASIC_IS_DCE6(rdev)) { | ||
1323 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); | ||
1324 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; | ||
1325 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); | ||
1326 | } else { | ||
1327 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); | ||
1328 | tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; | ||
1329 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); | ||
1330 | } | ||
1331 | /* wait for the next frame */ | ||
1332 | frame_count = radeon_get_vblank_counter(rdev, i); | ||
1333 | for (j = 0; j < rdev->usec_timeout; j++) { | ||
1334 | if (radeon_get_vblank_counter(rdev, i) != frame_count) | ||
1335 | break; | ||
1336 | udelay(1); | ||
1337 | } | ||
1338 | } | ||
1339 | } | ||
1340 | /* Unlock vga access */ | ||
1354 | WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); | 1341 | WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); |
1355 | mdelay(1); | 1342 | mdelay(1); |
1356 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); | 1343 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); |