Commit | Line | Data |
---|---|---|
8da1170a LL |
1 | /* |
2 | * Copyright 2021 Advanced Micro Devices, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | */ | |
23 | ||
24 | #include <linux/firmware.h> | |
25 | #include "amdgpu.h" | |
26 | #include "amdgpu_vcn.h" | |
27 | #include "amdgpu_pm.h" | |
0b15205c | 28 | #include "amdgpu_cs.h" |
8da1170a LL |
29 | #include "soc15.h" |
30 | #include "soc15d.h" | |
31 | #include "soc15_hw_ip.h" | |
32 | #include "vcn_v2_0.h" | |
aa44beb5 | 33 | #include "mmsch_v4_0.h" |
8da1170a LL |
34 | |
35 | #include "vcn/vcn_4_0_0_offset.h" | |
36 | #include "vcn/vcn_4_0_0_sh_mask.h" | |
37 | #include "ivsrcid/vcn/irqsrcs_vcn_4_0.h" | |
38 | ||
39 | #include <drm/drm_drv.h> | |
40 | ||
41 | #define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL | |
42 | #define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX | |
43 | #define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA | |
44 | #define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX | |
45 | ||
46 | #define VCN_VID_SOC_ADDRESS_2_0 0x1fb00 | |
47 | #define VCN1_VID_SOC_ADDRESS_3_0 0x48300 | |
48 | ||
aa44beb5 JJ |
49 | #define VCN_HARVEST_MMSCH 0 |
50 | ||
0b15205c SJ |
51 | #define RDECODE_MSG_CREATE 0x00000000 |
52 | #define RDECODE_MESSAGE_CREATE 0x00000001 | |
53 | ||
8da1170a LL |
54 | static int amdgpu_ih_clientid_vcns[] = { |
55 | SOC15_IH_CLIENTID_VCN, | |
56 | SOC15_IH_CLIENTID_VCN1 | |
57 | }; | |
58 | ||
aa44beb5 | 59 | static int vcn_v4_0_start_sriov(struct amdgpu_device *adev); |
bb4f196b | 60 | static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev); |
8da1170a LL |
61 | static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev); |
62 | static int vcn_v4_0_set_powergating_state(void *handle, | |
63 | enum amd_powergating_state state); | |
64 | static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, | |
65 | int inst_idx, struct dpg_pause_state *new_state); | |
aa44beb5 | 66 | static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring); |
8da1170a LL |
67 | |
68 | /** | |
69 | * vcn_v4_0_early_init - set function pointers | |
70 | * | |
71 | * @handle: amdgpu_device pointer | |
72 | * | |
73 | * Set ring and irq function pointers | |
74 | */ | |
75 | static int vcn_v4_0_early_init(void *handle) | |
76 | { | |
77 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
78 | ||
aa44beb5 JJ |
79 | if (amdgpu_sriov_vf(adev)) |
80 | adev->vcn.harvest_config = VCN_HARVEST_MMSCH; | |
81 | ||
bb4f196b RD |
82 | /* re-use enc ring as unified ring */ |
83 | adev->vcn.num_enc_rings = 1; | |
8da1170a | 84 | |
bb4f196b | 85 | vcn_v4_0_set_unified_ring_funcs(adev); |
8da1170a LL |
86 | vcn_v4_0_set_irq_funcs(adev); |
87 | ||
88 | return 0; | |
89 | } | |
90 | ||
8da1170a LL |
91 | /** |
92 | * vcn_v4_0_sw_init - sw init for VCN block | |
93 | * | |
94 | * @handle: amdgpu_device pointer | |
95 | * | |
96 | * Load firmware and sw initialization | |
97 | */ | |
98 | static int vcn_v4_0_sw_init(void *handle) | |
99 | { | |
100 | struct amdgpu_ring *ring; | |
8da1170a | 101 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
bb4f196b | 102 | int i, r; |
aa44beb5 | 103 | int vcn_doorbell_index = 0; |
8da1170a LL |
104 | |
105 | r = amdgpu_vcn_sw_init(adev); | |
106 | if (r) | |
107 | return r; | |
108 | ||
bb4f196b | 109 | amdgpu_vcn_setup_ucode(adev); |
8da1170a LL |
110 | |
111 | r = amdgpu_vcn_resume(adev); | |
112 | if (r) | |
113 | return r; | |
114 | ||
aa44beb5 JJ |
115 | if (amdgpu_sriov_vf(adev)) { |
116 | vcn_doorbell_index = adev->doorbell_index.vcn.vcn_ring0_1 - MMSCH_DOORBELL_OFFSET; | |
117 | /* get DWORD offset */ | |
118 | vcn_doorbell_index = vcn_doorbell_index << 1; | |
119 | } | |
120 | ||
8da1170a LL |
121 | for (i = 0; i < adev->vcn.num_vcn_inst; i++) { |
122 | volatile struct amdgpu_vcn4_fw_shared *fw_shared; | |
bb4f196b | 123 | |
8da1170a LL |
124 | if (adev->vcn.harvest_config & (1 << i)) |
125 | continue; | |
bb4f196b RD |
126 | |
127 | atomic_set(&adev->vcn.inst[i].sched_score, 0); | |
128 | ||
129 | /* VCN UNIFIED TRAP */ | |
8da1170a | 130 | r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i], |
bb4f196b | 131 | VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq); |
8da1170a LL |
132 | if (r) |
133 | return r; | |
134 | ||
bb4f196b RD |
135 | ring = &adev->vcn.inst[i].ring_enc[0]; |
136 | ring->use_doorbell = true; | |
aa44beb5 JJ |
137 | if (amdgpu_sriov_vf(adev)) |
138 | ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1; | |
139 | else | |
140 | ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i; | |
8da1170a | 141 | |
bb4f196b | 142 | sprintf(ring->name, "vcn_unified_%d", i); |
8da1170a | 143 | |
bb4f196b | 144 | r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, |
e751e4be | 145 | AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score); |
bb4f196b RD |
146 | if (r) |
147 | return r; | |
8da1170a | 148 | |
bb4f196b RD |
149 | fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; |
150 | fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); | |
151 | fw_shared->sq.is_enabled = 1; | |
8da1170a | 152 | |
aa44beb5 JJ |
153 | if (amdgpu_sriov_vf(adev)) |
154 | fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG); | |
155 | ||
8da1170a LL |
156 | if (amdgpu_vcnfw_log) |
157 | amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); | |
158 | } | |
159 | ||
aa44beb5 JJ |
160 | if (amdgpu_sriov_vf(adev)) { |
161 | r = amdgpu_virt_alloc_mm_table(adev); | |
162 | if (r) | |
163 | return r; | |
164 | } | |
165 | ||
bb4f196b RD |
166 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) |
167 | adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode; | |
168 | ||
8da1170a LL |
169 | return 0; |
170 | } | |
171 | ||
172 | /** | |
173 | * vcn_v4_0_sw_fini - sw fini for VCN block | |
174 | * | |
175 | * @handle: amdgpu_device pointer | |
176 | * | |
177 | * VCN suspend and free up sw allocation | |
178 | */ | |
179 | static int vcn_v4_0_sw_fini(void *handle) | |
180 | { | |
181 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
182 | int i, r, idx; | |
183 | ||
8585732b | 184 | if (drm_dev_enter(adev_to_drm(adev), &idx)) { |
bb4f196b RD |
185 | for (i = 0; i < adev->vcn.num_vcn_inst; i++) { |
186 | volatile struct amdgpu_vcn4_fw_shared *fw_shared; | |
8da1170a | 187 | |
bb4f196b RD |
188 | if (adev->vcn.harvest_config & (1 << i)) |
189 | continue; | |
8da1170a | 190 | |
bb4f196b RD |
191 | fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; |
192 | fw_shared->present_flag_0 = 0; | |
193 | fw_shared->sq.is_enabled = 0; | |
194 | } | |
8da1170a | 195 | |
bb4f196b RD |
196 | drm_dev_exit(idx); |
197 | } | |
8da1170a | 198 | |
aa44beb5 JJ |
199 | if (amdgpu_sriov_vf(adev)) |
200 | amdgpu_virt_free_mm_table(adev); | |
201 | ||
8da1170a LL |
202 | r = amdgpu_vcn_suspend(adev); |
203 | if (r) | |
204 | return r; | |
205 | ||
206 | r = amdgpu_vcn_sw_fini(adev); | |
207 | ||
208 | return r; | |
209 | } | |
210 | ||
211 | /** | |
212 | * vcn_v4_0_hw_init - start and test VCN block | |
213 | * | |
214 | * @handle: amdgpu_device pointer | |
215 | * | |
216 | * Initialize the hardware, boot up the VCPU and do some testing | |
217 | */ | |
218 | static int vcn_v4_0_hw_init(void *handle) | |
219 | { | |
220 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
221 | struct amdgpu_ring *ring; | |
bb4f196b | 222 | int i, r; |
8da1170a | 223 | |
aa44beb5 JJ |
224 | if (amdgpu_sriov_vf(adev)) { |
225 | r = vcn_v4_0_start_sriov(adev); | |
226 | if (r) | |
227 | goto done; | |
bb4f196b | 228 | |
aa44beb5 JJ |
229 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { |
230 | if (adev->vcn.harvest_config & (1 << i)) | |
231 | continue; | |
8da1170a | 232 | |
aa44beb5 JJ |
233 | ring = &adev->vcn.inst[i].ring_enc[0]; |
234 | if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) { | |
235 | ring->sched.ready = false; | |
236 | ring->no_scheduler = true; | |
237 | dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name); | |
238 | } else { | |
239 | ring->wptr = 0; | |
240 | ring->wptr_old = 0; | |
241 | vcn_v4_0_unified_ring_set_wptr(ring); | |
242 | ring->sched.ready = true; | |
243 | } | |
244 | } | |
245 | } else { | |
246 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
247 | if (adev->vcn.harvest_config & (1 << i)) | |
248 | continue; | |
8da1170a | 249 | |
aa44beb5 JJ |
250 | ring = &adev->vcn.inst[i].ring_enc[0]; |
251 | ||
252 | adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, | |
253 | ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i); | |
254 | ||
255 | r = amdgpu_ring_test_helper(ring); | |
256 | if (r) | |
257 | goto done; | |
258 | ||
259 | } | |
8da1170a LL |
260 | } |
261 | ||
262 | done: | |
263 | if (!r) | |
264 | DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", | |
265 | (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode"); | |
266 | ||
267 | return r; | |
268 | } | |
269 | ||
270 | /** | |
271 | * vcn_v4_0_hw_fini - stop the hardware block | |
272 | * | |
273 | * @handle: amdgpu_device pointer | |
274 | * | |
275 | * Stop the VCN block, mark ring as not ready any more | |
276 | */ | |
277 | static int vcn_v4_0_hw_fini(void *handle) | |
278 | { | |
279 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
280 | int i; | |
281 | ||
282 | cancel_delayed_work_sync(&adev->vcn.idle_work); | |
283 | ||
284 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
285 | if (adev->vcn.harvest_config & (1 << i)) | |
286 | continue; | |
aa44beb5 JJ |
287 | if (!amdgpu_sriov_vf(adev)) { |
288 | if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || | |
8da1170a LL |
289 | (adev->vcn.cur_state != AMD_PG_STATE_GATE && |
290 | RREG32_SOC15(VCN, i, regUVD_STATUS))) { | |
291 | vcn_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE); | |
aa44beb5 | 292 | } |
8da1170a | 293 | } |
aa44beb5 | 294 | |
8da1170a LL |
295 | } |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | /** | |
301 | * vcn_v4_0_suspend - suspend VCN block | |
302 | * | |
303 | * @handle: amdgpu_device pointer | |
304 | * | |
305 | * HW fini and suspend VCN block | |
306 | */ | |
307 | static int vcn_v4_0_suspend(void *handle) | |
308 | { | |
309 | int r; | |
310 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
311 | ||
312 | r = vcn_v4_0_hw_fini(adev); | |
313 | if (r) | |
314 | return r; | |
315 | ||
316 | r = amdgpu_vcn_suspend(adev); | |
317 | ||
318 | return r; | |
319 | } | |
320 | ||
321 | /** | |
322 | * vcn_v4_0_resume - resume VCN block | |
323 | * | |
324 | * @handle: amdgpu_device pointer | |
325 | * | |
326 | * Resume firmware and hw init VCN block | |
327 | */ | |
328 | static int vcn_v4_0_resume(void *handle) | |
329 | { | |
330 | int r; | |
331 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
332 | ||
333 | r = amdgpu_vcn_resume(adev); | |
334 | if (r) | |
335 | return r; | |
336 | ||
337 | r = vcn_v4_0_hw_init(adev); | |
338 | ||
339 | return r; | |
340 | } | |
341 | ||
342 | /** | |
343 | * vcn_v4_0_mc_resume - memory controller programming | |
344 | * | |
345 | * @adev: amdgpu_device pointer | |
346 | * @inst: instance number | |
347 | * | |
348 | * Let the VCN memory controller know it's offsets | |
349 | */ | |
350 | static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst) | |
351 | { | |
352 | uint32_t offset, size; | |
353 | const struct common_firmware_header *hdr; | |
354 | ||
355 | hdr = (const struct common_firmware_header *)adev->vcn.fw->data; | |
356 | size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); | |
357 | ||
358 | /* cache window 0: fw */ | |
359 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { | |
360 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, | |
361 | (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo)); | |
362 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, | |
363 | (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi)); | |
364 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0); | |
365 | offset = 0; | |
366 | } else { | |
367 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, | |
368 | lower_32_bits(adev->vcn.inst[inst].gpu_addr)); | |
369 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, | |
370 | upper_32_bits(adev->vcn.inst[inst].gpu_addr)); | |
371 | offset = size; | |
372 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3); | |
373 | } | |
374 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size); | |
375 | ||
376 | /* cache window 1: stack */ | |
377 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW, | |
378 | lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); | |
379 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH, | |
380 | upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); | |
381 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0); | |
382 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE); | |
383 | ||
384 | /* cache window 2: context */ | |
385 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW, | |
386 | lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); | |
387 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH, | |
388 | upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); | |
389 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0); | |
390 | WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE); | |
391 | ||
392 | /* non-cache window */ | |
393 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW, | |
394 | lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); | |
395 | WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH, | |
396 | upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); | |
397 | WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0); | |
398 | WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0, | |
399 | AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared))); | |
400 | } | |
401 | ||
402 | /** | |
403 | * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode | |
404 | * | |
405 | * @adev: amdgpu_device pointer | |
406 | * @inst_idx: instance number index | |
407 | * @indirect: indirectly write sram | |
408 | * | |
409 | * Let the VCN memory controller know it's offsets with dpg mode | |
410 | */ | |
411 | static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) | |
412 | { | |
413 | uint32_t offset, size; | |
414 | const struct common_firmware_header *hdr; | |
415 | hdr = (const struct common_firmware_header *)adev->vcn.fw->data; | |
416 | size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); | |
417 | ||
418 | /* cache window 0: fw */ | |
419 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { | |
420 | if (!indirect) { | |
421 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
422 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), | |
423 | (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo), 0, indirect); | |
424 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
425 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), | |
426 | (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi), 0, indirect); | |
427 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
428 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); | |
429 | } else { | |
430 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
431 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect); | |
432 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
433 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect); | |
434 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
435 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); | |
436 | } | |
437 | offset = 0; | |
438 | } else { | |
439 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
440 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), | |
441 | lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); | |
442 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
443 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), | |
444 | upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); | |
445 | offset = size; | |
446 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
447 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), | |
448 | AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect); | |
8da1170a LL |
449 | } |
450 | ||
451 | if (!indirect) | |
452 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
453 | VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect); | |
454 | else | |
455 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
456 | VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect); | |
457 | ||
458 | /* cache window 1: stack */ | |
459 | if (!indirect) { | |
460 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
461 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), | |
462 | lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); | |
463 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
464 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), | |
465 | upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); | |
466 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
467 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); | |
468 | } else { | |
469 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
470 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect); | |
471 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
472 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect); | |
473 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
474 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); | |
475 | } | |
476 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
477 | VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect); | |
478 | ||
479 | /* cache window 2: context */ | |
480 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
481 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), | |
482 | lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect); | |
483 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
484 | VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), | |
485 | upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect); | |
486 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
487 | VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect); | |
488 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
489 | VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect); | |
490 | ||
491 | /* non-cache window */ | |
492 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
493 | VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW), | |
494 | lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); | |
495 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
496 | VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH), | |
497 | upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); | |
498 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
499 | VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect); | |
500 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
501 | VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0), | |
502 | AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect); | |
503 | ||
504 | /* VCN global tiling registers */ | |
505 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
506 | VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); | |
507 | } | |
508 | ||
509 | /** | |
510 | * vcn_v4_0_disable_static_power_gating - disable VCN static power gating | |
511 | * | |
512 | * @adev: amdgpu_device pointer | |
513 | * @inst: instance number | |
514 | * | |
515 | * Disable static power gating for VCN block | |
516 | */ | |
517 | static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst) | |
518 | { | |
519 | uint32_t data = 0; | |
520 | ||
521 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { | |
522 | data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT | |
523 | | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT | |
524 | | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT | |
525 | | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT | |
526 | | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT | |
527 | | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT | |
528 | | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT | |
529 | | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT | |
530 | | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT | |
531 | | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT | |
532 | | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT | |
533 | | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT | |
534 | | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT | |
535 | | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); | |
536 | ||
537 | WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); | |
538 | SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, | |
539 | UVD_PGFSM_STATUS__UVDM_UVDU_UVDLM_PWR_ON_3_0, 0x3F3FFFFF); | |
540 | } else { | |
541 | uint32_t value; | |
542 | ||
543 | value = (inst) ? 0x2200800 : 0; | |
544 | data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT | |
545 | | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT | |
546 | | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT | |
547 | | 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT | |
548 | | 1 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT | |
549 | | 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT | |
550 | | 1 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT | |
551 | | 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT | |
552 | | 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT | |
553 | | 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT | |
554 | | 1 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT | |
555 | | 1 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT | |
556 | | 1 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT | |
557 | | 1 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); | |
558 | ||
559 | WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); | |
560 | SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, value, 0x3F3FFFFF); | |
561 | } | |
562 | ||
563 | data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS); | |
564 | data &= ~0x103; | |
565 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN) | |
566 | data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON | | |
567 | UVD_POWER_STATUS__UVD_PG_EN_MASK; | |
568 | ||
569 | WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data); | |
570 | ||
571 | return; | |
572 | } | |
573 | ||
574 | /** | |
575 | * vcn_v4_0_enable_static_power_gating - enable VCN static power gating | |
576 | * | |
577 | * @adev: amdgpu_device pointer | |
578 | * @inst: instance number | |
579 | * | |
580 | * Enable static power gating for VCN block | |
581 | */ | |
582 | static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst) | |
583 | { | |
584 | uint32_t data; | |
585 | ||
586 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { | |
587 | /* Before power off, this indicator has to be turned on */ | |
588 | data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS); | |
589 | data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK; | |
590 | data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF; | |
591 | WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data); | |
592 | ||
593 | data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT | |
594 | | 2 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT | |
595 | | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT | |
596 | | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT | |
597 | | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT | |
598 | | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT | |
599 | | 2 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT | |
600 | | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT | |
601 | | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT | |
602 | | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT | |
603 | | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT | |
604 | | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT | |
605 | | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT | |
606 | | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); | |
607 | WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); | |
608 | ||
609 | data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT | |
610 | | 2 << UVD_PGFSM_STATUS__UVDS_PWR_STATUS__SHIFT | |
611 | | 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT | |
612 | | 2 << UVD_PGFSM_STATUS__UVDTC_PWR_STATUS__SHIFT | |
613 | | 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT | |
614 | | 2 << UVD_PGFSM_STATUS__UVDTA_PWR_STATUS__SHIFT | |
615 | | 2 << UVD_PGFSM_STATUS__UVDLM_PWR_STATUS__SHIFT | |
616 | | 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT | |
617 | | 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT | |
618 | | 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT | |
619 | | 2 << UVD_PGFSM_STATUS__UVDAB_PWR_STATUS__SHIFT | |
620 | | 2 << UVD_PGFSM_STATUS__UVDTB_PWR_STATUS__SHIFT | |
621 | | 2 << UVD_PGFSM_STATUS__UVDNA_PWR_STATUS__SHIFT | |
622 | | 2 << UVD_PGFSM_STATUS__UVDNB_PWR_STATUS__SHIFT); | |
623 | SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, data, 0x3F3FFFFF); | |
624 | } | |
625 | ||
626 | return; | |
627 | } | |
628 | ||
629 | /** | |
630 | * vcn_v4_0_disable_clock_gating - disable VCN clock gating | |
631 | * | |
632 | * @adev: amdgpu_device pointer | |
633 | * @inst: instance number | |
634 | * | |
635 | * Disable clock gating for VCN block | |
636 | */ | |
637 | static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst) | |
638 | { | |
639 | uint32_t data; | |
640 | ||
641 | if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) | |
642 | return; | |
643 | ||
644 | /* VCN disable CGC */ | |
645 | data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); | |
646 | data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK; | |
647 | data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; | |
648 | data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; | |
649 | WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); | |
650 | ||
651 | data = RREG32_SOC15(VCN, inst, regUVD_CGC_GATE); | |
652 | data &= ~(UVD_CGC_GATE__SYS_MASK | |
653 | | UVD_CGC_GATE__UDEC_MASK | |
654 | | UVD_CGC_GATE__MPEG2_MASK | |
655 | | UVD_CGC_GATE__REGS_MASK | |
656 | | UVD_CGC_GATE__RBC_MASK | |
657 | | UVD_CGC_GATE__LMI_MC_MASK | |
658 | | UVD_CGC_GATE__LMI_UMC_MASK | |
659 | | UVD_CGC_GATE__IDCT_MASK | |
660 | | UVD_CGC_GATE__MPRD_MASK | |
661 | | UVD_CGC_GATE__MPC_MASK | |
662 | | UVD_CGC_GATE__LBSI_MASK | |
663 | | UVD_CGC_GATE__LRBBM_MASK | |
664 | | UVD_CGC_GATE__UDEC_RE_MASK | |
665 | | UVD_CGC_GATE__UDEC_CM_MASK | |
666 | | UVD_CGC_GATE__UDEC_IT_MASK | |
667 | | UVD_CGC_GATE__UDEC_DB_MASK | |
668 | | UVD_CGC_GATE__UDEC_MP_MASK | |
669 | | UVD_CGC_GATE__WCB_MASK | |
670 | | UVD_CGC_GATE__VCPU_MASK | |
671 | | UVD_CGC_GATE__MMSCH_MASK); | |
672 | ||
673 | WREG32_SOC15(VCN, inst, regUVD_CGC_GATE, data); | |
674 | SOC15_WAIT_ON_RREG(VCN, inst, regUVD_CGC_GATE, 0, 0xFFFFFFFF); | |
675 | ||
676 | data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); | |
677 | data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK | |
678 | | UVD_CGC_CTRL__UDEC_CM_MODE_MASK | |
679 | | UVD_CGC_CTRL__UDEC_IT_MODE_MASK | |
680 | | UVD_CGC_CTRL__UDEC_DB_MODE_MASK | |
681 | | UVD_CGC_CTRL__UDEC_MP_MODE_MASK | |
682 | | UVD_CGC_CTRL__SYS_MODE_MASK | |
683 | | UVD_CGC_CTRL__UDEC_MODE_MASK | |
684 | | UVD_CGC_CTRL__MPEG2_MODE_MASK | |
685 | | UVD_CGC_CTRL__REGS_MODE_MASK | |
686 | | UVD_CGC_CTRL__RBC_MODE_MASK | |
687 | | UVD_CGC_CTRL__LMI_MC_MODE_MASK | |
688 | | UVD_CGC_CTRL__LMI_UMC_MODE_MASK | |
689 | | UVD_CGC_CTRL__IDCT_MODE_MASK | |
690 | | UVD_CGC_CTRL__MPRD_MODE_MASK | |
691 | | UVD_CGC_CTRL__MPC_MODE_MASK | |
692 | | UVD_CGC_CTRL__LBSI_MODE_MASK | |
693 | | UVD_CGC_CTRL__LRBBM_MODE_MASK | |
694 | | UVD_CGC_CTRL__WCB_MODE_MASK | |
695 | | UVD_CGC_CTRL__VCPU_MODE_MASK | |
696 | | UVD_CGC_CTRL__MMSCH_MODE_MASK); | |
697 | WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); | |
698 | ||
699 | data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE); | |
700 | data |= (UVD_SUVD_CGC_GATE__SRE_MASK | |
701 | | UVD_SUVD_CGC_GATE__SIT_MASK | |
702 | | UVD_SUVD_CGC_GATE__SMP_MASK | |
703 | | UVD_SUVD_CGC_GATE__SCM_MASK | |
704 | | UVD_SUVD_CGC_GATE__SDB_MASK | |
705 | | UVD_SUVD_CGC_GATE__SRE_H264_MASK | |
8da1170a LL |
706 | | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |
707 | | UVD_SUVD_CGC_GATE__SIT_H264_MASK | |
708 | | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK | |
709 | | UVD_SUVD_CGC_GATE__SCM_H264_MASK | |
710 | | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK | |
711 | | UVD_SUVD_CGC_GATE__SDB_H264_MASK | |
712 | | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK | |
713 | | UVD_SUVD_CGC_GATE__SCLR_MASK | |
714 | | UVD_SUVD_CGC_GATE__UVD_SC_MASK | |
715 | | UVD_SUVD_CGC_GATE__ENT_MASK | |
716 | | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK | |
717 | | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK | |
718 | | UVD_SUVD_CGC_GATE__SITE_MASK | |
719 | | UVD_SUVD_CGC_GATE__SRE_VP9_MASK | |
720 | | UVD_SUVD_CGC_GATE__SCM_VP9_MASK | |
721 | | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK | |
722 | | UVD_SUVD_CGC_GATE__SDB_VP9_MASK | |
723 | | UVD_SUVD_CGC_GATE__IME_HEVC_MASK); | |
724 | WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE, data); | |
725 | ||
726 | data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL); | |
727 | data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK | |
728 | | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK | |
729 | | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK | |
730 | | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK | |
731 | | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK | |
732 | | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK | |
733 | | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK | |
734 | | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK | |
735 | | UVD_SUVD_CGC_CTRL__IME_MODE_MASK | |
736 | | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK); | |
737 | WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data); | |
738 | } | |
739 | ||
740 | /** | |
741 | * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode | |
742 | * | |
743 | * @adev: amdgpu_device pointer | |
744 | * @sram_sel: sram select | |
745 | * @inst_idx: instance number index | |
746 | * @indirect: indirectly write sram | |
747 | * | |
748 | * Disable clock gating for VCN block with dpg mode | |
749 | */ | |
750 | static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, | |
751 | int inst_idx, uint8_t indirect) | |
752 | { | |
753 | uint32_t reg_data = 0; | |
754 | ||
755 | if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) | |
756 | return; | |
757 | ||
758 | /* enable sw clock gating control */ | |
759 | reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; | |
760 | reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; | |
761 | reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; | |
762 | reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK | | |
763 | UVD_CGC_CTRL__UDEC_CM_MODE_MASK | | |
764 | UVD_CGC_CTRL__UDEC_IT_MODE_MASK | | |
765 | UVD_CGC_CTRL__UDEC_DB_MODE_MASK | | |
766 | UVD_CGC_CTRL__UDEC_MP_MODE_MASK | | |
767 | UVD_CGC_CTRL__SYS_MODE_MASK | | |
768 | UVD_CGC_CTRL__UDEC_MODE_MASK | | |
769 | UVD_CGC_CTRL__MPEG2_MODE_MASK | | |
770 | UVD_CGC_CTRL__REGS_MODE_MASK | | |
771 | UVD_CGC_CTRL__RBC_MODE_MASK | | |
772 | UVD_CGC_CTRL__LMI_MC_MODE_MASK | | |
773 | UVD_CGC_CTRL__LMI_UMC_MODE_MASK | | |
774 | UVD_CGC_CTRL__IDCT_MODE_MASK | | |
775 | UVD_CGC_CTRL__MPRD_MODE_MASK | | |
776 | UVD_CGC_CTRL__MPC_MODE_MASK | | |
777 | UVD_CGC_CTRL__LBSI_MODE_MASK | | |
778 | UVD_CGC_CTRL__LRBBM_MODE_MASK | | |
779 | UVD_CGC_CTRL__WCB_MODE_MASK | | |
780 | UVD_CGC_CTRL__VCPU_MODE_MASK); | |
781 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
782 | VCN, inst_idx, regUVD_CGC_CTRL), reg_data, sram_sel, indirect); | |
783 | ||
784 | /* turn off clock gating */ | |
785 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
786 | VCN, inst_idx, regUVD_CGC_GATE), 0, sram_sel, indirect); | |
787 | ||
788 | /* turn on SUVD clock gating */ | |
789 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
790 | VCN, inst_idx, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect); | |
791 | ||
792 | /* turn on sw mode in UVD_SUVD_CGC_CTRL */ | |
793 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
794 | VCN, inst_idx, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect); | |
795 | } | |
796 | ||
797 | /** | |
798 | * vcn_v4_0_enable_clock_gating - enable VCN clock gating | |
799 | * | |
800 | * @adev: amdgpu_device pointer | |
801 | * @inst: instance number | |
802 | * | |
803 | * Enable clock gating for VCN block | |
804 | */ | |
805 | static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst) | |
806 | { | |
807 | uint32_t data; | |
808 | ||
809 | if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) | |
810 | return; | |
811 | ||
812 | /* enable VCN CGC */ | |
813 | data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); | |
814 | data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; | |
815 | data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; | |
816 | data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; | |
817 | WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); | |
818 | ||
819 | data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); | |
820 | data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK | |
821 | | UVD_CGC_CTRL__UDEC_CM_MODE_MASK | |
822 | | UVD_CGC_CTRL__UDEC_IT_MODE_MASK | |
823 | | UVD_CGC_CTRL__UDEC_DB_MODE_MASK | |
824 | | UVD_CGC_CTRL__UDEC_MP_MODE_MASK | |
825 | | UVD_CGC_CTRL__SYS_MODE_MASK | |
826 | | UVD_CGC_CTRL__UDEC_MODE_MASK | |
827 | | UVD_CGC_CTRL__MPEG2_MODE_MASK | |
828 | | UVD_CGC_CTRL__REGS_MODE_MASK | |
829 | | UVD_CGC_CTRL__RBC_MODE_MASK | |
830 | | UVD_CGC_CTRL__LMI_MC_MODE_MASK | |
831 | | UVD_CGC_CTRL__LMI_UMC_MODE_MASK | |
832 | | UVD_CGC_CTRL__IDCT_MODE_MASK | |
833 | | UVD_CGC_CTRL__MPRD_MODE_MASK | |
834 | | UVD_CGC_CTRL__MPC_MODE_MASK | |
835 | | UVD_CGC_CTRL__LBSI_MODE_MASK | |
836 | | UVD_CGC_CTRL__LRBBM_MODE_MASK | |
837 | | UVD_CGC_CTRL__WCB_MODE_MASK | |
838 | | UVD_CGC_CTRL__VCPU_MODE_MASK | |
839 | | UVD_CGC_CTRL__MMSCH_MODE_MASK); | |
840 | WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); | |
841 | ||
842 | data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL); | |
843 | data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK | |
844 | | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK | |
845 | | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK | |
846 | | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK | |
847 | | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK | |
848 | | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK | |
849 | | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK | |
850 | | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK | |
851 | | UVD_SUVD_CGC_CTRL__IME_MODE_MASK | |
852 | | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK); | |
853 | WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data); | |
854 | ||
855 | return; | |
856 | } | |
857 | ||
858 | /** | |
859 | * vcn_v4_0_start_dpg_mode - VCN start with dpg mode | |
860 | * | |
861 | * @adev: amdgpu_device pointer | |
862 | * @inst_idx: instance number index | |
863 | * @indirect: indirectly write sram | |
864 | * | |
865 | * Start VCN block with dpg mode | |
866 | */ | |
867 | static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) | |
868 | { | |
869 | volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; | |
870 | struct amdgpu_ring *ring; | |
871 | uint32_t tmp; | |
8da1170a LL |
872 | |
873 | /* disable register anti-hang mechanism */ | |
874 | WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1, | |
875 | ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); | |
876 | /* enable dynamic power gating mode */ | |
877 | tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS); | |
878 | tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK; | |
879 | tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK; | |
880 | WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp); | |
881 | ||
882 | if (indirect) | |
883 | adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; | |
884 | ||
885 | /* enable clock gating */ | |
886 | vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); | |
887 | ||
888 | /* enable VCPU clock */ | |
889 | tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); | |
890 | tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK; | |
891 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
892 | VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect); | |
893 | ||
894 | /* disable master interupt */ | |
895 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
896 | VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect); | |
897 | ||
898 | /* setup regUVD_LMI_CTRL */ | |
899 | tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | | |
900 | UVD_LMI_CTRL__REQ_MODE_MASK | | |
901 | UVD_LMI_CTRL__CRC_RESET_MASK | | |
902 | UVD_LMI_CTRL__MASK_MC_URGENT_MASK | | |
903 | UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | | |
904 | UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK | | |
905 | (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) | | |
906 | 0x00100000L); | |
907 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
908 | VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect); | |
909 | ||
910 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
911 | VCN, inst_idx, regUVD_MPC_CNTL), | |
912 | 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect); | |
913 | ||
914 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
915 | VCN, inst_idx, regUVD_MPC_SET_MUXA0), | |
916 | ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | | |
917 | (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | | |
918 | (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | | |
919 | (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect); | |
920 | ||
921 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
922 | VCN, inst_idx, regUVD_MPC_SET_MUXB0), | |
923 | ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | | |
924 | (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | | |
925 | (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | | |
926 | (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect); | |
927 | ||
928 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
929 | VCN, inst_idx, regUVD_MPC_SET_MUX), | |
930 | ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | | |
931 | (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | | |
932 | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); | |
933 | ||
934 | vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect); | |
935 | ||
936 | tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); | |
937 | tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; | |
938 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
939 | VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect); | |
940 | ||
941 | /* enable LMI MC and UMC channels */ | |
942 | tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT; | |
943 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
944 | VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect); | |
945 | ||
946 | /* enable master interrupt */ | |
947 | WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( | |
948 | VCN, inst_idx, regUVD_MASTINT_EN), | |
949 | UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect); | |
950 | ||
951 | ||
952 | if (indirect) | |
953 | psp_update_vcn_sram(adev, inst_idx, adev->vcn.inst[inst_idx].dpg_sram_gpu_addr, | |
954 | (uint32_t)((uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_curr_addr - | |
955 | (uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr)); | |
956 | ||
bb4f196b | 957 | ring = &adev->vcn.inst[inst_idx].ring_enc[0]; |
8da1170a | 958 | |
bb4f196b RD |
959 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr); |
960 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); | |
961 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4); | |
8da1170a | 962 | |
8da1170a | 963 | tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE); |
bb4f196b | 964 | tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); |
8da1170a | 965 | WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp); |
bb4f196b RD |
966 | fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; |
967 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0); | |
968 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0); | |
8da1170a | 969 | |
e751e4be | 970 | tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR); |
bb4f196b RD |
971 | WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp); |
972 | ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR); | |
8da1170a LL |
973 | |
974 | tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE); | |
bb4f196b | 975 | tmp |= VCN_RB_ENABLE__RB1_EN_MASK; |
8da1170a | 976 | WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp); |
bb4f196b | 977 | fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); |
8da1170a | 978 | |
bb4f196b RD |
979 | WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL, |
980 | ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | | |
981 | VCN_RB1_DB_CTRL__EN_MASK); | |
8da1170a | 982 | |
8da1170a LL |
983 | return 0; |
984 | } | |
985 | ||
986 | ||
987 | /** | |
988 | * vcn_v4_0_start - VCN start | |
989 | * | |
990 | * @adev: amdgpu_device pointer | |
991 | * | |
992 | * Start VCN block | |
993 | */ | |
994 | static int vcn_v4_0_start(struct amdgpu_device *adev) | |
995 | { | |
996 | volatile struct amdgpu_vcn4_fw_shared *fw_shared; | |
997 | struct amdgpu_ring *ring; | |
998 | uint32_t tmp; | |
999 | int i, j, k, r; | |
1000 | ||
1001 | if (adev->pm.dpm_enabled) | |
1002 | amdgpu_dpm_enable_uvd(adev, true); | |
1003 | ||
1004 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
bb4f196b RD |
1005 | fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; |
1006 | ||
8da1170a LL |
1007 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { |
1008 | r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); | |
1009 | continue; | |
1010 | } | |
1011 | ||
1012 | /* disable VCN power gating */ | |
1013 | vcn_v4_0_disable_static_power_gating(adev, i); | |
1014 | ||
1015 | /* set VCN status busy */ | |
1016 | tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; | |
1017 | WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); | |
1018 | ||
1019 | /*SW clock gating */ | |
1020 | vcn_v4_0_disable_clock_gating(adev, i); | |
1021 | ||
1022 | /* enable VCPU clock */ | |
1023 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), | |
bb4f196b | 1024 | UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); |
8da1170a LL |
1025 | |
1026 | /* disable master interrupt */ | |
1027 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, | |
bb4f196b | 1028 | ~UVD_MASTINT_EN__VCPU_EN_MASK); |
8da1170a LL |
1029 | |
1030 | /* enable LMI MC and UMC channels */ | |
1031 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, | |
bb4f196b | 1032 | ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); |
8da1170a LL |
1033 | |
1034 | tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); | |
1035 | tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; | |
1036 | tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; | |
1037 | WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); | |
1038 | ||
1039 | /* setup regUVD_LMI_CTRL */ | |
1040 | tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); | |
1041 | WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | | |
bb4f196b RD |
1042 | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | |
1043 | UVD_LMI_CTRL__MASK_MC_URGENT_MASK | | |
1044 | UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | | |
1045 | UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); | |
8da1170a LL |
1046 | |
1047 | /* setup regUVD_MPC_CNTL */ | |
1048 | tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); | |
1049 | tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; | |
1050 | tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; | |
1051 | WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); | |
1052 | ||
1053 | /* setup UVD_MPC_SET_MUXA0 */ | |
1054 | WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, | |
bb4f196b RD |
1055 | ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | |
1056 | (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | | |
1057 | (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | | |
1058 | (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); | |
8da1170a LL |
1059 | |
1060 | /* setup UVD_MPC_SET_MUXB0 */ | |
1061 | WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, | |
bb4f196b RD |
1062 | ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | |
1063 | (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | | |
1064 | (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | | |
1065 | (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); | |
8da1170a LL |
1066 | |
1067 | /* setup UVD_MPC_SET_MUX */ | |
1068 | WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, | |
bb4f196b RD |
1069 | ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | |
1070 | (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | | |
1071 | (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); | |
8da1170a LL |
1072 | |
1073 | vcn_v4_0_mc_resume(adev, i); | |
1074 | ||
1075 | /* VCN global tiling registers */ | |
1076 | WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, | |
bb4f196b | 1077 | adev->gfx.config.gb_addr_config); |
8da1170a LL |
1078 | |
1079 | /* unblock VCPU register access */ | |
1080 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, | |
bb4f196b | 1081 | ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); |
8da1170a LL |
1082 | |
1083 | /* release VCPU reset to boot */ | |
1084 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, | |
bb4f196b | 1085 | ~UVD_VCPU_CNTL__BLK_RST_MASK); |
8da1170a LL |
1086 | |
1087 | for (j = 0; j < 10; ++j) { | |
1088 | uint32_t status; | |
1089 | ||
1090 | for (k = 0; k < 100; ++k) { | |
1091 | status = RREG32_SOC15(VCN, i, regUVD_STATUS); | |
1092 | if (status & 2) | |
1093 | break; | |
1094 | mdelay(10); | |
1095 | if (amdgpu_emu_mode==1) | |
1096 | msleep(1); | |
1097 | } | |
1098 | ||
1099 | if (amdgpu_emu_mode==1) { | |
736f7308 | 1100 | r = -1; |
8da1170a LL |
1101 | if (status & 2) { |
1102 | r = 0; | |
1103 | break; | |
1104 | } | |
1105 | } else { | |
1106 | r = 0; | |
1107 | if (status & 2) | |
1108 | break; | |
1109 | ||
bb4f196b RD |
1110 | dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); |
1111 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), | |
e751e4be RD |
1112 | UVD_VCPU_CNTL__BLK_RST_MASK, |
1113 | ~UVD_VCPU_CNTL__BLK_RST_MASK); | |
8da1170a LL |
1114 | mdelay(10); |
1115 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, | |
bb4f196b | 1116 | ~UVD_VCPU_CNTL__BLK_RST_MASK); |
8da1170a LL |
1117 | |
1118 | mdelay(10); | |
1119 | r = -1; | |
1120 | } | |
1121 | } | |
1122 | ||
1123 | if (r) { | |
bb4f196b | 1124 | dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); |
8da1170a LL |
1125 | return r; |
1126 | } | |
1127 | ||
1128 | /* enable master interrupt */ | |
1129 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), | |
bb4f196b RD |
1130 | UVD_MASTINT_EN__VCPU_EN_MASK, |
1131 | ~UVD_MASTINT_EN__VCPU_EN_MASK); | |
8da1170a LL |
1132 | |
1133 | /* clear the busy bit of VCN_STATUS */ | |
1134 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, | |
bb4f196b | 1135 | ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); |
8da1170a | 1136 | |
bb4f196b RD |
1137 | ring = &adev->vcn.inst[i].ring_enc[0]; |
1138 | WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, | |
1139 | ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | | |
1140 | VCN_RB1_DB_CTRL__EN_MASK); | |
8da1170a | 1141 | |
bb4f196b RD |
1142 | WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); |
1143 | WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); | |
1144 | WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); | |
8da1170a | 1145 | |
bb4f196b RD |
1146 | tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); |
1147 | tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); | |
1148 | WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); | |
1149 | fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; | |
1150 | WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); | |
1151 | WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); | |
8da1170a | 1152 | |
8da1170a LL |
1153 | tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); |
1154 | WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); | |
1155 | ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); | |
bb4f196b RD |
1156 | |
1157 | tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); | |
1158 | tmp |= VCN_RB_ENABLE__RB1_EN_MASK; | |
1159 | WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); | |
1160 | fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); | |
8da1170a LL |
1161 | } |
1162 | ||
1163 | return 0; | |
1164 | } | |
1165 | ||
aa44beb5 JJ |
1166 | static int vcn_v4_0_start_sriov(struct amdgpu_device *adev) |
1167 | { | |
1168 | int i; | |
1169 | struct amdgpu_ring *ring_enc; | |
1170 | uint64_t cache_addr; | |
1171 | uint64_t rb_enc_addr; | |
1172 | uint64_t ctx_addr; | |
1173 | uint32_t param, resp, expected; | |
1174 | uint32_t offset, cache_size; | |
1175 | uint32_t tmp, timeout; | |
1176 | ||
1177 | struct amdgpu_mm_table *table = &adev->virt.mm_table; | |
1178 | uint32_t *table_loc; | |
1179 | uint32_t table_size; | |
1180 | uint32_t size, size_dw; | |
1181 | uint32_t init_status; | |
1182 | uint32_t enabled_vcn; | |
1183 | ||
1184 | struct mmsch_v4_0_cmd_direct_write | |
1185 | direct_wt = { {0} }; | |
1186 | struct mmsch_v4_0_cmd_direct_read_modify_write | |
1187 | direct_rd_mod_wt = { {0} }; | |
1188 | struct mmsch_v4_0_cmd_end end = { {0} }; | |
1189 | struct mmsch_v4_0_init_header header; | |
1190 | ||
1191 | volatile struct amdgpu_vcn4_fw_shared *fw_shared; | |
1192 | volatile struct amdgpu_fw_shared_rb_setup *rb_setup; | |
1193 | ||
1194 | direct_wt.cmd_header.command_type = | |
1195 | MMSCH_COMMAND__DIRECT_REG_WRITE; | |
1196 | direct_rd_mod_wt.cmd_header.command_type = | |
1197 | MMSCH_COMMAND__DIRECT_REG_READ_MODIFY_WRITE; | |
1198 | end.cmd_header.command_type = | |
1199 | MMSCH_COMMAND__END; | |
1200 | ||
1201 | header.version = MMSCH_VERSION; | |
1202 | header.total_size = sizeof(struct mmsch_v4_0_init_header) >> 2; | |
1203 | for (i = 0; i < AMDGPU_MAX_VCN_INSTANCES; i++) { | |
1204 | header.inst[i].init_status = 0; | |
1205 | header.inst[i].table_offset = 0; | |
1206 | header.inst[i].table_size = 0; | |
1207 | } | |
1208 | ||
1209 | table_loc = (uint32_t *)table->cpu_addr; | |
1210 | table_loc += header.total_size; | |
1211 | for (i = 0; i < adev->vcn.num_vcn_inst; i++) { | |
1212 | if (adev->vcn.harvest_config & (1 << i)) | |
1213 | continue; | |
1214 | ||
1215 | table_size = 0; | |
1216 | ||
1217 | MMSCH_V4_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCN, i, | |
1218 | regUVD_STATUS), | |
1219 | ~UVD_STATUS__UVD_BUSY, UVD_STATUS__UVD_BUSY); | |
1220 | ||
1221 | cache_size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4); | |
1222 | ||
1223 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { | |
1224 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1225 | regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), | |
1226 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo); | |
1227 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1228 | regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), | |
1229 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi); | |
1230 | offset = 0; | |
1231 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1232 | regUVD_VCPU_CACHE_OFFSET0), | |
1233 | 0); | |
1234 | } else { | |
1235 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1236 | regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), | |
1237 | lower_32_bits(adev->vcn.inst[i].gpu_addr)); | |
1238 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1239 | regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), | |
1240 | upper_32_bits(adev->vcn.inst[i].gpu_addr)); | |
1241 | offset = cache_size; | |
1242 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1243 | regUVD_VCPU_CACHE_OFFSET0), | |
1244 | AMDGPU_UVD_FIRMWARE_OFFSET >> 3); | |
1245 | } | |
1246 | ||
1247 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1248 | regUVD_VCPU_CACHE_SIZE0), | |
1249 | cache_size); | |
1250 | ||
1251 | cache_addr = adev->vcn.inst[i].gpu_addr + offset; | |
1252 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1253 | regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), | |
1254 | lower_32_bits(cache_addr)); | |
1255 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1256 | regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), | |
1257 | upper_32_bits(cache_addr)); | |
1258 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1259 | regUVD_VCPU_CACHE_OFFSET1), | |
1260 | 0); | |
1261 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1262 | regUVD_VCPU_CACHE_SIZE1), | |
1263 | AMDGPU_VCN_STACK_SIZE); | |
1264 | ||
1265 | cache_addr = adev->vcn.inst[i].gpu_addr + offset + | |
1266 | AMDGPU_VCN_STACK_SIZE; | |
1267 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1268 | regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), | |
1269 | lower_32_bits(cache_addr)); | |
1270 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1271 | regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), | |
1272 | upper_32_bits(cache_addr)); | |
1273 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1274 | regUVD_VCPU_CACHE_OFFSET2), | |
1275 | 0); | |
1276 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1277 | regUVD_VCPU_CACHE_SIZE2), | |
1278 | AMDGPU_VCN_CONTEXT_SIZE); | |
1279 | ||
1280 | fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; | |
1281 | rb_setup = &fw_shared->rb_setup; | |
1282 | ||
1283 | ring_enc = &adev->vcn.inst[i].ring_enc[0]; | |
1284 | ring_enc->wptr = 0; | |
1285 | rb_enc_addr = ring_enc->gpu_addr; | |
1286 | ||
1287 | rb_setup->is_rb_enabled_flags |= RB_ENABLED; | |
1288 | rb_setup->rb_addr_lo = lower_32_bits(rb_enc_addr); | |
1289 | rb_setup->rb_addr_hi = upper_32_bits(rb_enc_addr); | |
1290 | rb_setup->rb_size = ring_enc->ring_size / 4; | |
1291 | fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG); | |
1292 | ||
1293 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1294 | regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW), | |
1295 | lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr)); | |
1296 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1297 | regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH), | |
1298 | upper_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr)); | |
1299 | MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i, | |
1300 | regUVD_VCPU_NONCACHE_SIZE0), | |
1301 | AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared))); | |
1302 | ||
1303 | /* add end packet */ | |
1304 | MMSCH_V4_0_INSERT_END(); | |
1305 | ||
1306 | /* refine header */ | |
1307 | header.inst[i].init_status = 0; | |
1308 | header.inst[i].table_offset = header.total_size; | |
1309 | header.inst[i].table_size = table_size; | |
1310 | header.total_size += table_size; | |
1311 | } | |
1312 | ||
1313 | /* Update init table header in memory */ | |
1314 | size = sizeof(struct mmsch_v4_0_init_header); | |
1315 | table_loc = (uint32_t *)table->cpu_addr; | |
1316 | memcpy((void *)table_loc, &header, size); | |
1317 | ||
1318 | /* message MMSCH (in VCN[0]) to initialize this client | |
1319 | * 1, write to mmsch_vf_ctx_addr_lo/hi register with GPU mc addr | |
1320 | * of memory descriptor location | |
1321 | */ | |
1322 | ctx_addr = table->gpu_addr; | |
1323 | WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_LO, lower_32_bits(ctx_addr)); | |
1324 | WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_HI, upper_32_bits(ctx_addr)); | |
1325 | ||
1326 | /* 2, update vmid of descriptor */ | |
1327 | tmp = RREG32_SOC15(VCN, 0, regMMSCH_VF_VMID); | |
1328 | tmp &= ~MMSCH_VF_VMID__VF_CTX_VMID_MASK; | |
1329 | /* use domain0 for MM scheduler */ | |
1330 | tmp |= (0 << MMSCH_VF_VMID__VF_CTX_VMID__SHIFT); | |
1331 | WREG32_SOC15(VCN, 0, regMMSCH_VF_VMID, tmp); | |
1332 | ||
1333 | /* 3, notify mmsch about the size of this descriptor */ | |
1334 | size = header.total_size; | |
1335 | WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE, size); | |
1336 | ||
1337 | /* 4, set resp to zero */ | |
1338 | WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP, 0); | |
1339 | ||
1340 | /* 5, kick off the initialization and wait until | |
1341 | * MMSCH_VF_MAILBOX_RESP becomes non-zero | |
1342 | */ | |
1343 | param = 0x00000001; | |
1344 | WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_HOST, param); | |
1345 | tmp = 0; | |
1346 | timeout = 1000; | |
1347 | resp = 0; | |
1348 | expected = MMSCH_VF_MAILBOX_RESP__OK; | |
1349 | while (resp != expected) { | |
1350 | resp = RREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP); | |
1351 | if (resp != 0) | |
1352 | break; | |
1353 | ||
1354 | udelay(10); | |
1355 | tmp = tmp + 10; | |
1356 | if (tmp >= timeout) { | |
1357 | DRM_ERROR("failed to init MMSCH. TIME-OUT after %d usec"\ | |
1358 | " waiting for regMMSCH_VF_MAILBOX_RESP "\ | |
1359 | "(expected=0x%08x, readback=0x%08x)\n", | |
1360 | tmp, expected, resp); | |
1361 | return -EBUSY; | |
1362 | } | |
1363 | } | |
1364 | enabled_vcn = amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, 0) ? 1 : 0; | |
1365 | init_status = ((struct mmsch_v4_0_init_header *)(table_loc))->inst[enabled_vcn].init_status; | |
1366 | if (resp != expected && resp != MMSCH_VF_MAILBOX_RESP__INCOMPLETE | |
1367 | && init_status != MMSCH_VF_ENGINE_STATUS__PASS) | |
1368 | DRM_ERROR("MMSCH init status is incorrect! readback=0x%08x, header init "\ | |
1369 | "status for VCN%x: 0x%x\n", resp, enabled_vcn, init_status); | |
1370 | ||
1371 | return 0; | |
1372 | } | |
1373 | ||
8da1170a LL |
1374 | /** |
1375 | * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode | |
1376 | * | |
1377 | * @adev: amdgpu_device pointer | |
1378 | * @inst_idx: instance number index | |
1379 | * | |
1380 | * Stop VCN block with dpg mode | |
1381 | */ | |
385bf5a8 | 1382 | static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) |
8da1170a LL |
1383 | { |
1384 | uint32_t tmp; | |
1385 | ||
1386 | /* Wait for power status to be 1 */ | |
1387 | SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, | |
1388 | UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); | |
1389 | ||
1390 | /* wait for read ptr to be equal to write ptr */ | |
1391 | tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR); | |
1392 | SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF); | |
1393 | ||
8da1170a LL |
1394 | SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, |
1395 | UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); | |
1396 | ||
1397 | /* disable dynamic power gating mode */ | |
1398 | WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0, | |
1399 | ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); | |
8da1170a LL |
1400 | } |
1401 | ||
1402 | /** | |
1403 | * vcn_v4_0_stop - VCN stop | |
1404 | * | |
1405 | * @adev: amdgpu_device pointer | |
1406 | * | |
1407 | * Stop VCN block | |
1408 | */ | |
1409 | static int vcn_v4_0_stop(struct amdgpu_device *adev) | |
1410 | { | |
bb4f196b | 1411 | volatile struct amdgpu_vcn4_fw_shared *fw_shared; |
8da1170a LL |
1412 | uint32_t tmp; |
1413 | int i, r = 0; | |
1414 | ||
1415 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
bb4f196b RD |
1416 | fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; |
1417 | fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; | |
1418 | ||
8da1170a | 1419 | if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { |
385bf5a8 | 1420 | vcn_v4_0_stop_dpg_mode(adev, i); |
8da1170a LL |
1421 | continue; |
1422 | } | |
1423 | ||
1424 | /* wait for vcn idle */ | |
1425 | r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); | |
1426 | if (r) | |
1427 | return r; | |
1428 | ||
1429 | tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | | |
1430 | UVD_LMI_STATUS__READ_CLEAN_MASK | | |
1431 | UVD_LMI_STATUS__WRITE_CLEAN_MASK | | |
1432 | UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; | |
1433 | r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); | |
1434 | if (r) | |
1435 | return r; | |
1436 | ||
1437 | /* disable LMI UMC channel */ | |
1438 | tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); | |
1439 | tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; | |
1440 | WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); | |
1441 | tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | | |
1442 | UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; | |
1443 | r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); | |
1444 | if (r) | |
1445 | return r; | |
1446 | ||
1447 | /* block VCPU register access */ | |
1448 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), | |
1449 | UVD_RB_ARB_CTRL__VCPU_DIS_MASK, | |
1450 | ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); | |
1451 | ||
1452 | /* reset VCPU */ | |
1453 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), | |
1454 | UVD_VCPU_CNTL__BLK_RST_MASK, | |
1455 | ~UVD_VCPU_CNTL__BLK_RST_MASK); | |
1456 | ||
1457 | /* disable VCPU clock */ | |
1458 | WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, | |
1459 | ~(UVD_VCPU_CNTL__CLK_EN_MASK)); | |
1460 | ||
1461 | /* apply soft reset */ | |
1462 | tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); | |
1463 | tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; | |
1464 | WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); | |
1465 | tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); | |
1466 | tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; | |
1467 | WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); | |
1468 | ||
1469 | /* clear status */ | |
1470 | WREG32_SOC15(VCN, i, regUVD_STATUS, 0); | |
1471 | ||
1472 | /* apply HW clock gating */ | |
1473 | vcn_v4_0_enable_clock_gating(adev, i); | |
1474 | ||
1475 | /* enable VCN power gating */ | |
1476 | vcn_v4_0_enable_static_power_gating(adev, i); | |
1477 | } | |
1478 | ||
1479 | if (adev->pm.dpm_enabled) | |
1480 | amdgpu_dpm_enable_uvd(adev, false); | |
1481 | ||
1482 | return 0; | |
1483 | } | |
1484 | ||
1485 | /** | |
1486 | * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode | |
1487 | * | |
1488 | * @adev: amdgpu_device pointer | |
1489 | * @inst_idx: instance number index | |
1490 | * @new_state: pause state | |
1491 | * | |
1492 | * Pause dpg mode for VCN block | |
1493 | */ | |
1494 | static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, | |
1495 | struct dpg_pause_state *new_state) | |
1496 | { | |
1497 | uint32_t reg_data = 0; | |
1498 | int ret_code; | |
1499 | ||
1500 | /* pause/unpause if state is changed */ | |
1501 | if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) { | |
1502 | DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d", | |
1503 | adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based); | |
1504 | reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) & | |
1505 | (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); | |
1506 | ||
1507 | if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { | |
1508 | ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1, | |
1509 | UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); | |
1510 | ||
1511 | if (!ret_code) { | |
1512 | /* pause DPG */ | |
1513 | reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; | |
1514 | WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data); | |
1515 | ||
1516 | /* wait for ACK */ | |
1517 | SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE, | |
1518 | UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, | |
1519 | UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); | |
1520 | ||
1521 | SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, | |
1522 | UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); | |
1523 | } | |
1524 | } else { | |
1525 | /* unpause dpg, no need to wait */ | |
1526 | reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; | |
1527 | WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data); | |
8da1170a LL |
1528 | } |
1529 | adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based; | |
1530 | } | |
1531 | ||
1532 | return 0; | |
1533 | } | |
1534 | ||
1535 | /** | |
bb4f196b | 1536 | * vcn_v4_0_unified_ring_get_rptr - get unified read pointer |
8da1170a LL |
1537 | * |
1538 | * @ring: amdgpu_ring pointer | |
1539 | * | |
bb4f196b | 1540 | * Returns the current hardware unified read pointer |
8da1170a | 1541 | */ |
bb4f196b | 1542 | static uint64_t vcn_v4_0_unified_ring_get_rptr(struct amdgpu_ring *ring) |
8da1170a LL |
1543 | { |
1544 | struct amdgpu_device *adev = ring->adev; | |
1545 | ||
bb4f196b RD |
1546 | if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) |
1547 | DRM_ERROR("wrong ring id is identified in %s", __func__); | |
1548 | ||
1549 | return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR); | |
8da1170a LL |
1550 | } |
1551 | ||
1552 | /** | |
bb4f196b | 1553 | * vcn_v4_0_unified_ring_get_wptr - get unified write pointer |
8da1170a LL |
1554 | * |
1555 | * @ring: amdgpu_ring pointer | |
1556 | * | |
bb4f196b | 1557 | * Returns the current hardware unified write pointer |
8da1170a | 1558 | */ |
bb4f196b | 1559 | static uint64_t vcn_v4_0_unified_ring_get_wptr(struct amdgpu_ring *ring) |
8da1170a LL |
1560 | { |
1561 | struct amdgpu_device *adev = ring->adev; | |
1562 | ||
bb4f196b RD |
1563 | if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) |
1564 | DRM_ERROR("wrong ring id is identified in %s", __func__); | |
1565 | ||
8da1170a LL |
1566 | if (ring->use_doorbell) |
1567 | return *ring->wptr_cpu_addr; | |
1568 | else | |
bb4f196b | 1569 | return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR); |
8da1170a LL |
1570 | } |
1571 | ||
1572 | /** | |
bb4f196b | 1573 | * vcn_v4_0_unified_ring_set_wptr - set enc write pointer |
8da1170a LL |
1574 | * |
1575 | * @ring: amdgpu_ring pointer | |
1576 | * | |
bb4f196b | 1577 | * Commits the enc write pointer to the hardware |
8da1170a | 1578 | */ |
bb4f196b | 1579 | static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring) |
8da1170a LL |
1580 | { |
1581 | struct amdgpu_device *adev = ring->adev; | |
1582 | ||
bb4f196b RD |
1583 | if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) |
1584 | DRM_ERROR("wrong ring id is identified in %s", __func__); | |
8da1170a LL |
1585 | |
1586 | if (ring->use_doorbell) { | |
1587 | *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); | |
1588 | WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); | |
1589 | } else { | |
bb4f196b | 1590 | WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr)); |
8da1170a LL |
1591 | } |
1592 | } | |
1593 | ||
0b15205c SJ |
1594 | static int vcn_v4_0_limit_sched(struct amdgpu_cs_parser *p) |
1595 | { | |
1596 | struct drm_gpu_scheduler **scheds; | |
1597 | ||
1598 | /* The create msg must be in the first IB submitted */ | |
1599 | if (atomic_read(&p->entity->fence_seq)) | |
1600 | return -EINVAL; | |
1601 | ||
1602 | scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] | |
1603 | [AMDGPU_RING_PRIO_0].sched; | |
1604 | drm_sched_entity_modify_sched(p->entity, scheds, 1); | |
1605 | return 0; | |
1606 | } | |
1607 | ||
1608 | static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, uint64_t addr) | |
1609 | { | |
1610 | struct ttm_operation_ctx ctx = { false, false }; | |
1611 | struct amdgpu_bo_va_mapping *map; | |
1612 | uint32_t *msg, num_buffers; | |
1613 | struct amdgpu_bo *bo; | |
1614 | uint64_t start, end; | |
1615 | unsigned int i; | |
1616 | void *ptr; | |
1617 | int r; | |
1618 | ||
1619 | addr &= AMDGPU_GMC_HOLE_MASK; | |
1620 | r = amdgpu_cs_find_mapping(p, addr, &bo, &map); | |
1621 | if (r) { | |
1622 | DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr); | |
1623 | return r; | |
1624 | } | |
1625 | ||
1626 | start = map->start * AMDGPU_GPU_PAGE_SIZE; | |
1627 | end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE; | |
1628 | if (addr & 0x7) { | |
1629 | DRM_ERROR("VCN messages must be 8 byte aligned!\n"); | |
1630 | return -EINVAL; | |
1631 | } | |
1632 | ||
1633 | bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; | |
1634 | amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); | |
1635 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); | |
1636 | if (r) { | |
1637 | DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r); | |
1638 | return r; | |
1639 | } | |
1640 | ||
1641 | r = amdgpu_bo_kmap(bo, &ptr); | |
1642 | if (r) { | |
1643 | DRM_ERROR("Failed mapping the VCN message (%d)!\n", r); | |
1644 | return r; | |
1645 | } | |
1646 | ||
1647 | msg = ptr + addr - start; | |
1648 | ||
1649 | /* Check length */ | |
1650 | if (msg[1] > end - addr) { | |
1651 | r = -EINVAL; | |
1652 | goto out; | |
1653 | } | |
1654 | ||
1655 | if (msg[3] != RDECODE_MSG_CREATE) | |
1656 | goto out; | |
1657 | ||
1658 | num_buffers = msg[2]; | |
1659 | for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { | |
1660 | uint32_t offset, size, *create; | |
1661 | ||
1662 | if (msg[0] != RDECODE_MESSAGE_CREATE) | |
1663 | continue; | |
1664 | ||
1665 | offset = msg[1]; | |
1666 | size = msg[2]; | |
1667 | ||
1668 | if (offset + size > end) { | |
1669 | r = -EINVAL; | |
1670 | goto out; | |
1671 | } | |
1672 | ||
1673 | create = ptr + addr + offset - start; | |
1674 | ||
1675 | /* H246, HEVC and VP9 can run on any instance */ | |
1676 | if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) | |
1677 | continue; | |
1678 | ||
1679 | r = vcn_v4_0_limit_sched(p); | |
1680 | if (r) | |
1681 | goto out; | |
1682 | } | |
1683 | ||
1684 | out: | |
1685 | amdgpu_bo_kunmap(bo); | |
1686 | return r; | |
1687 | } | |
1688 | ||
1689 | #define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) | |
1690 | ||
1691 | static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, | |
1692 | struct amdgpu_job *job, | |
1693 | struct amdgpu_ib *ib) | |
1694 | { | |
1695 | struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched); | |
1696 | struct amdgpu_vcn_decode_buffer *decode_buffer = NULL; | |
1697 | uint32_t val; | |
1698 | int r = 0; | |
1699 | ||
1700 | /* The first instance can decode anything */ | |
1701 | if (!ring->me) | |
1702 | return r; | |
1703 | ||
1704 | /* unified queue ib header has 8 double words. */ | |
1705 | if (ib->length_dw < 8) | |
1706 | return r; | |
1707 | ||
1708 | val = amdgpu_ib_get_value(ib, 6); //RADEON_VCN_ENGINE_TYPE | |
1709 | ||
1710 | if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { | |
1711 | decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[10]; | |
1712 | ||
1713 | if (decode_buffer->valid_buf_flag & 0x1) | |
1714 | r = vcn_v4_0_dec_msg(p, ((u64)decode_buffer->msg_buffer_address_hi) << 32 | | |
1715 | decode_buffer->msg_buffer_address_lo); | |
1716 | } | |
1717 | return r; | |
1718 | } | |
1719 | ||
bb4f196b | 1720 | static const struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = { |
8da1170a LL |
1721 | .type = AMDGPU_RING_TYPE_VCN_ENC, |
1722 | .align_mask = 0x3f, | |
1723 | .nop = VCN_ENC_CMD_NO_OP, | |
1724 | .vmhub = AMDGPU_MMHUB_0, | |
bb4f196b RD |
1725 | .get_rptr = vcn_v4_0_unified_ring_get_rptr, |
1726 | .get_wptr = vcn_v4_0_unified_ring_get_wptr, | |
1727 | .set_wptr = vcn_v4_0_unified_ring_set_wptr, | |
0b15205c | 1728 | .patch_cs_in_place = vcn_v4_0_ring_patch_cs_in_place, |
8da1170a LL |
1729 | .emit_frame_size = |
1730 | SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + | |
1731 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + | |
1732 | 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ | |
1733 | 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ | |
1734 | 1, /* vcn_v2_0_enc_ring_insert_end */ | |
1735 | .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */ | |
1736 | .emit_ib = vcn_v2_0_enc_ring_emit_ib, | |
1737 | .emit_fence = vcn_v2_0_enc_ring_emit_fence, | |
1738 | .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush, | |
1739 | .test_ring = amdgpu_vcn_enc_ring_test_ring, | |
bb4f196b | 1740 | .test_ib = amdgpu_vcn_unified_ring_test_ib, |
8da1170a LL |
1741 | .insert_nop = amdgpu_ring_insert_nop, |
1742 | .insert_end = vcn_v2_0_enc_ring_insert_end, | |
1743 | .pad_ib = amdgpu_ring_generic_pad_ib, | |
1744 | .begin_use = amdgpu_vcn_ring_begin_use, | |
1745 | .end_use = amdgpu_vcn_ring_end_use, | |
1746 | .emit_wreg = vcn_v2_0_enc_ring_emit_wreg, | |
1747 | .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait, | |
1748 | .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, | |
1749 | }; | |
1750 | ||
1751 | /** | |
bb4f196b | 1752 | * vcn_v4_0_set_unified_ring_funcs - set unified ring functions |
8da1170a LL |
1753 | * |
1754 | * @adev: amdgpu_device pointer | |
1755 | * | |
bb4f196b | 1756 | * Set unified ring functions |
8da1170a | 1757 | */ |
bb4f196b | 1758 | static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev) |
8da1170a LL |
1759 | { |
1760 | int i; | |
1761 | ||
1762 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
1763 | if (adev->vcn.harvest_config & (1 << i)) | |
1764 | continue; | |
1765 | ||
bb4f196b RD |
1766 | adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_unified_ring_vm_funcs; |
1767 | adev->vcn.inst[i].ring_enc[0].me = i; | |
8da1170a | 1768 | |
bb4f196b | 1769 | DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i); |
8da1170a LL |
1770 | } |
1771 | } | |
1772 | ||
1773 | /** | |
1774 | * vcn_v4_0_is_idle - check VCN block is idle | |
1775 | * | |
1776 | * @handle: amdgpu_device pointer | |
1777 | * | |
1778 | * Check whether VCN block is idle | |
1779 | */ | |
1780 | static bool vcn_v4_0_is_idle(void *handle) | |
1781 | { | |
1782 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
1783 | int i, ret = 1; | |
1784 | ||
1785 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
1786 | if (adev->vcn.harvest_config & (1 << i)) | |
1787 | continue; | |
1788 | ||
1789 | ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE); | |
1790 | } | |
1791 | ||
1792 | return ret; | |
1793 | } | |
1794 | ||
1795 | /** | |
1796 | * vcn_v4_0_wait_for_idle - wait for VCN block idle | |
1797 | * | |
1798 | * @handle: amdgpu_device pointer | |
1799 | * | |
1800 | * Wait for VCN block idle | |
1801 | */ | |
1802 | static int vcn_v4_0_wait_for_idle(void *handle) | |
1803 | { | |
1804 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
1805 | int i, ret = 0; | |
1806 | ||
1807 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
1808 | if (adev->vcn.harvest_config & (1 << i)) | |
1809 | continue; | |
1810 | ||
1811 | ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, | |
1812 | UVD_STATUS__IDLE); | |
1813 | if (ret) | |
1814 | return ret; | |
1815 | } | |
1816 | ||
1817 | return ret; | |
1818 | } | |
1819 | ||
1820 | /** | |
1821 | * vcn_v4_0_set_clockgating_state - set VCN block clockgating state | |
1822 | * | |
1823 | * @handle: amdgpu_device pointer | |
1824 | * @state: clock gating state | |
1825 | * | |
1826 | * Set VCN block clockgating state | |
1827 | */ | |
1828 | static int vcn_v4_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) | |
1829 | { | |
1830 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
1831 | bool enable = (state == AMD_CG_STATE_GATE) ? true : false; | |
1832 | int i; | |
1833 | ||
1834 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
1835 | if (adev->vcn.harvest_config & (1 << i)) | |
1836 | continue; | |
1837 | ||
1838 | if (enable) { | |
1839 | if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE) | |
1840 | return -EBUSY; | |
1841 | vcn_v4_0_enable_clock_gating(adev, i); | |
1842 | } else { | |
1843 | vcn_v4_0_disable_clock_gating(adev, i); | |
1844 | } | |
1845 | } | |
1846 | ||
1847 | return 0; | |
1848 | } | |
1849 | ||
1850 | /** | |
1851 | * vcn_v4_0_set_powergating_state - set VCN block powergating state | |
1852 | * | |
1853 | * @handle: amdgpu_device pointer | |
1854 | * @state: power gating state | |
1855 | * | |
1856 | * Set VCN block powergating state | |
1857 | */ | |
1858 | static int vcn_v4_0_set_powergating_state(void *handle, enum amd_powergating_state state) | |
1859 | { | |
1860 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
1861 | int ret; | |
1862 | ||
aa44beb5 JJ |
1863 | /* for SRIOV, guest should not control VCN Power-gating |
1864 | * MMSCH FW should control Power-gating and clock-gating | |
1865 | * guest should avoid touching CGC and PG | |
1866 | */ | |
1867 | if (amdgpu_sriov_vf(adev)) { | |
1868 | adev->vcn.cur_state = AMD_PG_STATE_UNGATE; | |
1869 | return 0; | |
1870 | } | |
1871 | ||
8da1170a LL |
1872 | if(state == adev->vcn.cur_state) |
1873 | return 0; | |
1874 | ||
1875 | if (state == AMD_PG_STATE_GATE) | |
1876 | ret = vcn_v4_0_stop(adev); | |
1877 | else | |
1878 | ret = vcn_v4_0_start(adev); | |
1879 | ||
1880 | if(!ret) | |
1881 | adev->vcn.cur_state = state; | |
1882 | ||
1883 | return ret; | |
1884 | } | |
1885 | ||
1886 | /** | |
1887 | * vcn_v4_0_set_interrupt_state - set VCN block interrupt state | |
1888 | * | |
1889 | * @adev: amdgpu_device pointer | |
1890 | * @source: interrupt sources | |
1891 | * @type: interrupt types | |
1892 | * @state: interrupt states | |
1893 | * | |
1894 | * Set VCN block interrupt state | |
1895 | */ | |
1896 | static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
1897 | unsigned type, enum amdgpu_interrupt_state state) | |
1898 | { | |
1899 | return 0; | |
1900 | } | |
1901 | ||
1902 | /** | |
1903 | * vcn_v4_0_process_interrupt - process VCN block interrupt | |
1904 | * | |
1905 | * @adev: amdgpu_device pointer | |
1906 | * @source: interrupt sources | |
1907 | * @entry: interrupt entry from clients and sources | |
1908 | * | |
1909 | * Process VCN block interrupt | |
1910 | */ | |
1911 | static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
1912 | struct amdgpu_iv_entry *entry) | |
1913 | { | |
1914 | uint32_t ip_instance; | |
1915 | ||
1916 | switch (entry->client_id) { | |
1917 | case SOC15_IH_CLIENTID_VCN: | |
1918 | ip_instance = 0; | |
1919 | break; | |
1920 | case SOC15_IH_CLIENTID_VCN1: | |
1921 | ip_instance = 1; | |
1922 | break; | |
1923 | default: | |
1924 | DRM_ERROR("Unhandled client id: %d\n", entry->client_id); | |
1925 | return 0; | |
1926 | } | |
1927 | ||
1928 | DRM_DEBUG("IH: VCN TRAP\n"); | |
1929 | ||
1930 | switch (entry->src_id) { | |
8da1170a LL |
1931 | case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE: |
1932 | amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]); | |
1933 | break; | |
8da1170a LL |
1934 | default: |
1935 | DRM_ERROR("Unhandled interrupt: %d %d\n", | |
1936 | entry->src_id, entry->src_data[0]); | |
1937 | break; | |
1938 | } | |
1939 | ||
1940 | return 0; | |
1941 | } | |
1942 | ||
1943 | static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = { | |
1944 | .set = vcn_v4_0_set_interrupt_state, | |
1945 | .process = vcn_v4_0_process_interrupt, | |
1946 | }; | |
1947 | ||
1948 | /** | |
1949 | * vcn_v4_0_set_irq_funcs - set VCN block interrupt irq functions | |
1950 | * | |
1951 | * @adev: amdgpu_device pointer | |
1952 | * | |
1953 | * Set VCN block interrupt irq functions | |
1954 | */ | |
1955 | static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev) | |
1956 | { | |
1957 | int i; | |
1958 | ||
1959 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | |
1960 | if (adev->vcn.harvest_config & (1 << i)) | |
1961 | continue; | |
1962 | ||
1963 | adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; | |
1964 | adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs; | |
1965 | } | |
1966 | } | |
1967 | ||
1968 | static const struct amd_ip_funcs vcn_v4_0_ip_funcs = { | |
1969 | .name = "vcn_v4_0", | |
1970 | .early_init = vcn_v4_0_early_init, | |
1971 | .late_init = NULL, | |
1972 | .sw_init = vcn_v4_0_sw_init, | |
1973 | .sw_fini = vcn_v4_0_sw_fini, | |
1974 | .hw_init = vcn_v4_0_hw_init, | |
1975 | .hw_fini = vcn_v4_0_hw_fini, | |
1976 | .suspend = vcn_v4_0_suspend, | |
1977 | .resume = vcn_v4_0_resume, | |
1978 | .is_idle = vcn_v4_0_is_idle, | |
1979 | .wait_for_idle = vcn_v4_0_wait_for_idle, | |
1980 | .check_soft_reset = NULL, | |
1981 | .pre_soft_reset = NULL, | |
1982 | .soft_reset = NULL, | |
1983 | .post_soft_reset = NULL, | |
1984 | .set_clockgating_state = vcn_v4_0_set_clockgating_state, | |
1985 | .set_powergating_state = vcn_v4_0_set_powergating_state, | |
1986 | }; | |
1987 | ||
1988 | const struct amdgpu_ip_block_version vcn_v4_0_ip_block = | |
1989 | { | |
1990 | .type = AMD_IP_BLOCK_TYPE_VCN, | |
1991 | .major = 4, | |
1992 | .minor = 0, | |
1993 | .rev = 0, | |
1994 | .funcs = &vcn_v4_0_ip_funcs, | |
1995 | }; |