diff options
author | Christian König <deathsimple@vodafone.de> | 2013-04-08 06:41:29 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-09 10:31:33 -0400 |
commit | f2ba57b5eab8817d86d0f108fdf1878e51dc0a37 (patch) | |
tree | e784f0573069f6341768968fe3d49df6d2c9a534 /drivers/gpu/drm/radeon/rv770.c | |
parent | 4474f3a91f95e3fcc62d97e36f1e8e3392c96ee0 (diff) |
drm/radeon: UVD bringup v8
Just everything needed to decode videos using UVD.
v6: just all the bugfixes and support for R7xx-SI merged in one patch
v7: UVD_CGC_GATE is a write only register, lockup detection fix
v8: split out VRAM fallback changes, remove support for RV770,
add support for HEMLOCK, add buffer sizes checks
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/rv770.c')
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index d4d9be17cfb9..a47e7b903cbc 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -68,6 +68,105 @@ u32 rv770_get_xclk(struct radeon_device *rdev) | |||
68 | return reference_clock; | 68 | return reference_clock; |
69 | } | 69 | } |
70 | 70 | ||
71 | int rv770_uvd_resume(struct radeon_device *rdev) | ||
72 | { | ||
73 | uint64_t addr; | ||
74 | uint32_t chip_id, size; | ||
75 | int r; | ||
76 | |||
77 | r = radeon_uvd_resume(rdev); | ||
78 | if (r) | ||
79 | return r; | ||
80 | |||
81 | /* programm the VCPU memory controller bits 0-27 */ | ||
82 | addr = rdev->uvd.gpu_addr >> 3; | ||
83 | size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; | ||
84 | WREG32(UVD_VCPU_CACHE_OFFSET0, addr); | ||
85 | WREG32(UVD_VCPU_CACHE_SIZE0, size); | ||
86 | |||
87 | addr += size; | ||
88 | size = RADEON_UVD_STACK_SIZE >> 3; | ||
89 | WREG32(UVD_VCPU_CACHE_OFFSET1, addr); | ||
90 | WREG32(UVD_VCPU_CACHE_SIZE1, size); | ||
91 | |||
92 | addr += size; | ||
93 | size = RADEON_UVD_HEAP_SIZE >> 3; | ||
94 | WREG32(UVD_VCPU_CACHE_OFFSET2, addr); | ||
95 | WREG32(UVD_VCPU_CACHE_SIZE2, size); | ||
96 | |||
97 | /* bits 28-31 */ | ||
98 | addr = (rdev->uvd.gpu_addr >> 28) & 0xF; | ||
99 | WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0)); | ||
100 | |||
101 | /* bits 32-39 */ | ||
102 | addr = (rdev->uvd.gpu_addr >> 32) & 0xFF; | ||
103 | WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31)); | ||
104 | |||
105 | /* tell firmware which hardware it is running on */ | ||
106 | switch (rdev->family) { | ||
107 | default: | ||
108 | return -EINVAL; | ||
109 | case CHIP_RV710: | ||
110 | chip_id = 0x01000005; | ||
111 | break; | ||
112 | case CHIP_RV730: | ||
113 | chip_id = 0x01000006; | ||
114 | break; | ||
115 | case CHIP_RV740: | ||
116 | chip_id = 0x01000007; | ||
117 | break; | ||
118 | case CHIP_CYPRESS: | ||
119 | case CHIP_HEMLOCK: | ||
120 | chip_id = 0x01000008; | ||
121 | break; | ||
122 | case CHIP_JUNIPER: | ||
123 | chip_id = 0x01000009; | ||
124 | break; | ||
125 | case CHIP_REDWOOD: | ||
126 | chip_id = 0x0100000a; | ||
127 | break; | ||
128 | case CHIP_CEDAR: | ||
129 | chip_id = 0x0100000b; | ||
130 | break; | ||
131 | case CHIP_SUMO: | ||
132 | chip_id = 0x0100000c; | ||
133 | break; | ||
134 | case CHIP_SUMO2: | ||
135 | chip_id = 0x0100000d; | ||
136 | break; | ||
137 | case CHIP_PALM: | ||
138 | chip_id = 0x0100000e; | ||
139 | break; | ||
140 | case CHIP_CAYMAN: | ||
141 | chip_id = 0x0100000f; | ||
142 | break; | ||
143 | case CHIP_BARTS: | ||
144 | chip_id = 0x01000010; | ||
145 | break; | ||
146 | case CHIP_TURKS: | ||
147 | chip_id = 0x01000011; | ||
148 | break; | ||
149 | case CHIP_CAICOS: | ||
150 | chip_id = 0x01000012; | ||
151 | break; | ||
152 | case CHIP_TAHITI: | ||
153 | chip_id = 0x01000014; | ||
154 | break; | ||
155 | case CHIP_VERDE: | ||
156 | chip_id = 0x01000015; | ||
157 | break; | ||
158 | case CHIP_PITCAIRN: | ||
159 | chip_id = 0x01000016; | ||
160 | break; | ||
161 | case CHIP_ARUBA: | ||
162 | chip_id = 0x01000017; | ||
163 | break; | ||
164 | } | ||
165 | WREG32(UVD_VCPU_CHIP_ID, chip_id); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
71 | u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 170 | u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
72 | { | 171 | { |
73 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 172 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
@@ -1040,6 +1139,17 @@ static int rv770_startup(struct radeon_device *rdev) | |||
1040 | return r; | 1139 | return r; |
1041 | } | 1140 | } |
1042 | 1141 | ||
1142 | r = rv770_uvd_resume(rdev); | ||
1143 | if (!r) { | ||
1144 | r = radeon_fence_driver_start_ring(rdev, | ||
1145 | R600_RING_TYPE_UVD_INDEX); | ||
1146 | if (r) | ||
1147 | dev_err(rdev->dev, "UVD fences init error (%d).\n", r); | ||
1148 | } | ||
1149 | |||
1150 | if (r) | ||
1151 | rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; | ||
1152 | |||
1043 | /* Enable IRQ */ | 1153 | /* Enable IRQ */ |
1044 | r = r600_irq_init(rdev); | 1154 | r = r600_irq_init(rdev); |
1045 | if (r) { | 1155 | if (r) { |
@@ -1074,6 +1184,19 @@ static int rv770_startup(struct radeon_device *rdev) | |||
1074 | if (r) | 1184 | if (r) |
1075 | return r; | 1185 | return r; |
1076 | 1186 | ||
1187 | ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | ||
1188 | if (ring->ring_size) { | ||
1189 | r = radeon_ring_init(rdev, ring, ring->ring_size, | ||
1190 | R600_WB_UVD_RPTR_OFFSET, | ||
1191 | UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, | ||
1192 | 0, 0xfffff, RADEON_CP_PACKET2); | ||
1193 | if (!r) | ||
1194 | r = r600_uvd_init(rdev); | ||
1195 | |||
1196 | if (r) | ||
1197 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); | ||
1198 | } | ||
1199 | |||
1077 | r = radeon_ib_pool_init(rdev); | 1200 | r = radeon_ib_pool_init(rdev); |
1078 | if (r) { | 1201 | if (r) { |
1079 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | 1202 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
@@ -1115,6 +1238,7 @@ int rv770_resume(struct radeon_device *rdev) | |||
1115 | int rv770_suspend(struct radeon_device *rdev) | 1238 | int rv770_suspend(struct radeon_device *rdev) |
1116 | { | 1239 | { |
1117 | r600_audio_fini(rdev); | 1240 | r600_audio_fini(rdev); |
1241 | radeon_uvd_suspend(rdev); | ||
1118 | r700_cp_stop(rdev); | 1242 | r700_cp_stop(rdev); |
1119 | r600_dma_stop(rdev); | 1243 | r600_dma_stop(rdev); |
1120 | r600_irq_suspend(rdev); | 1244 | r600_irq_suspend(rdev); |
@@ -1190,6 +1314,13 @@ int rv770_init(struct radeon_device *rdev) | |||
1190 | rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; | 1314 | rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; |
1191 | r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); | 1315 | r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); |
1192 | 1316 | ||
1317 | r = radeon_uvd_init(rdev); | ||
1318 | if (!r) { | ||
1319 | rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; | ||
1320 | r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], | ||
1321 | 4096); | ||
1322 | } | ||
1323 | |||
1193 | rdev->ih.ring_obj = NULL; | 1324 | rdev->ih.ring_obj = NULL; |
1194 | r600_ih_ring_init(rdev, 64 * 1024); | 1325 | r600_ih_ring_init(rdev, 64 * 1024); |
1195 | 1326 | ||
@@ -1224,6 +1355,7 @@ void rv770_fini(struct radeon_device *rdev) | |||
1224 | radeon_ib_pool_fini(rdev); | 1355 | radeon_ib_pool_fini(rdev); |
1225 | radeon_irq_kms_fini(rdev); | 1356 | radeon_irq_kms_fini(rdev); |
1226 | rv770_pcie_gart_fini(rdev); | 1357 | rv770_pcie_gart_fini(rdev); |
1358 | radeon_uvd_fini(rdev); | ||
1227 | r600_vram_scratch_fini(rdev); | 1359 | r600_vram_scratch_fini(rdev); |
1228 | radeon_gem_fini(rdev); | 1360 | radeon_gem_fini(rdev); |
1229 | radeon_fence_driver_fini(rdev); | 1361 | radeon_fence_driver_fini(rdev); |