diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2012-12-12 14:30:32 -0500 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2012-12-12 14:34:08 -0500 |
| commit | 6253e4c75d96006c06b9ac8f417eba873de2497b (patch) | |
| tree | cf582d44c381f4732364d9947ebc6f05d61cc963 | |
| parent | bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a (diff) | |
drm/radeon: improve mc_stop/mc_resume on r5xx-r7xx
Along the same lines of what was done for evergreen+
in the last kernel.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_reg.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/rv515.c | 122 |
3 files changed, 116 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index 2b960cb5c18a..909219b1bf80 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h | |||
| @@ -96,6 +96,15 @@ | |||
| 96 | #define R600_CONFIG_F0_BASE 0x542C | 96 | #define R600_CONFIG_F0_BASE 0x542C |
| 97 | #define R600_CONFIG_APER_SIZE 0x5430 | 97 | #define R600_CONFIG_APER_SIZE 0x5430 |
| 98 | 98 | ||
| 99 | #define R600_BIF_FB_EN 0x5490 | ||
| 100 | #define R600_FB_READ_EN (1 << 0) | ||
| 101 | #define R600_FB_WRITE_EN (1 << 1) | ||
| 102 | |||
| 103 | #define R600_CITF_CNTL 0x200c | ||
| 104 | #define R600_BLACKOUT_MASK 0x00000003 | ||
| 105 | |||
| 106 | #define R700_MC_CITF_CNTL 0x25c0 | ||
| 107 | |||
| 99 | #define R600_ROM_CNTL 0x1600 | 108 | #define R600_ROM_CNTL 0x1600 |
| 100 | # define R600_SCK_OVERWRITE (1 << 1) | 109 | # define R600_SCK_OVERWRITE (1 << 1) |
| 101 | # define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 | 110 | # define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index ae56673d2410..c338931190a5 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -263,6 +263,7 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); | |||
| 263 | struct rv515_mc_save { | 263 | struct rv515_mc_save { |
| 264 | u32 vga_render_control; | 264 | u32 vga_render_control; |
| 265 | u32 vga_hdp_control; | 265 | u32 vga_hdp_control; |
| 266 | bool crtc_enabled[2]; | ||
| 266 | }; | 267 | }; |
| 267 | 268 | ||
| 268 | int rv515_init(struct radeon_device *rdev); | 269 | int rv515_init(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 785d09590b24..2bb6d0e84b3d 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -40,6 +40,12 @@ static int rv515_debugfs_ga_info_init(struct radeon_device *rdev); | |||
| 40 | static void rv515_gpu_init(struct radeon_device *rdev); | 40 | static void rv515_gpu_init(struct radeon_device *rdev); |
| 41 | int rv515_mc_wait_for_idle(struct radeon_device *rdev); | 41 | int rv515_mc_wait_for_idle(struct radeon_device *rdev); |
| 42 | 42 | ||
| 43 | static const u32 crtc_offsets[2] = | ||
| 44 | { | ||
| 45 | 0, | ||
| 46 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL | ||
| 47 | }; | ||
| 48 | |||
| 43 | void rv515_debugfs(struct radeon_device *rdev) | 49 | void rv515_debugfs(struct radeon_device *rdev) |
| 44 | { | 50 | { |
| 45 | if (r100_debugfs_rbbm_init(rdev)) { | 51 | if (r100_debugfs_rbbm_init(rdev)) { |
| @@ -281,30 +287,114 @@ static int rv515_debugfs_ga_info_init(struct radeon_device *rdev) | |||
| 281 | 287 | ||
| 282 | void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) | 288 | void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) |
| 283 | { | 289 | { |
| 290 | u32 crtc_enabled, tmp, frame_count, blackout; | ||
| 291 | int i, j; | ||
| 292 | |||
| 284 | save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); | 293 | save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); |
| 285 | save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); | 294 | save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); |
| 286 | 295 | ||
| 287 | /* Stop all video */ | 296 | /* disable VGA render */ |
| 288 | WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); | ||
| 289 | WREG32(R_000300_VGA_RENDER_CONTROL, 0); | 297 | WREG32(R_000300_VGA_RENDER_CONTROL, 0); |
| 290 | WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); | 298 | /* blank the display controllers */ |
| 291 | WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); | 299 | for (i = 0; i < rdev->num_crtc; i++) { |
| 292 | WREG32(R_006080_D1CRTC_CONTROL, 0); | 300 | crtc_enabled = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN; |
| 293 | WREG32(R_006880_D2CRTC_CONTROL, 0); | 301 | if (crtc_enabled) { |
| 294 | WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); | 302 | save->crtc_enabled[i] = true; |
| 295 | WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); | 303 | tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); |
| 296 | WREG32(R_000330_D1VGA_CONTROL, 0); | 304 | if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) { |
| 297 | WREG32(R_000338_D2VGA_CONTROL, 0); | 305 | radeon_wait_for_vblank(rdev, i); |
| 306 | tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; | ||
| 307 | WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); | ||
| 308 | } | ||
| 309 | /* wait for the next frame */ | ||
| 310 | frame_count = radeon_get_vblank_counter(rdev, i); | ||
| 311 | for (j = 0; j < rdev->usec_timeout; j++) { | ||
| 312 | if (radeon_get_vblank_counter(rdev, i) != frame_count) | ||
| 313 | break; | ||
| 314 | udelay(1); | ||
| 315 | } | ||
| 316 | } else { | ||
| 317 | save->crtc_enabled[i] = false; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | radeon_mc_wait_for_idle(rdev); | ||
| 322 | |||
| 323 | if (rdev->family >= CHIP_R600) { | ||
| 324 | if (rdev->family >= CHIP_RV770) | ||
| 325 | blackout = RREG32(R700_MC_CITF_CNTL); | ||
| 326 | else | ||
| 327 | blackout = RREG32(R600_CITF_CNTL); | ||
| 328 | if ((blackout & R600_BLACKOUT_MASK) != R600_BLACKOUT_MASK) { | ||
| 329 | /* Block CPU access */ | ||
| 330 | WREG32(R600_BIF_FB_EN, 0); | ||
| 331 | /* blackout the MC */ | ||
| 332 | blackout |= R600_BLACKOUT_MASK; | ||
| 333 | if (rdev->family >= CHIP_RV770) | ||
| 334 | WREG32(R700_MC_CITF_CNTL, blackout); | ||
| 335 | else | ||
| 336 | WREG32(R600_CITF_CNTL, blackout); | ||
| 337 | } | ||
| 338 | } | ||
| 298 | } | 339 | } |
| 299 | 340 | ||
| 300 | void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) | 341 | void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) |
| 301 | { | 342 | { |
| 302 | WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start); | 343 | u32 tmp, frame_count; |
| 303 | WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start); | 344 | int i, j; |
| 304 | WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start); | 345 | |
| 305 | WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start); | 346 | /* update crtc base addresses */ |
| 306 | WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start); | 347 | for (i = 0; i < rdev->num_crtc; i++) { |
| 307 | /* Unlock host access */ | 348 | if (rdev->family >= CHIP_RV770) { |
| 349 | if (i == 1) { | ||
| 350 | WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, | ||
| 351 | upper_32_bits(rdev->mc.vram_start)); | ||
| 352 | WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, | ||
| 353 | upper_32_bits(rdev->mc.vram_start)); | ||
| 354 | } else { | ||
| 355 | WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, | ||
| 356 | upper_32_bits(rdev->mc.vram_start)); | ||
| 357 | WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, | ||
| 358 | upper_32_bits(rdev->mc.vram_start)); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], | ||
| 362 | (u32)rdev->mc.vram_start); | ||
| 363 | WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], | ||
| 364 | (u32)rdev->mc.vram_start); | ||
| 365 | } | ||
| 366 | WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); | ||
| 367 | |||
| 368 | if (rdev->family >= CHIP_R600) { | ||
| 369 | /* unblackout the MC */ | ||
| 370 | if (rdev->family >= CHIP_RV770) | ||
| 371 | tmp = RREG32(R700_MC_CITF_CNTL); | ||
| 372 | else | ||
| 373 | tmp = RREG32(R600_CITF_CNTL); | ||
| 374 | tmp &= ~R600_BLACKOUT_MASK; | ||
| 375 | if (rdev->family >= CHIP_RV770) | ||
| 376 | WREG32(R700_MC_CITF_CNTL, tmp); | ||
| 377 | else | ||
| 378 | WREG32(R600_CITF_CNTL, tmp); | ||
| 379 | /* allow CPU access */ | ||
| 380 | WREG32(R600_BIF_FB_EN, R600_FB_READ_EN | R600_FB_WRITE_EN); | ||
| 381 | } | ||
| 382 | |||
| 383 | for (i = 0; i < rdev->num_crtc; i++) { | ||
| 384 | if (save->crtc_enabled[i]) { | ||
| 385 | tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); | ||
| 386 | tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; | ||
| 387 | WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); | ||
| 388 | /* wait for the next frame */ | ||
| 389 | frame_count = radeon_get_vblank_counter(rdev, i); | ||
| 390 | for (j = 0; j < rdev->usec_timeout; j++) { | ||
| 391 | if (radeon_get_vblank_counter(rdev, i) != frame_count) | ||
| 392 | break; | ||
| 393 | udelay(1); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | /* Unlock vga access */ | ||
| 308 | WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); | 398 | WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); |
| 309 | mdelay(1); | 399 | mdelay(1); |
| 310 | WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); | 400 | WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); |
