aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/evergreen.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-08-15 17:18:42 -0400
committerAlex Deucher <alexander.deucher@amd.com>2012-09-20 13:10:33 -0400
commit62444b7462a2b98bc78d68736c03a7c4e66ba7e2 (patch)
tree818b15a0c9503e39210967c1d7adc021c5cfe53a /drivers/gpu/drm/radeon/evergreen.c
parent75104fa4f98cdac5e97be5cb59463d49eb08da85 (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.c169
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
1242void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) 1242void 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
1292void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) 1294void 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);