diff options
author | Christian König <christian.koenig@amd.com> | 2013-04-09 13:39:21 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-26 16:11:50 -0400 |
commit | 87167bb16dfdd76b836ed3c19024c4a2d985f993 (patch) | |
tree | 5a54a9f4472384090388f7d1980b17df1db4c600 | |
parent | 9219ed65d34ab016c7263758886781e7b5c33eab (diff) |
drm/radeon: add UVD support for CIK (v3)
v2: agd5f: fix clock dividers setup for bonaire
v3: agd5f: rebase
Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 111 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/cikd.h | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_uvd.c | 8 |
4 files changed, 149 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4c8407df175b..3e32b145341f 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -1495,6 +1495,9 @@ static void cik_gpu_init(struct radeon_device *rdev) | |||
1495 | WREG32(DMIF_ADDR_CALC, gb_addr_config); | 1495 | WREG32(DMIF_ADDR_CALC, gb_addr_config); |
1496 | WREG32(SDMA0_TILING_CONFIG + SDMA0_REGISTER_OFFSET, gb_addr_config & 0x70); | 1496 | WREG32(SDMA0_TILING_CONFIG + SDMA0_REGISTER_OFFSET, gb_addr_config & 0x70); |
1497 | WREG32(SDMA0_TILING_CONFIG + SDMA1_REGISTER_OFFSET, gb_addr_config & 0x70); | 1497 | WREG32(SDMA0_TILING_CONFIG + SDMA1_REGISTER_OFFSET, gb_addr_config & 0x70); |
1498 | WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config); | ||
1499 | WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config); | ||
1500 | WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config); | ||
1498 | 1501 | ||
1499 | cik_tiling_mode_table_init(rdev); | 1502 | cik_tiling_mode_table_init(rdev); |
1500 | 1503 | ||
@@ -4906,6 +4909,16 @@ static int cik_startup(struct radeon_device *rdev) | |||
4906 | return r; | 4909 | return r; |
4907 | } | 4910 | } |
4908 | 4911 | ||
4912 | r = cik_uvd_resume(rdev); | ||
4913 | if (!r) { | ||
4914 | r = radeon_fence_driver_start_ring(rdev, | ||
4915 | R600_RING_TYPE_UVD_INDEX); | ||
4916 | if (r) | ||
4917 | dev_err(rdev->dev, "UVD fences init error (%d).\n", r); | ||
4918 | } | ||
4919 | if (r) | ||
4920 | rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; | ||
4921 | |||
4909 | /* Enable IRQ */ | 4922 | /* Enable IRQ */ |
4910 | if (!rdev->irq.installed) { | 4923 | if (!rdev->irq.installed) { |
4911 | r = radeon_irq_kms_init(rdev); | 4924 | r = radeon_irq_kms_init(rdev); |
@@ -4952,6 +4965,18 @@ static int cik_startup(struct radeon_device *rdev) | |||
4952 | if (r) | 4965 | if (r) |
4953 | return r; | 4966 | return r; |
4954 | 4967 | ||
4968 | ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | ||
4969 | if (ring->ring_size) { | ||
4970 | r = radeon_ring_init(rdev, ring, ring->ring_size, | ||
4971 | R600_WB_UVD_RPTR_OFFSET, | ||
4972 | UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, | ||
4973 | 0, 0xfffff, RADEON_CP_PACKET2); | ||
4974 | if (!r) | ||
4975 | r = r600_uvd_init(rdev); | ||
4976 | if (r) | ||
4977 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); | ||
4978 | } | ||
4979 | |||
4955 | r = radeon_ib_pool_init(rdev); | 4980 | r = radeon_ib_pool_init(rdev); |
4956 | if (r) { | 4981 | if (r) { |
4957 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | 4982 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
@@ -5009,6 +5034,8 @@ int cik_suspend(struct radeon_device *rdev) | |||
5009 | radeon_vm_manager_fini(rdev); | 5034 | radeon_vm_manager_fini(rdev); |
5010 | cik_cp_enable(rdev, false); | 5035 | cik_cp_enable(rdev, false); |
5011 | cik_sdma_enable(rdev, false); | 5036 | cik_sdma_enable(rdev, false); |
5037 | r600_uvd_rbc_stop(rdev); | ||
5038 | radeon_uvd_suspend(rdev); | ||
5012 | cik_irq_suspend(rdev); | 5039 | cik_irq_suspend(rdev); |
5013 | radeon_wb_disable(rdev); | 5040 | radeon_wb_disable(rdev); |
5014 | cik_pcie_gart_disable(rdev); | 5041 | cik_pcie_gart_disable(rdev); |
@@ -5092,6 +5119,13 @@ int cik_init(struct radeon_device *rdev) | |||
5092 | ring->ring_obj = NULL; | 5119 | ring->ring_obj = NULL; |
5093 | r600_ring_init(rdev, ring, 256 * 1024); | 5120 | r600_ring_init(rdev, ring, 256 * 1024); |
5094 | 5121 | ||
5122 | r = radeon_uvd_init(rdev); | ||
5123 | if (!r) { | ||
5124 | ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | ||
5125 | ring->ring_obj = NULL; | ||
5126 | r600_ring_init(rdev, ring, 4096); | ||
5127 | } | ||
5128 | |||
5095 | rdev->ih.ring_obj = NULL; | 5129 | rdev->ih.ring_obj = NULL; |
5096 | r600_ih_ring_init(rdev, 64 * 1024); | 5130 | r600_ih_ring_init(rdev, 64 * 1024); |
5097 | 5131 | ||
@@ -5146,6 +5180,7 @@ void cik_fini(struct radeon_device *rdev) | |||
5146 | radeon_vm_manager_fini(rdev); | 5180 | radeon_vm_manager_fini(rdev); |
5147 | radeon_ib_pool_fini(rdev); | 5181 | radeon_ib_pool_fini(rdev); |
5148 | radeon_irq_kms_fini(rdev); | 5182 | radeon_irq_kms_fini(rdev); |
5183 | radeon_uvd_fini(rdev); | ||
5149 | cik_pcie_gart_fini(rdev); | 5184 | cik_pcie_gart_fini(rdev); |
5150 | r600_vram_scratch_fini(rdev); | 5185 | r600_vram_scratch_fini(rdev); |
5151 | radeon_gem_fini(rdev); | 5186 | radeon_gem_fini(rdev); |
@@ -5713,3 +5748,79 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev) | |||
5713 | return clock; | 5748 | return clock; |
5714 | } | 5749 | } |
5715 | 5750 | ||
5751 | static int cik_set_uvd_clock(struct radeon_device *rdev, u32 clock, | ||
5752 | u32 cntl_reg, u32 status_reg) | ||
5753 | { | ||
5754 | int r, i; | ||
5755 | struct atom_clock_dividers dividers; | ||
5756 | uint32_t tmp; | ||
5757 | |||
5758 | r = radeon_atom_get_clock_dividers(rdev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, | ||
5759 | clock, false, ÷rs); | ||
5760 | if (r) | ||
5761 | return r; | ||
5762 | |||
5763 | tmp = RREG32_SMC(cntl_reg); | ||
5764 | tmp &= ~(DCLK_DIR_CNTL_EN|DCLK_DIVIDER_MASK); | ||
5765 | tmp |= dividers.post_divider; | ||
5766 | WREG32_SMC(cntl_reg, tmp); | ||
5767 | |||
5768 | for (i = 0; i < 100; i++) { | ||
5769 | if (RREG32_SMC(status_reg) & DCLK_STATUS) | ||
5770 | break; | ||
5771 | mdelay(10); | ||
5772 | } | ||
5773 | if (i == 100) | ||
5774 | return -ETIMEDOUT; | ||
5775 | |||
5776 | return 0; | ||
5777 | } | ||
5778 | |||
5779 | int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | ||
5780 | { | ||
5781 | int r = 0; | ||
5782 | |||
5783 | r = cik_set_uvd_clock(rdev, vclk, CG_VCLK_CNTL, CG_VCLK_STATUS); | ||
5784 | if (r) | ||
5785 | return r; | ||
5786 | |||
5787 | r = cik_set_uvd_clock(rdev, dclk, CG_DCLK_CNTL, CG_DCLK_STATUS); | ||
5788 | return r; | ||
5789 | } | ||
5790 | |||
5791 | int cik_uvd_resume(struct radeon_device *rdev) | ||
5792 | { | ||
5793 | uint64_t addr; | ||
5794 | uint32_t size; | ||
5795 | int r; | ||
5796 | |||
5797 | r = radeon_uvd_resume(rdev); | ||
5798 | if (r) | ||
5799 | return r; | ||
5800 | |||
5801 | /* programm the VCPU memory controller bits 0-27 */ | ||
5802 | addr = rdev->uvd.gpu_addr >> 3; | ||
5803 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; | ||
5804 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); | ||
5805 | WREG32(UVD_VCPU_CACHE_SIZE0, size); | ||
5806 | |||
5807 | addr += size; | ||
5808 | size = RADEON_UVD_STACK_SIZE >> 3; | ||
5809 | WREG32(UVD_VCPU_CACHE_OFFSET1, addr); | ||
5810 | WREG32(UVD_VCPU_CACHE_SIZE1, size); | ||
5811 | |||
5812 | addr += size; | ||
5813 | size = RADEON_UVD_HEAP_SIZE >> 3; | ||
5814 | WREG32(UVD_VCPU_CACHE_OFFSET2, addr); | ||
5815 | WREG32(UVD_VCPU_CACHE_SIZE2, size); | ||
5816 | |||
5817 | /* bits 28-31 */ | ||
5818 | addr = (rdev->uvd.gpu_addr >> 28) & 0xF; | ||
5819 | WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0)); | ||
5820 | |||
5821 | /* bits 32-39 */ | ||
5822 | addr = (rdev->uvd.gpu_addr >> 32) & 0xFF; | ||
5823 | WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31)); | ||
5824 | |||
5825 | return 0; | ||
5826 | } | ||
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index d23809a557a6..79be39e071a9 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h | |||
@@ -1204,4 +1204,32 @@ | |||
1204 | # define SDMA_SRBM_WRITE_EXTRA_BYTE_ENABLE(x) ((x) << 12) | 1204 | # define SDMA_SRBM_WRITE_EXTRA_BYTE_ENABLE(x) ((x) << 12) |
1205 | /* byte mask */ | 1205 | /* byte mask */ |
1206 | 1206 | ||
1207 | /* UVD */ | ||
1208 | |||
1209 | #define UVD_UDEC_ADDR_CONFIG 0xef4c | ||
1210 | #define UVD_UDEC_DB_ADDR_CONFIG 0xef50 | ||
1211 | #define UVD_UDEC_DBW_ADDR_CONFIG 0xef54 | ||
1212 | |||
1213 | #define UVD_LMI_EXT40_ADDR 0xf498 | ||
1214 | #define UVD_LMI_ADDR_EXT 0xf594 | ||
1215 | #define UVD_VCPU_CACHE_OFFSET0 0xf608 | ||
1216 | #define UVD_VCPU_CACHE_SIZE0 0xf60c | ||
1217 | #define UVD_VCPU_CACHE_OFFSET1 0xf610 | ||
1218 | #define UVD_VCPU_CACHE_SIZE1 0xf614 | ||
1219 | #define UVD_VCPU_CACHE_OFFSET2 0xf618 | ||
1220 | #define UVD_VCPU_CACHE_SIZE2 0xf61c | ||
1221 | |||
1222 | #define UVD_RBC_RB_RPTR 0xf690 | ||
1223 | #define UVD_RBC_RB_WPTR 0xf694 | ||
1224 | |||
1225 | /* UVD clocks */ | ||
1226 | |||
1227 | #define CG_DCLK_CNTL 0xC050009C | ||
1228 | # define DCLK_DIVIDER_MASK 0x7f | ||
1229 | # define DCLK_DIR_CNTL_EN (1 << 8) | ||
1230 | #define CG_DCLK_STATUS 0xC05000A0 | ||
1231 | # define DCLK_STATUS (1 << 0) | ||
1232 | #define CG_VCLK_CNTL 0xC05000A4 | ||
1233 | #define CG_VCLK_STATUS 0xC05000A8 | ||
1234 | |||
1207 | #endif | 1235 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 8c19e3646256..340574277f09 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -560,5 +560,7 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev); | |||
560 | u32 cik_get_xclk(struct radeon_device *rdev); | 560 | u32 cik_get_xclk(struct radeon_device *rdev); |
561 | uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg); | 561 | uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg); |
562 | void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 562 | void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
563 | int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); | ||
564 | int cik_uvd_resume(struct radeon_device *rdev); | ||
563 | 565 | ||
564 | #endif | 566 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index cad735dd02c6..fdc77d1eaac8 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c | |||
@@ -44,11 +44,13 @@ | |||
44 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" | 44 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" |
45 | #define FIRMWARE_SUMO "radeon/SUMO_uvd.bin" | 45 | #define FIRMWARE_SUMO "radeon/SUMO_uvd.bin" |
46 | #define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin" | 46 | #define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin" |
47 | #define FIRMWARE_BONAIRE "radeon/BONAIRE_uvd.bin" | ||
47 | 48 | ||
48 | MODULE_FIRMWARE(FIRMWARE_RV710); | 49 | MODULE_FIRMWARE(FIRMWARE_RV710); |
49 | MODULE_FIRMWARE(FIRMWARE_CYPRESS); | 50 | MODULE_FIRMWARE(FIRMWARE_CYPRESS); |
50 | MODULE_FIRMWARE(FIRMWARE_SUMO); | 51 | MODULE_FIRMWARE(FIRMWARE_SUMO); |
51 | MODULE_FIRMWARE(FIRMWARE_TAHITI); | 52 | MODULE_FIRMWARE(FIRMWARE_TAHITI); |
53 | MODULE_FIRMWARE(FIRMWARE_BONAIRE); | ||
52 | 54 | ||
53 | static void radeon_uvd_idle_work_handler(struct work_struct *work); | 55 | static void radeon_uvd_idle_work_handler(struct work_struct *work); |
54 | 56 | ||
@@ -100,6 +102,12 @@ int radeon_uvd_init(struct radeon_device *rdev) | |||
100 | fw_name = FIRMWARE_TAHITI; | 102 | fw_name = FIRMWARE_TAHITI; |
101 | break; | 103 | break; |
102 | 104 | ||
105 | case CHIP_BONAIRE: | ||
106 | case CHIP_KABINI: | ||
107 | case CHIP_KAVERI: | ||
108 | fw_name = FIRMWARE_BONAIRE; | ||
109 | break; | ||
110 | |||
103 | default: | 111 | default: |
104 | return -EINVAL; | 112 | return -EINVAL; |
105 | } | 113 | } |