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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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); |