diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/si.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 168 |
1 files changed, 145 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 85e1edfaa3be..9a124d0608b3 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -80,6 +80,8 @@ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); | |||
80 | extern bool evergreen_is_display_hung(struct radeon_device *rdev); | 80 | extern bool evergreen_is_display_hung(struct radeon_device *rdev); |
81 | static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, | 81 | static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, |
82 | bool enable); | 82 | bool enable); |
83 | static void si_init_pg(struct radeon_device *rdev); | ||
84 | static void si_init_cg(struct radeon_device *rdev); | ||
83 | static void si_fini_pg(struct radeon_device *rdev); | 85 | static void si_fini_pg(struct radeon_device *rdev); |
84 | static void si_fini_cg(struct radeon_device *rdev); | 86 | static void si_fini_cg(struct radeon_device *rdev); |
85 | static void si_rlc_stop(struct radeon_device *rdev); | 87 | static void si_rlc_stop(struct radeon_device *rdev); |
@@ -1460,7 +1462,7 @@ static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { | |||
1460 | }; | 1462 | }; |
1461 | 1463 | ||
1462 | /* ucode loading */ | 1464 | /* ucode loading */ |
1463 | static int si_mc_load_microcode(struct radeon_device *rdev) | 1465 | int si_mc_load_microcode(struct radeon_device *rdev) |
1464 | { | 1466 | { |
1465 | const __be32 *fw_data; | 1467 | const __be32 *fw_data; |
1466 | u32 running, blackout = 0; | 1468 | u32 running, blackout = 0; |
@@ -3247,7 +3249,8 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable) | |||
3247 | if (enable) | 3249 | if (enable) |
3248 | WREG32(CP_ME_CNTL, 0); | 3250 | WREG32(CP_ME_CNTL, 0); |
3249 | else { | 3251 | else { |
3250 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); | 3252 | if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) |
3253 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); | ||
3251 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); | 3254 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); |
3252 | WREG32(SCRATCH_UMSK, 0); | 3255 | WREG32(SCRATCH_UMSK, 0); |
3253 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 3256 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
@@ -3508,6 +3511,9 @@ static int si_cp_resume(struct radeon_device *rdev) | |||
3508 | 3511 | ||
3509 | si_enable_gui_idle_interrupt(rdev, true); | 3512 | si_enable_gui_idle_interrupt(rdev, true); |
3510 | 3513 | ||
3514 | if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) | ||
3515 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | ||
3516 | |||
3511 | return 0; | 3517 | return 0; |
3512 | } | 3518 | } |
3513 | 3519 | ||
@@ -3724,6 +3730,106 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
3724 | evergreen_print_gpu_status_regs(rdev); | 3730 | evergreen_print_gpu_status_regs(rdev); |
3725 | } | 3731 | } |
3726 | 3732 | ||
3733 | static void si_set_clk_bypass_mode(struct radeon_device *rdev) | ||
3734 | { | ||
3735 | u32 tmp, i; | ||
3736 | |||
3737 | tmp = RREG32(CG_SPLL_FUNC_CNTL); | ||
3738 | tmp |= SPLL_BYPASS_EN; | ||
3739 | WREG32(CG_SPLL_FUNC_CNTL, tmp); | ||
3740 | |||
3741 | tmp = RREG32(CG_SPLL_FUNC_CNTL_2); | ||
3742 | tmp |= SPLL_CTLREQ_CHG; | ||
3743 | WREG32(CG_SPLL_FUNC_CNTL_2, tmp); | ||
3744 | |||
3745 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
3746 | if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS) | ||
3747 | break; | ||
3748 | udelay(1); | ||
3749 | } | ||
3750 | |||
3751 | tmp = RREG32(CG_SPLL_FUNC_CNTL_2); | ||
3752 | tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE); | ||
3753 | WREG32(CG_SPLL_FUNC_CNTL_2, tmp); | ||
3754 | |||
3755 | tmp = RREG32(MPLL_CNTL_MODE); | ||
3756 | tmp &= ~MPLL_MCLK_SEL; | ||
3757 | WREG32(MPLL_CNTL_MODE, tmp); | ||
3758 | } | ||
3759 | |||
3760 | static void si_spll_powerdown(struct radeon_device *rdev) | ||
3761 | { | ||
3762 | u32 tmp; | ||
3763 | |||
3764 | tmp = RREG32(SPLL_CNTL_MODE); | ||
3765 | tmp |= SPLL_SW_DIR_CONTROL; | ||
3766 | WREG32(SPLL_CNTL_MODE, tmp); | ||
3767 | |||
3768 | tmp = RREG32(CG_SPLL_FUNC_CNTL); | ||
3769 | tmp |= SPLL_RESET; | ||
3770 | WREG32(CG_SPLL_FUNC_CNTL, tmp); | ||
3771 | |||
3772 | tmp = RREG32(CG_SPLL_FUNC_CNTL); | ||
3773 | tmp |= SPLL_SLEEP; | ||
3774 | WREG32(CG_SPLL_FUNC_CNTL, tmp); | ||
3775 | |||
3776 | tmp = RREG32(SPLL_CNTL_MODE); | ||
3777 | tmp &= ~SPLL_SW_DIR_CONTROL; | ||
3778 | WREG32(SPLL_CNTL_MODE, tmp); | ||
3779 | } | ||
3780 | |||
3781 | static void si_gpu_pci_config_reset(struct radeon_device *rdev) | ||
3782 | { | ||
3783 | struct evergreen_mc_save save; | ||
3784 | u32 tmp, i; | ||
3785 | |||
3786 | dev_info(rdev->dev, "GPU pci config reset\n"); | ||
3787 | |||
3788 | /* disable dpm? */ | ||
3789 | |||
3790 | /* disable cg/pg */ | ||
3791 | si_fini_pg(rdev); | ||
3792 | si_fini_cg(rdev); | ||
3793 | |||
3794 | /* Disable CP parsing/prefetching */ | ||
3795 | WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); | ||
3796 | /* dma0 */ | ||
3797 | tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); | ||
3798 | tmp &= ~DMA_RB_ENABLE; | ||
3799 | WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); | ||
3800 | /* dma1 */ | ||
3801 | tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); | ||
3802 | tmp &= ~DMA_RB_ENABLE; | ||
3803 | WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); | ||
3804 | /* XXX other engines? */ | ||
3805 | |||
3806 | /* halt the rlc, disable cp internal ints */ | ||
3807 | si_rlc_stop(rdev); | ||
3808 | |||
3809 | udelay(50); | ||
3810 | |||
3811 | /* disable mem access */ | ||
3812 | evergreen_mc_stop(rdev, &save); | ||
3813 | if (evergreen_mc_wait_for_idle(rdev)) { | ||
3814 | dev_warn(rdev->dev, "Wait for MC idle timed out !\n"); | ||
3815 | } | ||
3816 | |||
3817 | /* set mclk/sclk to bypass */ | ||
3818 | si_set_clk_bypass_mode(rdev); | ||
3819 | /* powerdown spll */ | ||
3820 | si_spll_powerdown(rdev); | ||
3821 | /* disable BM */ | ||
3822 | pci_clear_master(rdev->pdev); | ||
3823 | /* reset */ | ||
3824 | radeon_pci_config_reset(rdev); | ||
3825 | /* wait for asic to come out of reset */ | ||
3826 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
3827 | if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) | ||
3828 | break; | ||
3829 | udelay(1); | ||
3830 | } | ||
3831 | } | ||
3832 | |||
3727 | int si_asic_reset(struct radeon_device *rdev) | 3833 | int si_asic_reset(struct radeon_device *rdev) |
3728 | { | 3834 | { |
3729 | u32 reset_mask; | 3835 | u32 reset_mask; |
@@ -3733,10 +3839,17 @@ int si_asic_reset(struct radeon_device *rdev) | |||
3733 | if (reset_mask) | 3839 | if (reset_mask) |
3734 | r600_set_bios_scratch_engine_hung(rdev, true); | 3840 | r600_set_bios_scratch_engine_hung(rdev, true); |
3735 | 3841 | ||
3842 | /* try soft reset */ | ||
3736 | si_gpu_soft_reset(rdev, reset_mask); | 3843 | si_gpu_soft_reset(rdev, reset_mask); |
3737 | 3844 | ||
3738 | reset_mask = si_gpu_check_soft_reset(rdev); | 3845 | reset_mask = si_gpu_check_soft_reset(rdev); |
3739 | 3846 | ||
3847 | /* try pci config reset */ | ||
3848 | if (reset_mask && radeon_hard_reset) | ||
3849 | si_gpu_pci_config_reset(rdev); | ||
3850 | |||
3851 | reset_mask = si_gpu_check_soft_reset(rdev); | ||
3852 | |||
3740 | if (!reset_mask) | 3853 | if (!reset_mask) |
3741 | r600_set_bios_scratch_engine_hung(rdev, false); | 3854 | r600_set_bios_scratch_engine_hung(rdev, false); |
3742 | 3855 | ||
@@ -5212,8 +5325,8 @@ static void si_enable_hdp_ls(struct radeon_device *rdev, | |||
5212 | WREG32(HDP_MEM_POWER_LS, data); | 5325 | WREG32(HDP_MEM_POWER_LS, data); |
5213 | } | 5326 | } |
5214 | 5327 | ||
5215 | void si_update_cg(struct radeon_device *rdev, | 5328 | static void si_update_cg(struct radeon_device *rdev, |
5216 | u32 block, bool enable) | 5329 | u32 block, bool enable) |
5217 | { | 5330 | { |
5218 | if (block & RADEON_CG_BLOCK_GFX) { | 5331 | if (block & RADEON_CG_BLOCK_GFX) { |
5219 | si_enable_gui_idle_interrupt(rdev, false); | 5332 | si_enable_gui_idle_interrupt(rdev, false); |
@@ -5379,6 +5492,9 @@ static void si_init_pg(struct radeon_device *rdev) | |||
5379 | si_init_ao_cu_mask(rdev); | 5492 | si_init_ao_cu_mask(rdev); |
5380 | if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { | 5493 | if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { |
5381 | si_init_gfx_cgpg(rdev); | 5494 | si_init_gfx_cgpg(rdev); |
5495 | } else { | ||
5496 | WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); | ||
5497 | WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); | ||
5382 | } | 5498 | } |
5383 | si_enable_dma_pg(rdev, true); | 5499 | si_enable_dma_pg(rdev, true); |
5384 | si_enable_gfx_cgpg(rdev, true); | 5500 | si_enable_gfx_cgpg(rdev, true); |
@@ -5566,7 +5682,7 @@ static void si_disable_interrupt_state(struct radeon_device *rdev) | |||
5566 | } | 5682 | } |
5567 | 5683 | ||
5568 | if (!ASIC_IS_NODCE(rdev)) { | 5684 | if (!ASIC_IS_NODCE(rdev)) { |
5569 | WREG32(DACA_AUTODETECT_INT_CONTROL, 0); | 5685 | WREG32(DAC_AUTODETECT_INT_CONTROL, 0); |
5570 | 5686 | ||
5571 | tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; | 5687 | tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; |
5572 | WREG32(DC_HPD1_INT_CONTROL, tmp); | 5688 | WREG32(DC_HPD1_INT_CONTROL, tmp); |
@@ -6222,6 +6338,10 @@ restart_ih: | |||
6222 | break; | 6338 | break; |
6223 | } | 6339 | } |
6224 | break; | 6340 | break; |
6341 | case 124: /* UVD */ | ||
6342 | DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data); | ||
6343 | radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX); | ||
6344 | break; | ||
6225 | case 146: | 6345 | case 146: |
6226 | case 147: | 6346 | case 147: |
6227 | addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); | 6347 | addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); |
@@ -6324,21 +6444,14 @@ static int si_startup(struct radeon_device *rdev) | |||
6324 | 6444 | ||
6325 | si_mc_program(rdev); | 6445 | si_mc_program(rdev); |
6326 | 6446 | ||
6327 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || | 6447 | if (!rdev->pm.dpm_enabled) { |
6328 | !rdev->rlc_fw || !rdev->mc_fw) { | 6448 | r = si_mc_load_microcode(rdev); |
6329 | r = si_init_microcode(rdev); | ||
6330 | if (r) { | 6449 | if (r) { |
6331 | DRM_ERROR("Failed to load firmware!\n"); | 6450 | DRM_ERROR("Failed to load MC firmware!\n"); |
6332 | return r; | 6451 | return r; |
6333 | } | 6452 | } |
6334 | } | 6453 | } |
6335 | 6454 | ||
6336 | r = si_mc_load_microcode(rdev); | ||
6337 | if (r) { | ||
6338 | DRM_ERROR("Failed to load MC firmware!\n"); | ||
6339 | return r; | ||
6340 | } | ||
6341 | |||
6342 | r = si_pcie_gart_enable(rdev); | 6455 | r = si_pcie_gart_enable(rdev); |
6343 | if (r) | 6456 | if (r) |
6344 | return r; | 6457 | return r; |
@@ -6421,37 +6534,30 @@ static int si_startup(struct radeon_device *rdev) | |||
6421 | 6534 | ||
6422 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 6535 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
6423 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, | 6536 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, |
6424 | CP_RB0_RPTR, CP_RB0_WPTR, | ||
6425 | RADEON_CP_PACKET2); | 6537 | RADEON_CP_PACKET2); |
6426 | if (r) | 6538 | if (r) |
6427 | return r; | 6539 | return r; |
6428 | 6540 | ||
6429 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | 6541 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; |
6430 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, | 6542 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, |
6431 | CP_RB1_RPTR, CP_RB1_WPTR, | ||
6432 | RADEON_CP_PACKET2); | 6543 | RADEON_CP_PACKET2); |
6433 | if (r) | 6544 | if (r) |
6434 | return r; | 6545 | return r; |
6435 | 6546 | ||
6436 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | 6547 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; |
6437 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, | 6548 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, |
6438 | CP_RB2_RPTR, CP_RB2_WPTR, | ||
6439 | RADEON_CP_PACKET2); | 6549 | RADEON_CP_PACKET2); |
6440 | if (r) | 6550 | if (r) |
6441 | return r; | 6551 | return r; |
6442 | 6552 | ||
6443 | ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; | 6553 | ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; |
6444 | r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, | 6554 | r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, |
6445 | DMA_RB_RPTR + DMA0_REGISTER_OFFSET, | ||
6446 | DMA_RB_WPTR + DMA0_REGISTER_OFFSET, | ||
6447 | DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); | 6555 | DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); |
6448 | if (r) | 6556 | if (r) |
6449 | return r; | 6557 | return r; |
6450 | 6558 | ||
6451 | ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; | 6559 | ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; |
6452 | r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, | 6560 | r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, |
6453 | DMA_RB_RPTR + DMA1_REGISTER_OFFSET, | ||
6454 | DMA_RB_WPTR + DMA1_REGISTER_OFFSET, | ||
6455 | DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); | 6561 | DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); |
6456 | if (r) | 6562 | if (r) |
6457 | return r; | 6563 | return r; |
@@ -6471,7 +6577,6 @@ static int si_startup(struct radeon_device *rdev) | |||
6471 | ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | 6577 | ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; |
6472 | if (ring->ring_size) { | 6578 | if (ring->ring_size) { |
6473 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, | 6579 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, |
6474 | UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, | ||
6475 | RADEON_CP_PACKET2); | 6580 | RADEON_CP_PACKET2); |
6476 | if (!r) | 6581 | if (!r) |
6477 | r = uvd_v1_0_init(rdev); | 6582 | r = uvd_v1_0_init(rdev); |
@@ -6513,6 +6618,9 @@ int si_resume(struct radeon_device *rdev) | |||
6513 | /* init golden registers */ | 6618 | /* init golden registers */ |
6514 | si_init_golden_registers(rdev); | 6619 | si_init_golden_registers(rdev); |
6515 | 6620 | ||
6621 | if (rdev->pm.pm_method == PM_METHOD_DPM) | ||
6622 | radeon_pm_resume(rdev); | ||
6623 | |||
6516 | rdev->accel_working = true; | 6624 | rdev->accel_working = true; |
6517 | r = si_startup(rdev); | 6625 | r = si_startup(rdev); |
6518 | if (r) { | 6626 | if (r) { |
@@ -6527,6 +6635,7 @@ int si_resume(struct radeon_device *rdev) | |||
6527 | 6635 | ||
6528 | int si_suspend(struct radeon_device *rdev) | 6636 | int si_suspend(struct radeon_device *rdev) |
6529 | { | 6637 | { |
6638 | radeon_pm_suspend(rdev); | ||
6530 | dce6_audio_fini(rdev); | 6639 | dce6_audio_fini(rdev); |
6531 | radeon_vm_manager_fini(rdev); | 6640 | radeon_vm_manager_fini(rdev); |
6532 | si_cp_enable(rdev, false); | 6641 | si_cp_enable(rdev, false); |
@@ -6600,6 +6709,18 @@ int si_init(struct radeon_device *rdev) | |||
6600 | if (r) | 6709 | if (r) |
6601 | return r; | 6710 | return r; |
6602 | 6711 | ||
6712 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || | ||
6713 | !rdev->rlc_fw || !rdev->mc_fw) { | ||
6714 | r = si_init_microcode(rdev); | ||
6715 | if (r) { | ||
6716 | DRM_ERROR("Failed to load firmware!\n"); | ||
6717 | return r; | ||
6718 | } | ||
6719 | } | ||
6720 | |||
6721 | /* Initialize power management */ | ||
6722 | radeon_pm_init(rdev); | ||
6723 | |||
6603 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 6724 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
6604 | ring->ring_obj = NULL; | 6725 | ring->ring_obj = NULL; |
6605 | r600_ring_init(rdev, ring, 1024 * 1024); | 6726 | r600_ring_init(rdev, ring, 1024 * 1024); |
@@ -6666,6 +6787,7 @@ int si_init(struct radeon_device *rdev) | |||
6666 | 6787 | ||
6667 | void si_fini(struct radeon_device *rdev) | 6788 | void si_fini(struct radeon_device *rdev) |
6668 | { | 6789 | { |
6790 | radeon_pm_fini(rdev); | ||
6669 | si_cp_fini(rdev); | 6791 | si_cp_fini(rdev); |
6670 | cayman_dma_fini(rdev); | 6792 | cayman_dma_fini(rdev); |
6671 | si_fini_pg(rdev); | 6793 | si_fini_pg(rdev); |