diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-02-15 16:49:59 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 19:16:29 -0400 |
commit | d719cef316d6377a7d6b5df495de118afb3a9fc2 (patch) | |
tree | 9b513e9940dd7c1b315ce54aae395d21bbbdd726 /drivers/gpu/drm/radeon/si.c | |
parent | 8ba104637b5901cdc52fb0455cefcc73dc4b10e4 (diff) |
drm/radeon: update rlc programming sequence on SI
This is required for certain power management features.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/si.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 9fd0bc379f36..84ed3325a0d9 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -4418,14 +4418,93 @@ int si_rlc_init(struct radeon_device *rdev) | |||
4418 | return 0; | 4418 | return 0; |
4419 | } | 4419 | } |
4420 | 4420 | ||
4421 | static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, | ||
4422 | bool enable) | ||
4423 | { | ||
4424 | u32 tmp = RREG32(CP_INT_CNTL_RING0); | ||
4425 | u32 mask; | ||
4426 | int i; | ||
4427 | |||
4428 | if (enable) | ||
4429 | tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); | ||
4430 | else | ||
4431 | tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); | ||
4432 | WREG32(CP_INT_CNTL_RING0, tmp); | ||
4433 | |||
4434 | if (!enable) { | ||
4435 | /* read a gfx register */ | ||
4436 | tmp = RREG32(DB_DEPTH_INFO); | ||
4437 | |||
4438 | mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS; | ||
4439 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
4440 | if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS)) | ||
4441 | break; | ||
4442 | udelay(1); | ||
4443 | } | ||
4444 | } | ||
4445 | } | ||
4446 | |||
4447 | static void si_wait_for_rlc_serdes(struct radeon_device *rdev) | ||
4448 | { | ||
4449 | int i; | ||
4450 | |||
4451 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
4452 | if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0) | ||
4453 | break; | ||
4454 | udelay(1); | ||
4455 | } | ||
4456 | |||
4457 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
4458 | if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0) | ||
4459 | break; | ||
4460 | udelay(1); | ||
4461 | } | ||
4462 | } | ||
4463 | |||
4421 | static void si_rlc_stop(struct radeon_device *rdev) | 4464 | static void si_rlc_stop(struct radeon_device *rdev) |
4422 | { | 4465 | { |
4423 | WREG32(RLC_CNTL, 0); | 4466 | WREG32(RLC_CNTL, 0); |
4467 | |||
4468 | si_enable_gui_idle_interrupt(rdev, false); | ||
4469 | |||
4470 | si_wait_for_rlc_serdes(rdev); | ||
4424 | } | 4471 | } |
4425 | 4472 | ||
4426 | static void si_rlc_start(struct radeon_device *rdev) | 4473 | static void si_rlc_start(struct radeon_device *rdev) |
4427 | { | 4474 | { |
4428 | WREG32(RLC_CNTL, RLC_ENABLE); | 4475 | WREG32(RLC_CNTL, RLC_ENABLE); |
4476 | |||
4477 | si_enable_gui_idle_interrupt(rdev, true); | ||
4478 | |||
4479 | udelay(50); | ||
4480 | } | ||
4481 | |||
4482 | static bool si_lbpw_supported(struct radeon_device *rdev) | ||
4483 | { | ||
4484 | u32 tmp; | ||
4485 | |||
4486 | /* Enable LBPW only for DDR3 */ | ||
4487 | tmp = RREG32(MC_SEQ_MISC0); | ||
4488 | if ((tmp & 0xF0000000) == 0xB0000000) | ||
4489 | return true; | ||
4490 | return false; | ||
4491 | } | ||
4492 | |||
4493 | static void si_enable_lbpw(struct radeon_device *rdev, bool enable) | ||
4494 | { | ||
4495 | u32 tmp; | ||
4496 | |||
4497 | tmp = RREG32(RLC_LB_CNTL); | ||
4498 | if (enable) | ||
4499 | tmp |= LOAD_BALANCE_ENABLE; | ||
4500 | else | ||
4501 | tmp &= ~LOAD_BALANCE_ENABLE; | ||
4502 | WREG32(RLC_LB_CNTL, tmp); | ||
4503 | |||
4504 | if (!enable) { | ||
4505 | si_select_se_sh(rdev, 0xffffffff, 0xffffffff); | ||
4506 | WREG32(SPI_LB_CU_MASK, 0x00ff); | ||
4507 | } | ||
4429 | } | 4508 | } |
4430 | 4509 | ||
4431 | static int si_rlc_resume(struct radeon_device *rdev) | 4510 | static int si_rlc_resume(struct radeon_device *rdev) |
@@ -4443,6 +4522,7 @@ static int si_rlc_resume(struct radeon_device *rdev) | |||
4443 | WREG32(RLC_LB_CNTL, 0); | 4522 | WREG32(RLC_LB_CNTL, 0); |
4444 | WREG32(RLC_LB_CNTR_MAX, 0xffffffff); | 4523 | WREG32(RLC_LB_CNTR_MAX, 0xffffffff); |
4445 | WREG32(RLC_LB_CNTR_INIT, 0); | 4524 | WREG32(RLC_LB_CNTR_INIT, 0); |
4525 | WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff); | ||
4446 | 4526 | ||
4447 | WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); | 4527 | WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); |
4448 | WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); | 4528 | WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); |
@@ -4457,6 +4537,8 @@ static int si_rlc_resume(struct radeon_device *rdev) | |||
4457 | } | 4537 | } |
4458 | WREG32(RLC_UCODE_ADDR, 0); | 4538 | WREG32(RLC_UCODE_ADDR, 0); |
4459 | 4539 | ||
4540 | si_enable_lbpw(rdev, si_lbpw_supported(rdev)); | ||
4541 | |||
4460 | si_rlc_start(rdev); | 4542 | si_rlc_start(rdev); |
4461 | 4543 | ||
4462 | return 0; | 4544 | return 0; |