aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2013-04-09 13:39:21 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-06-26 16:11:50 -0400
commit87167bb16dfdd76b836ed3c19024c4a2d985f993 (patch)
tree5a54a9f4472384090388f7d1980b17df1db4c600
parent9219ed65d34ab016c7263758886781e7b5c33eab (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.c111
-rw-r--r--drivers/gpu/drm/radeon/cikd.h28
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c8
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
5751static 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, &dividers);
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
5779int 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
5791int 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);
560u32 cik_get_xclk(struct radeon_device *rdev); 560u32 cik_get_xclk(struct radeon_device *rdev);
561uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg); 561uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
562void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 562void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
563int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
564int 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
48MODULE_FIRMWARE(FIRMWARE_RV710); 49MODULE_FIRMWARE(FIRMWARE_RV710);
49MODULE_FIRMWARE(FIRMWARE_CYPRESS); 50MODULE_FIRMWARE(FIRMWARE_CYPRESS);
50MODULE_FIRMWARE(FIRMWARE_SUMO); 51MODULE_FIRMWARE(FIRMWARE_SUMO);
51MODULE_FIRMWARE(FIRMWARE_TAHITI); 52MODULE_FIRMWARE(FIRMWARE_TAHITI);
53MODULE_FIRMWARE(FIRMWARE_BONAIRE);
52 54
53static void radeon_uvd_idle_work_handler(struct work_struct *work); 55static 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 }