1 /*
2 * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
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"
28 #include "soc15.h"
29 #include "soc15d.h"
30 #include "soc15_hw_ip.h"
31 #include "vcn_v2_0.h"
32 #include "vcn_v4_0_3.h"
33
34 #include "vcn/vcn_5_0_0_offset.h"
35 #include "vcn/vcn_5_0_0_sh_mask.h"
36 #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
37 #include "vcn_v5_0_0.h"
38 #include "vcn_v5_0_1.h"
39 #include "vcn_v5_0_2.h"
40
41 #include <drm/drm_drv.h>
42
43 static void vcn_v5_0_2_set_unified_ring_funcs(struct amdgpu_device *adev);
44 static void vcn_v5_0_2_set_irq_funcs(struct amdgpu_device *adev);
45 static int vcn_v5_0_2_set_pg_state(struct amdgpu_vcn_inst *vinst,
46 enum amd_powergating_state state);
47 static void vcn_v5_0_2_unified_ring_set_wptr(struct amdgpu_ring *ring);
48
49 /**
50 * vcn_v5_0_2_early_init - set function pointers and load microcode
51 *
52 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
53 *
54 * Set ring and irq function pointers
55 * Load microcode from filesystem
56 */
vcn_v5_0_2_early_init(struct amdgpu_ip_block * ip_block)57 static int vcn_v5_0_2_early_init(struct amdgpu_ip_block *ip_block)
58 {
59 struct amdgpu_device *adev = ip_block->adev;
60 int i, r;
61
62 for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
63 /* re-use enc ring as unified ring */
64 adev->vcn.inst[i].num_enc_rings = 1;
65
66 vcn_v5_0_2_set_unified_ring_funcs(adev);
67 vcn_v5_0_2_set_irq_funcs(adev);
68
69 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
70 adev->vcn.inst[i].set_pg_state = vcn_v5_0_2_set_pg_state;
71
72 r = amdgpu_vcn_early_init(adev, i);
73 if (r)
74 return r;
75 }
76
77 return 0;
78 }
79
vcn_v5_0_2_fw_shared_init(struct amdgpu_device * adev,int inst_idx)80 static void vcn_v5_0_2_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
81 {
82 struct amdgpu_vcn5_fw_shared *fw_shared;
83
84 fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
85
86 if (fw_shared->sq.is_enabled)
87 return;
88 fw_shared->present_flag_0 =
89 cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
90 fw_shared->sq.is_enabled = 1;
91
92 if (amdgpu_vcnfw_log)
93 amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]);
94 }
95
96 /**
97 * vcn_v5_0_2_sw_init - sw init for VCN block
98 *
99 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
100 *
101 * Load firmware and sw initialization
102 */
vcn_v5_0_2_sw_init(struct amdgpu_ip_block * ip_block)103 static int vcn_v5_0_2_sw_init(struct amdgpu_ip_block *ip_block)
104 {
105 struct amdgpu_device *adev = ip_block->adev;
106 struct amdgpu_ring *ring;
107 int i, r, vcn_inst;
108
109 /* VCN UNIFIED TRAP */
110 r = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_VCN,
111 VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
112 if (r)
113 return r;
114
115 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
116 vcn_inst = GET_INST(VCN, i);
117
118 r = amdgpu_vcn_sw_init(adev, i);
119 if (r)
120 return r;
121
122 amdgpu_vcn_setup_ucode(adev, i);
123
124 r = amdgpu_vcn_resume(adev, i);
125 if (r)
126 return r;
127
128 ring = &adev->vcn.inst[i].ring_enc[0];
129 ring->use_doorbell = true;
130
131 ring->doorbell_index =
132 (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 32 * vcn_inst;
133
134 ring->vm_hub = AMDGPU_MMHUB0(adev->vcn.inst[i].aid_id);
135 sprintf(ring->name, "vcn_unified_%d", adev->vcn.inst[i].aid_id);
136
137 r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
138 AMDGPU_RING_PRIO_DEFAULT, &adev->vcn.inst[i].sched_score);
139 if (r)
140 return r;
141
142 vcn_v5_0_2_fw_shared_init(adev, i);
143 }
144
145 /* TODO: Add queue reset mask when FW fully supports it */
146 adev->vcn.supported_reset =
147 amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
148
149 return amdgpu_vcn_sysfs_reset_mask_init(adev);
150 }
151
152 /**
153 * vcn_v5_0_2_sw_fini - sw fini for VCN block
154 *
155 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
156 *
157 * VCN suspend and free up sw allocation
158 */
vcn_v5_0_2_sw_fini(struct amdgpu_ip_block * ip_block)159 static int vcn_v5_0_2_sw_fini(struct amdgpu_ip_block *ip_block)
160 {
161 struct amdgpu_device *adev = ip_block->adev;
162 int i, r, idx;
163
164 if (drm_dev_enter(adev_to_drm(adev), &idx)) {
165 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
166 struct amdgpu_vcn5_fw_shared *fw_shared;
167
168 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
169 fw_shared->present_flag_0 = 0;
170 fw_shared->sq.is_enabled = 0;
171 }
172
173 drm_dev_exit(idx);
174 }
175
176 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
177 r = amdgpu_vcn_suspend(adev, i);
178 if (r)
179 return r;
180 }
181
182 for (i = 0; i < adev->vcn.num_vcn_inst; i++)
183 amdgpu_vcn_sw_fini(adev, i);
184
185 amdgpu_vcn_sysfs_reset_mask_fini(adev);
186
187 kfree(adev->vcn.ip_dump); //TODO check
188
189 return 0;
190 }
191
192 /**
193 * vcn_v5_0_2_hw_init - start and test VCN block
194 *
195 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
196 *
197 * Initialize the hardware, boot up the VCPU and do some testing
198 */
vcn_v5_0_2_hw_init(struct amdgpu_ip_block * ip_block)199 static int vcn_v5_0_2_hw_init(struct amdgpu_ip_block *ip_block)
200 {
201 struct amdgpu_device *adev = ip_block->adev;
202 struct amdgpu_ring *ring;
203 int i, r, vcn_inst;
204 uint32_t tmp;
205
206 if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x200)
207 adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED);
208 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
209 vcn_inst = GET_INST(VCN, i);
210 ring = &adev->vcn.inst[i].ring_enc[0];
211
212 /* Remove Video Tiles antihang mechanism */
213 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS);
214 tmp &= (~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
215 WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp);
216
217 if (ring->use_doorbell)
218 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
219 ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
220 11 * vcn_inst),
221 adev->vcn.inst[i].aid_id);
222
223 /* Re-init fw_shared, if required */
224 vcn_v5_0_2_fw_shared_init(adev, i);
225
226 r = amdgpu_ring_test_helper(ring);
227 if (r)
228 return r;
229 }
230
231 return 0;
232 }
233
234 /**
235 * vcn_v5_0_2_hw_fini - stop the hardware block
236 *
237 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
238 *
239 * Stop the VCN block, mark ring as not ready any more
240 */
vcn_v5_0_2_hw_fini(struct amdgpu_ip_block * ip_block)241 static int vcn_v5_0_2_hw_fini(struct amdgpu_ip_block *ip_block)
242 {
243 struct amdgpu_device *adev = ip_block->adev;
244 int i;
245
246 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
247 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
248
249 cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
250 if (vinst->cur_state != AMD_PG_STATE_GATE)
251 vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
252 }
253
254 return 0;
255 }
256
257 /**
258 * vcn_v5_0_2_suspend - suspend VCN block
259 *
260 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
261 *
262 * HW fini and suspend VCN block
263 */
vcn_v5_0_2_suspend(struct amdgpu_ip_block * ip_block)264 static int vcn_v5_0_2_suspend(struct amdgpu_ip_block *ip_block)
265 {
266 struct amdgpu_device *adev = ip_block->adev;
267 int r, i;
268
269 r = vcn_v5_0_2_hw_fini(ip_block);
270 if (r)
271 return r;
272
273 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
274 r = amdgpu_vcn_suspend(ip_block->adev, i);
275 if (r)
276 return r;
277 }
278
279 return r;
280 }
281
282 /**
283 * vcn_v5_0_2_resume - resume VCN block
284 *
285 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
286 *
287 * Resume firmware and hw init VCN block
288 */
vcn_v5_0_2_resume(struct amdgpu_ip_block * ip_block)289 static int vcn_v5_0_2_resume(struct amdgpu_ip_block *ip_block)
290 {
291 struct amdgpu_device *adev = ip_block->adev;
292 int r, i;
293
294 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
295 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
296
297 if (amdgpu_in_reset(adev))
298 vinst->cur_state = AMD_PG_STATE_GATE;
299
300 r = amdgpu_vcn_resume(ip_block->adev, i);
301 if (r)
302 return r;
303 }
304
305 r = vcn_v5_0_2_hw_init(ip_block);
306
307 return r;
308 }
309
310 /**
311 * vcn_v5_0_2_mc_resume - memory controller programming
312 *
313 * @vinst: VCN instance
314 *
315 * Let the VCN memory controller know it's offsets
316 */
vcn_v5_0_2_mc_resume(struct amdgpu_vcn_inst * vinst)317 static void vcn_v5_0_2_mc_resume(struct amdgpu_vcn_inst *vinst)
318 {
319 struct amdgpu_device *adev = vinst->adev;
320 int inst = vinst->inst;
321 uint32_t offset, size, vcn_inst;
322 const struct common_firmware_header *hdr;
323
324 hdr = (const struct common_firmware_header *)adev->vcn.inst[inst].fw->data;
325 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
326
327 vcn_inst = GET_INST(VCN, inst);
328 /* cache window 0: fw */
329 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
330 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
331 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));
332 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
333 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));
334 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0, 0);
335 offset = 0;
336 } else {
337 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
338 lower_32_bits(adev->vcn.inst[inst].gpu_addr));
339 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
340 upper_32_bits(adev->vcn.inst[inst].gpu_addr));
341 offset = size;
342 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0,
343 AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
344 }
345 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE0, size);
346
347 /* cache window 1: stack */
348 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
349 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
350 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
351 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
352 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET1, 0);
353 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
354
355 /* cache window 2: context */
356 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
357 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
358 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
359 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
360 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET2, 0);
361 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
362
363 /* non-cache window */
364 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
365 lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
366 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
367 upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
368 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);
369 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_SIZE0,
370 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)));
371 }
372
373 /**
374 * vcn_v5_0_2_mc_resume_dpg_mode - memory controller programming for dpg mode
375 *
376 * @vinst: VCN instance
377 * @indirect: indirectly write sram
378 *
379 * Let the VCN memory controller know it's offsets with dpg mode
380 */
vcn_v5_0_2_mc_resume_dpg_mode(struct amdgpu_vcn_inst * vinst,bool indirect)381 static void vcn_v5_0_2_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
382 bool indirect)
383 {
384 struct amdgpu_device *adev = vinst->adev;
385 int inst_idx = vinst->inst;
386 uint32_t offset, size;
387 const struct common_firmware_header *hdr;
388
389 hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data;
390 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
391
392 /* cache window 0: fw */
393 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
394 if (!indirect) {
395 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
396 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
397 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
398 inst_idx].tmr_mc_addr_lo), 0, indirect);
399 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
400 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
401 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
402 inst_idx].tmr_mc_addr_hi), 0, indirect);
403 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
404 VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
405 } else {
406 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
407 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);
408 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
409 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);
410 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
411 VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
412 }
413 offset = 0;
414 } else {
415 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
416 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
417 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
418 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
419 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
420 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
421 offset = size;
422 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
423 VCN, 0, regUVD_VCPU_CACHE_OFFSET0),
424 AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);
425 }
426
427 if (!indirect)
428 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
429 VCN, 0, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);
430 else
431 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
432 VCN, 0, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);
433
434 /* cache window 1: stack */
435 if (!indirect) {
436 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
437 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
438 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
439 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
440 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
441 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
442 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
443 VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
444 } else {
445 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
446 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);
447 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
448 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);
449 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
450 VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
451 }
452 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
453 VCN, 0, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);
454
455 /* cache window 2: context */
456 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
457 VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
458 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
459 AMDGPU_VCN_STACK_SIZE), 0, indirect);
460 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
461 VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
462 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
463 AMDGPU_VCN_STACK_SIZE), 0, indirect);
464 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
465 VCN, 0, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);
466 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
467 VCN, 0, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);
468
469 /* non-cache window */
470 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
471 VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
472 lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
473 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
474 VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),
475 upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
476 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
477 VCN, 0, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);
478 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
479 VCN, 0, regUVD_VCPU_NONCACHE_SIZE0),
480 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect);
481
482 /* VCN global tiling registers */
483 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
484 VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
485 }
486
487 /**
488 * vcn_v5_0_2_disable_clock_gating - disable VCN clock gating
489 *
490 * @vinst: VCN instance
491 *
492 * Disable clock gating for VCN block
493 */
vcn_v5_0_2_disable_clock_gating(struct amdgpu_vcn_inst * vinst)494 static void vcn_v5_0_2_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
495 {
496 }
497
498 /**
499 * vcn_v5_0_2_enable_clock_gating - enable VCN clock gating
500 *
501 * @vinst: VCN instance
502 *
503 * Enable clock gating for VCN block
504 */
vcn_v5_0_2_enable_clock_gating(struct amdgpu_vcn_inst * vinst)505 static void vcn_v5_0_2_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
506 {
507 }
508
509 /**
510 * vcn_v5_0_2_pause_dpg_mode - VCN pause with dpg mode
511 *
512 * @vinst: VCN instance
513 * @new_state: pause state
514 *
515 * Pause dpg mode for VCN block
516 */
vcn_v5_0_2_pause_dpg_mode(struct amdgpu_vcn_inst * vinst,struct dpg_pause_state * new_state)517 static int vcn_v5_0_2_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
518 struct dpg_pause_state *new_state)
519 {
520 struct amdgpu_device *adev = vinst->adev;
521 uint32_t reg_data = 0;
522 int vcn_inst;
523
524 vcn_inst = GET_INST(VCN, vinst->inst);
525
526 /* pause/unpause if state is changed */
527 if (vinst->pause_state.fw_based != new_state->fw_based) {
528 DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d %s\n",
529 vinst->pause_state.fw_based, new_state->fw_based,
530 new_state->fw_based ? "VCN_DPG_STATE__PAUSE" : "VCN_DPG_STATE__UNPAUSE");
531 reg_data = RREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE) &
532 (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
533
534 if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
535 /* pause DPG */
536 reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
537 WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);
538
539 /* wait for ACK */
540 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_DPG_PAUSE,
541 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
542 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
543 } else {
544 /* unpause DPG, no need to wait */
545 reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
546 WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data);
547 }
548 vinst->pause_state.fw_based = new_state->fw_based;
549 }
550
551 return 0;
552 }
553
554 /**
555 * vcn_v5_0_2_start_dpg_mode - VCN start with dpg mode
556 *
557 * @vinst: VCN instance
558 * @indirect: indirectly write sram
559 *
560 * Start VCN block with dpg mode
561 */
vcn_v5_0_2_start_dpg_mode(struct amdgpu_vcn_inst * vinst,bool indirect)562 static int vcn_v5_0_2_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
563 bool indirect)
564 {
565 struct amdgpu_device *adev = vinst->adev;
566 int inst_idx = vinst->inst;
567 struct amdgpu_vcn5_fw_shared *fw_shared =
568 adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
569 struct amdgpu_ring *ring;
570 struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
571 int vcn_inst, ret;
572 uint32_t tmp;
573
574 vcn_inst = GET_INST(VCN, inst_idx);
575
576 /* disable register anti-hang mechanism */
577 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 1,
578 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
579
580 /* enable dynamic power gating mode */
581 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS);
582 tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
583 WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp);
584
585 if (indirect) {
586 adev->vcn.inst[inst_idx].dpg_sram_curr_addr =
587 (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
588 /* Use dummy register 0xDEADBEEF passing AID selection to PSP FW */
589 WREG32_SOC24_DPG_MODE(inst_idx, 0xDEADBEEF,
590 adev->vcn.inst[inst_idx].aid_id, 0, true);
591 }
592
593 /* enable VCPU clock */
594 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
595 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;
596 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
597 VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
598
599 /* disable master interrupt */
600 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
601 VCN, 0, regUVD_MASTINT_EN), 0, 0, indirect);
602
603 /* setup regUVD_LMI_CTRL */
604 tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
605 UVD_LMI_CTRL__REQ_MODE_MASK |
606 UVD_LMI_CTRL__CRC_RESET_MASK |
607 UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
608 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
609 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
610 (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
611 0x00100000L);
612 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
613 VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect);
614
615 vcn_v5_0_2_mc_resume_dpg_mode(vinst, indirect);
616
617 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
618 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
619 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
620 VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
621
622 /* enable LMI MC and UMC channels */
623 tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;
624 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
625 VCN, 0, regUVD_LMI_CTRL2), tmp, 0, indirect);
626
627 /* enable master interrupt */
628 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
629 VCN, 0, regUVD_MASTINT_EN),
630 UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);
631
632 if (indirect) {
633 ret = amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM);
634 if (ret) {
635 dev_err(adev->dev, "vcn sram load failed %d\n", ret);
636 return ret;
637 }
638 }
639
640 /* resetting ring, fw should not check RB ring */
641 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
642
643 /* Pause dpg */
644 vcn_v5_0_2_pause_dpg_mode(vinst, &state);
645
646 ring = &adev->vcn.inst[inst_idx].ring_enc[0];
647
648 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, lower_32_bits(ring->gpu_addr));
649 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
650 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / sizeof(uint32_t));
651
652 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
653 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
654 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
655 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
656 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
657
658 ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
659
660 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
661 tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
662 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
663 /* resetting done, fw can check RB ring */
664 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
665
666 WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
667 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
668 VCN_RB1_DB_CTRL__EN_MASK);
669 /* Read DB_CTRL to flush the write DB_CTRL command. */
670 RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
671
672 return 0;
673 }
674
675 /**
676 * vcn_v5_0_2_start - VCN start
677 *
678 * @vinst: VCN instance
679 *
680 * Start VCN block
681 */
vcn_v5_0_2_start(struct amdgpu_vcn_inst * vinst)682 static int vcn_v5_0_2_start(struct amdgpu_vcn_inst *vinst)
683 {
684 struct amdgpu_device *adev = vinst->adev;
685 int i = vinst->inst;
686 struct amdgpu_vcn5_fw_shared *fw_shared;
687 struct amdgpu_ring *ring;
688 uint32_t tmp;
689 int j, k, r, vcn_inst;
690
691 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
692
693 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
694 return vcn_v5_0_2_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
695
696 vcn_inst = GET_INST(VCN, i);
697
698 /* set VCN status busy */
699 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
700 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
701
702 /* enable VCPU clock */
703 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
704 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
705
706 /* disable master interrupt */
707 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
708 ~UVD_MASTINT_EN__VCPU_EN_MASK);
709
710 /* enable LMI MC and UMC channels */
711 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
712 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
713
714 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
715 tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
716 tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
717 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
718
719 /* setup regUVD_LMI_CTRL */
720 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
721 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
722 UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
723 UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
724 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
725 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
726
727 vcn_v5_0_2_mc_resume(vinst);
728
729 /* VCN global tiling registers */
730 WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
731 adev->gfx.config.gb_addr_config);
732
733 /* unblock VCPU register access */
734 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
735 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
736
737 /* release VCPU reset to boot */
738 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
739 ~UVD_VCPU_CNTL__BLK_RST_MASK);
740
741 for (j = 0; j < 10; ++j) {
742 uint32_t status;
743
744 for (k = 0; k < 100; ++k) {
745 status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
746 if (status & 2)
747 break;
748 mdelay(1000);
749 if (amdgpu_emu_mode == 1)
750 msleep(520);
751 }
752
753 if (amdgpu_emu_mode == 1) {
754 r = -1;
755 if (status & 2) {
756 r = 0;
757 break;
758 }
759 } else {
760 r = 0;
761 if (status & 2)
762 break;
763
764 dev_err(adev->dev,
765 "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
766 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
767 UVD_VCPU_CNTL__BLK_RST_MASK,
768 ~UVD_VCPU_CNTL__BLK_RST_MASK);
769 mdelay(10);
770 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
771 ~UVD_VCPU_CNTL__BLK_RST_MASK);
772
773 mdelay(10);
774 r = -1;
775 }
776 }
777
778 if (r) {
779 dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
780 return r;
781 }
782
783 /* enable master interrupt */
784 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
785 UVD_MASTINT_EN__VCPU_EN_MASK,
786 ~UVD_MASTINT_EN__VCPU_EN_MASK);
787
788 /* clear the busy bit of VCN_STATUS */
789 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
790 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
791
792 ring = &adev->vcn.inst[i].ring_enc[0];
793
794 WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
795 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
796 VCN_RB1_DB_CTRL__EN_MASK);
797
798 /* Read DB_CTRL to flush the write DB_CTRL command. */
799 RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
800
801 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
802 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
803 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
804
805 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
806 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
807 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
808 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
809 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
810 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
811
812 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
813 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
814 ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
815
816 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
817 tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
818 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
819 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
820
821 return 0;
822 }
823
824 /**
825 * vcn_v5_0_2_stop_dpg_mode - VCN stop with dpg mode
826 *
827 * @vinst: VCN instance
828 *
829 * Stop VCN block with dpg mode
830 */
vcn_v5_0_2_stop_dpg_mode(struct amdgpu_vcn_inst * vinst)831 static void vcn_v5_0_2_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
832 {
833 struct amdgpu_device *adev = vinst->adev;
834 int inst_idx = vinst->inst;
835 uint32_t tmp;
836 int vcn_inst;
837 struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
838
839 vcn_inst = GET_INST(VCN, inst_idx);
840
841 /* Unpause dpg */
842 vcn_v5_0_2_pause_dpg_mode(vinst, &state);
843
844 /* Wait for power status to be 1 */
845 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
846 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
847
848 /* wait for read ptr to be equal to write ptr */
849 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
850 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
851
852 /* disable dynamic power gating mode */
853 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 0,
854 ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
855 }
856
857 /**
858 * vcn_v5_0_2_stop - VCN stop
859 *
860 * @vinst: VCN instance
861 *
862 * Stop VCN block
863 */
vcn_v5_0_2_stop(struct amdgpu_vcn_inst * vinst)864 static int vcn_v5_0_2_stop(struct amdgpu_vcn_inst *vinst)
865 {
866 struct amdgpu_device *adev = vinst->adev;
867 int i = vinst->inst;
868 struct amdgpu_vcn5_fw_shared *fw_shared;
869 uint32_t tmp;
870 int r = 0, vcn_inst;
871
872 vcn_inst = GET_INST(VCN, i);
873
874 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
875 fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
876
877 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
878 vcn_v5_0_2_stop_dpg_mode(vinst);
879 return 0;
880 }
881
882 /* wait for vcn idle */
883 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
884 if (r)
885 return r;
886
887 tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
888 UVD_LMI_STATUS__READ_CLEAN_MASK |
889 UVD_LMI_STATUS__WRITE_CLEAN_MASK |
890 UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
891 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
892 if (r)
893 return r;
894
895 /* disable LMI UMC channel */
896 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
897 tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
898 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
899 tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
900 UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
901 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
902 if (r)
903 return r;
904
905 /* block VCPU register access */
906 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
907 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
908 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
909
910 /* reset VCPU */
911 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
912 UVD_VCPU_CNTL__BLK_RST_MASK,
913 ~UVD_VCPU_CNTL__BLK_RST_MASK);
914
915 /* disable VCPU clock */
916 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
917 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
918
919 /* apply soft reset */
920 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
921 tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
922 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
923 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
924 tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
925 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
926
927 /* clear status */
928 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
929
930 return 0;
931 }
932
933 /**
934 * vcn_v5_0_2_unified_ring_get_rptr - get unified read pointer
935 *
936 * @ring: amdgpu_ring pointer
937 *
938 * Returns the current hardware unified read pointer
939 */
vcn_v5_0_2_unified_ring_get_rptr(struct amdgpu_ring * ring)940 static uint64_t vcn_v5_0_2_unified_ring_get_rptr(struct amdgpu_ring *ring)
941 {
942 struct amdgpu_device *adev = ring->adev;
943
944 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
945 DRM_ERROR("wrong ring id is identified in %s", __func__);
946
947 return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_RPTR);
948 }
949
950 /**
951 * vcn_v5_0_2_unified_ring_get_wptr - get unified write pointer
952 *
953 * @ring: amdgpu_ring pointer
954 *
955 * Returns the current hardware unified write pointer
956 */
vcn_v5_0_2_unified_ring_get_wptr(struct amdgpu_ring * ring)957 static uint64_t vcn_v5_0_2_unified_ring_get_wptr(struct amdgpu_ring *ring)
958 {
959 struct amdgpu_device *adev = ring->adev;
960
961 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
962 DRM_ERROR("wrong ring id is identified in %s", __func__);
963
964 if (ring->use_doorbell)
965 return *ring->wptr_cpu_addr;
966 else
967 return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR);
968 }
969
970 /**
971 * vcn_v5_0_2_unified_ring_set_wptr - set enc write pointer
972 *
973 * @ring: amdgpu_ring pointer
974 *
975 * Commits the enc write pointer to the hardware
976 */
vcn_v5_0_2_unified_ring_set_wptr(struct amdgpu_ring * ring)977 static void vcn_v5_0_2_unified_ring_set_wptr(struct amdgpu_ring *ring)
978 {
979 struct amdgpu_device *adev = ring->adev;
980
981 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
982 DRM_ERROR("wrong ring id is identified in %s", __func__);
983
984 if (ring->use_doorbell) {
985 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
986 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
987 } else {
988 WREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR,
989 lower_32_bits(ring->wptr));
990 }
991 }
992
993 static const struct amdgpu_ring_funcs vcn_v5_0_2_unified_ring_vm_funcs = {
994 .type = AMDGPU_RING_TYPE_VCN_ENC,
995 .align_mask = 0x3f,
996 .nop = VCN_ENC_CMD_NO_OP,
997 .no_user_fence = true,
998 .get_rptr = vcn_v5_0_2_unified_ring_get_rptr,
999 .get_wptr = vcn_v5_0_2_unified_ring_get_wptr,
1000 .set_wptr = vcn_v5_0_2_unified_ring_set_wptr,
1001 .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
1002 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
1003 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
1004 5 +
1005 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
1006 1, /* vcn_v2_0_enc_ring_insert_end */
1007 .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
1008 .emit_ib = vcn_v2_0_enc_ring_emit_ib,
1009 .emit_fence = vcn_v2_0_enc_ring_emit_fence,
1010 .emit_vm_flush = vcn_v4_0_3_enc_ring_emit_vm_flush,
1011 .emit_hdp_flush = vcn_v4_0_3_ring_emit_hdp_flush,
1012 .test_ring = amdgpu_vcn_enc_ring_test_ring,
1013 .test_ib = amdgpu_vcn_unified_ring_test_ib,
1014 .insert_nop = amdgpu_ring_insert_nop,
1015 .insert_end = vcn_v2_0_enc_ring_insert_end,
1016 .pad_ib = amdgpu_ring_generic_pad_ib,
1017 .begin_use = amdgpu_vcn_ring_begin_use,
1018 .end_use = amdgpu_vcn_ring_end_use,
1019 .emit_wreg = vcn_v4_0_3_enc_ring_emit_wreg,
1020 .emit_reg_wait = vcn_v4_0_3_enc_ring_emit_reg_wait,
1021 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
1022 };
1023
1024 /**
1025 * vcn_v5_0_2_set_unified_ring_funcs - set unified ring functions
1026 *
1027 * @adev: amdgpu_device pointer
1028 *
1029 * Set unified ring functions
1030 */
vcn_v5_0_2_set_unified_ring_funcs(struct amdgpu_device * adev)1031 static void vcn_v5_0_2_set_unified_ring_funcs(struct amdgpu_device *adev)
1032 {
1033 int i, vcn_inst;
1034
1035 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1036 adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v5_0_2_unified_ring_vm_funcs;
1037 adev->vcn.inst[i].ring_enc[0].me = i;
1038 vcn_inst = GET_INST(VCN, i);
1039 adev->vcn.inst[i].aid_id = vcn_inst / adev->vcn.num_inst_per_aid;
1040 }
1041 }
1042
1043 /**
1044 * vcn_v5_0_2_is_idle - check VCN block is idle
1045 *
1046 * @ip_block: Pointer to the amdgpu_ip_block structure
1047 *
1048 * Check whether VCN block is idle
1049 */
vcn_v5_0_2_is_idle(struct amdgpu_ip_block * ip_block)1050 static bool vcn_v5_0_2_is_idle(struct amdgpu_ip_block *ip_block)
1051 {
1052 struct amdgpu_device *adev = ip_block->adev;
1053 int i, ret = 1;
1054
1055 for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
1056 ret &= (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) == UVD_STATUS__IDLE);
1057
1058 return ret;
1059 }
1060
1061 /**
1062 * vcn_v5_0_2_wait_for_idle - wait for VCN block idle
1063 *
1064 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
1065 *
1066 * Wait for VCN block idle
1067 */
vcn_v5_0_2_wait_for_idle(struct amdgpu_ip_block * ip_block)1068 static int vcn_v5_0_2_wait_for_idle(struct amdgpu_ip_block *ip_block)
1069 {
1070 struct amdgpu_device *adev = ip_block->adev;
1071 int i, ret = 0;
1072
1073 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1074 ret = SOC15_WAIT_ON_RREG(VCN, GET_INST(VCN, i), regUVD_STATUS, UVD_STATUS__IDLE,
1075 UVD_STATUS__IDLE);
1076 if (ret)
1077 return ret;
1078 }
1079
1080 return ret;
1081 }
1082
1083 /**
1084 * vcn_v5_0_2_set_clockgating_state - set VCN block clockgating state
1085 *
1086 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
1087 * @state: clock gating state
1088 *
1089 * Set VCN block clockgating state
1090 */
vcn_v5_0_2_set_clockgating_state(struct amdgpu_ip_block * ip_block,enum amd_clockgating_state state)1091 static int vcn_v5_0_2_set_clockgating_state(struct amdgpu_ip_block *ip_block,
1092 enum amd_clockgating_state state)
1093 {
1094 struct amdgpu_device *adev = ip_block->adev;
1095 bool enable = state == AMD_CG_STATE_GATE;
1096 int i;
1097
1098 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1099 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
1100
1101 if (enable) {
1102 if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE)
1103 return -EBUSY;
1104 vcn_v5_0_2_enable_clock_gating(vinst);
1105 } else {
1106 vcn_v5_0_2_disable_clock_gating(vinst);
1107 }
1108 }
1109
1110 return 0;
1111 }
1112
vcn_v5_0_2_set_pg_state(struct amdgpu_vcn_inst * vinst,enum amd_powergating_state state)1113 static int vcn_v5_0_2_set_pg_state(struct amdgpu_vcn_inst *vinst,
1114 enum amd_powergating_state state)
1115 {
1116 int ret = 0;
1117
1118 if (state == vinst->cur_state)
1119 return 0;
1120
1121 if (state == AMD_PG_STATE_GATE)
1122 ret = vcn_v5_0_2_stop(vinst);
1123 else
1124 ret = vcn_v5_0_2_start(vinst);
1125
1126 if (!ret)
1127 vinst->cur_state = state;
1128
1129 return ret;
1130 }
1131
1132 /**
1133 * vcn_v5_0_2_process_interrupt - process VCN block interrupt
1134 *
1135 * @adev: amdgpu_device pointer
1136 * @source: interrupt sources
1137 * @entry: interrupt entry from clients and sources
1138 *
1139 * Process VCN block interrupt
1140 */
vcn_v5_0_2_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)1141 static int vcn_v5_0_2_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
1142 struct amdgpu_iv_entry *entry)
1143 {
1144 uint32_t i, inst;
1145
1146 i = node_id_to_phys_map[entry->node_id];
1147
1148 DRM_DEV_DEBUG(adev->dev, "IH: VCN TRAP\n");
1149
1150 for (inst = 0; inst < adev->vcn.num_vcn_inst; ++inst)
1151 if (adev->vcn.inst[inst].aid_id == i)
1152 break;
1153
1154 if (inst >= adev->vcn.num_vcn_inst) {
1155 dev_WARN_ONCE(adev->dev, 1,
1156 "Interrupt received for unknown VCN instance %d",
1157 entry->node_id);
1158 return 0;
1159 }
1160
1161 switch (entry->src_id) {
1162 case VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
1163 amdgpu_fence_process(&adev->vcn.inst[inst].ring_enc[0]);
1164 break;
1165 default:
1166 DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
1167 entry->src_id, entry->src_data[0]);
1168 break;
1169 }
1170
1171 return 0;
1172 }
1173
1174 static const struct amdgpu_irq_src_funcs vcn_v5_0_2_irq_funcs = {
1175 .process = vcn_v5_0_2_process_interrupt,
1176 };
1177
1178 /**
1179 * vcn_v5_0_2_set_irq_funcs - set VCN block interrupt irq functions
1180 *
1181 * @adev: amdgpu_device pointer
1182 *
1183 * Set VCN block interrupt irq functions
1184 */
vcn_v5_0_2_set_irq_funcs(struct amdgpu_device * adev)1185 static void vcn_v5_0_2_set_irq_funcs(struct amdgpu_device *adev)
1186 {
1187 int i;
1188
1189 for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
1190 adev->vcn.inst->irq.num_types++;
1191 adev->vcn.inst->irq.funcs = &vcn_v5_0_2_irq_funcs;
1192 }
1193
1194 static const struct amd_ip_funcs vcn_v5_0_2_ip_funcs = {
1195 .name = "vcn_v5_0_2",
1196 .early_init = vcn_v5_0_2_early_init,
1197 .late_init = NULL,
1198 .sw_init = vcn_v5_0_2_sw_init,
1199 .sw_fini = vcn_v5_0_2_sw_fini,
1200 .hw_init = vcn_v5_0_2_hw_init,
1201 .hw_fini = vcn_v5_0_2_hw_fini,
1202 .suspend = vcn_v5_0_2_suspend,
1203 .resume = vcn_v5_0_2_resume,
1204 .is_idle = vcn_v5_0_2_is_idle,
1205 .wait_for_idle = vcn_v5_0_2_wait_for_idle,
1206 .check_soft_reset = NULL,
1207 .pre_soft_reset = NULL,
1208 .soft_reset = NULL,
1209 .post_soft_reset = NULL,
1210 .set_clockgating_state = vcn_v5_0_2_set_clockgating_state,
1211 .set_powergating_state = vcn_set_powergating_state,
1212 };
1213
1214 const struct amdgpu_ip_block_version vcn_v5_0_2_ip_block = {
1215 .type = AMD_IP_BLOCK_TYPE_VCN,
1216 .major = 5,
1217 .minor = 0,
1218 .rev = 2,
1219 .funcs = &vcn_v5_0_2_ip_funcs,
1220 };
1221