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