aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-12-12 14:30:32 -0500
committerAlex Deucher <alexander.deucher@amd.com>2012-12-12 14:34:08 -0500
commit6253e4c75d96006c06b9ac8f417eba873de2497b (patch)
treecf582d44c381f4732364d9947ebc6f05d61cc963 /drivers
parentbd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a (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.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h1
-rw-r--r--drivers/gpu/drm/radeon/rv515.c122
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);
263struct rv515_mc_save { 263struct 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
268int rv515_init(struct radeon_device *rdev); 269int 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);
40static void rv515_gpu_init(struct radeon_device *rdev); 40static void rv515_gpu_init(struct radeon_device *rdev);
41int rv515_mc_wait_for_idle(struct radeon_device *rdev); 41int rv515_mc_wait_for_idle(struct radeon_device *rdev);
42 42
43static const u32 crtc_offsets[2] =
44{
45 0,
46 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
47};
48
43void rv515_debugfs(struct radeon_device *rdev) 49void 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
282void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) 288void 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
300void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) 341void 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);