]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / amd / amdgpu / vcn_v5_0_1.c
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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         if (adev->pm.dpm_enabled)
579                 amdgpu_dpm_enable_uvd(adev, true);
580
581         for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
582                 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
583
584                 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
585                         r = vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
586                         continue;
587                 }
588
589                 vcn_inst = GET_INST(VCN, i);
590
591                 /* set VCN status busy */
592                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
593                 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
594
595                 /* enable VCPU clock */
596                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
597                         UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
598
599                 /* disable master interrupt */
600                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
601                         ~UVD_MASTINT_EN__VCPU_EN_MASK);
602
603                 /* enable LMI MC and UMC channels */
604                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
605                         ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
606
607                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
608                 tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
609                 tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
610                 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
611
612                 /* setup regUVD_LMI_CTRL */
613                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
614                 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
615                         UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
616                         UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
617                         UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
618                         UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
619
620                 vcn_v5_0_1_mc_resume(adev, i);
621
622                 /* VCN global tiling registers */
623                 WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
624                         adev->gfx.config.gb_addr_config);
625
626                 /* unblock VCPU register access */
627                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
628                         ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
629
630                 /* release VCPU reset to boot */
631                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
632                         ~UVD_VCPU_CNTL__BLK_RST_MASK);
633
634                 for (j = 0; j < 10; ++j) {
635                         uint32_t status;
636
637                         for (k = 0; k < 100; ++k) {
638                                 status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
639                                 if (status & 2)
640                                         break;
641                                 mdelay(100);
642                                 if (amdgpu_emu_mode == 1)
643                                         msleep(20);
644                         }
645
646                         if (amdgpu_emu_mode == 1) {
647                                 r = -1;
648                                 if (status & 2) {
649                                         r = 0;
650                                         break;
651                                 }
652                         } else {
653                                 r = 0;
654                                 if (status & 2)
655                                         break;
656
657                                 dev_err(adev->dev,
658                                     "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
659                                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
660                                                         UVD_VCPU_CNTL__BLK_RST_MASK,
661                                                         ~UVD_VCPU_CNTL__BLK_RST_MASK);
662                                 mdelay(10);
663                                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
664                                                         ~UVD_VCPU_CNTL__BLK_RST_MASK);
665
666                                 mdelay(10);
667                                 r = -1;
668                         }
669                 }
670
671                 if (r) {
672                         dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
673                         return r;
674                 }
675
676                 /* enable master interrupt */
677                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
678                                 UVD_MASTINT_EN__VCPU_EN_MASK,
679                                 ~UVD_MASTINT_EN__VCPU_EN_MASK);
680
681                 /* clear the busy bit of VCN_STATUS */
682                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
683                         ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
684
685                 ring = &adev->vcn.inst[i].ring_enc[0];
686
687                 WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
688                         ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
689                         VCN_RB1_DB_CTRL__EN_MASK);
690
691                 /* Read DB_CTRL to flush the write DB_CTRL command. */
692                 RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
693
694                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
695                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
696                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
697
698                 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
699                 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
700                 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
701                 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
702                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
703                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
704
705                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
706                 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
707                 ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
708
709                 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
710                 tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
711                 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
712                 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
713         }
714
715         return 0;
716 }
717
718 /**
719  * vcn_v5_0_1_stop_dpg_mode - VCN stop with dpg mode
720  *
721  * @adev: amdgpu_device pointer
722  * @inst_idx: instance number index
723  *
724  * Stop VCN block with dpg mode
725  */
726 static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
727 {
728         uint32_t tmp;
729         int vcn_inst;
730
731         vcn_inst = GET_INST(VCN, inst_idx);
732
733         /* Wait for power status to be 1 */
734         SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
735                 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
736
737         /* wait for read ptr to be equal to write ptr */
738         tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
739         SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
740
741         /* disable dynamic power gating mode */
742         WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 0,
743                 ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
744 }
745
746 /**
747  * vcn_v5_0_1_stop - VCN stop
748  *
749  * @adev: amdgpu_device pointer
750  *
751  * Stop VCN block
752  */
753 static int vcn_v5_0_1_stop(struct amdgpu_device *adev)
754 {
755         volatile struct amdgpu_vcn4_fw_shared *fw_shared;
756         uint32_t tmp;
757         int i, r = 0, vcn_inst;
758
759         for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
760                 vcn_inst = GET_INST(VCN, i);
761
762                 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
763                 fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
764
765                 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
766                         vcn_v5_0_1_stop_dpg_mode(adev, i);
767                         continue;
768                 }
769
770                 /* wait for vcn idle */
771                 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
772                 if (r)
773                         return r;
774
775                 tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
776                       UVD_LMI_STATUS__READ_CLEAN_MASK |
777                       UVD_LMI_STATUS__WRITE_CLEAN_MASK |
778                       UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
779                 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
780                 if (r)
781                         return r;
782
783                 /* disable LMI UMC channel */
784                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
785                 tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
786                 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
787                 tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
788                       UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
789                 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
790                 if (r)
791                         return r;
792
793                 /* block VCPU register access */
794                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
795                         UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
796                         ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
797
798                 /* reset VCPU */
799                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
800                         UVD_VCPU_CNTL__BLK_RST_MASK,
801                         ~UVD_VCPU_CNTL__BLK_RST_MASK);
802
803                 /* disable VCPU clock */
804                 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
805                         ~(UVD_VCPU_CNTL__CLK_EN_MASK));
806
807                 /* apply soft reset */
808                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
809                 tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
810                 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
811                 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
812                 tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
813                 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
814
815                 /* clear status */
816                 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
817         }
818
819         if (adev->pm.dpm_enabled)
820                 amdgpu_dpm_enable_uvd(adev, false);
821
822         return 0;
823 }
824
825 /**
826  * vcn_v5_0_1_unified_ring_get_rptr - get unified read pointer
827  *
828  * @ring: amdgpu_ring pointer
829  *
830  * Returns the current hardware unified read pointer
831  */
832 static uint64_t vcn_v5_0_1_unified_ring_get_rptr(struct amdgpu_ring *ring)
833 {
834         struct amdgpu_device *adev = ring->adev;
835
836         if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
837                 DRM_ERROR("wrong ring id is identified in %s", __func__);
838
839         return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_RPTR);
840 }
841
842 /**
843  * vcn_v5_0_1_unified_ring_get_wptr - get unified write pointer
844  *
845  * @ring: amdgpu_ring pointer
846  *
847  * Returns the current hardware unified write pointer
848  */
849 static uint64_t vcn_v5_0_1_unified_ring_get_wptr(struct amdgpu_ring *ring)
850 {
851         struct amdgpu_device *adev = ring->adev;
852
853         if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
854                 DRM_ERROR("wrong ring id is identified in %s", __func__);
855
856         if (ring->use_doorbell)
857                 return *ring->wptr_cpu_addr;
858         else
859                 return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR);
860 }
861
862 /**
863  * vcn_v5_0_1_unified_ring_set_wptr - set enc write pointer
864  *
865  * @ring: amdgpu_ring pointer
866  *
867  * Commits the enc write pointer to the hardware
868  */
869 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring)
870 {
871         struct amdgpu_device *adev = ring->adev;
872
873         if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
874                 DRM_ERROR("wrong ring id is identified in %s", __func__);
875
876         if (ring->use_doorbell) {
877                 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
878                 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
879         } else {
880                 WREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR,
881                                 lower_32_bits(ring->wptr));
882         }
883 }
884
885 static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {
886         .type = AMDGPU_RING_TYPE_VCN_ENC,
887         .align_mask = 0x3f,
888         .nop = VCN_ENC_CMD_NO_OP,
889         .get_rptr = vcn_v5_0_1_unified_ring_get_rptr,
890         .get_wptr = vcn_v5_0_1_unified_ring_get_wptr,
891         .set_wptr = vcn_v5_0_1_unified_ring_set_wptr,
892         .emit_frame_size =
893                 SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
894                 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
895                 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
896                 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
897                 1, /* vcn_v2_0_enc_ring_insert_end */
898         .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
899         .emit_ib = vcn_v2_0_enc_ring_emit_ib,
900         .emit_fence = vcn_v2_0_enc_ring_emit_fence,
901         .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,
902         .test_ring = amdgpu_vcn_enc_ring_test_ring,
903         .test_ib = amdgpu_vcn_unified_ring_test_ib,
904         .insert_nop = amdgpu_ring_insert_nop,
905         .insert_end = vcn_v2_0_enc_ring_insert_end,
906         .pad_ib = amdgpu_ring_generic_pad_ib,
907         .begin_use = amdgpu_vcn_ring_begin_use,
908         .end_use = amdgpu_vcn_ring_end_use,
909         .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
910         .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
911         .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
912 };
913
914 /**
915  * vcn_v5_0_1_set_unified_ring_funcs - set unified ring functions
916  *
917  * @adev: amdgpu_device pointer
918  *
919  * Set unified ring functions
920  */
921 static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev)
922 {
923         int i, vcn_inst;
924
925         for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
926                 adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v5_0_1_unified_ring_vm_funcs;
927                 adev->vcn.inst[i].ring_enc[0].me = i;
928                 vcn_inst = GET_INST(VCN, i);
929                 adev->vcn.inst[i].aid_id = vcn_inst / adev->vcn.num_inst_per_aid;
930         }
931 }
932
933 /**
934  * vcn_v5_0_1_is_idle - check VCN block is idle
935  *
936  * @handle: amdgpu_device pointer
937  *
938  * Check whether VCN block is idle
939  */
940 static bool vcn_v5_0_1_is_idle(void *handle)
941 {
942         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
943         int i, ret = 1;
944
945         for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
946                 ret &= (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) == UVD_STATUS__IDLE);
947
948         return ret;
949 }
950
951 /**
952  * vcn_v5_0_1_wait_for_idle - wait for VCN block idle
953  *
954  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
955  *
956  * Wait for VCN block idle
957  */
958 static int vcn_v5_0_1_wait_for_idle(struct amdgpu_ip_block *ip_block)
959 {
960         struct amdgpu_device *adev = ip_block->adev;
961         int i, ret = 0;
962
963         for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
964                 ret = SOC15_WAIT_ON_RREG(VCN, GET_INST(VCN, i), regUVD_STATUS, UVD_STATUS__IDLE,
965                         UVD_STATUS__IDLE);
966                 if (ret)
967                         return ret;
968         }
969
970         return ret;
971 }
972
973 /**
974  * vcn_v5_0_1_set_clockgating_state - set VCN block clockgating state
975  *
976  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
977  * @state: clock gating state
978  *
979  * Set VCN block clockgating state
980  */
981 static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
982                                             enum amd_clockgating_state state)
983 {
984         struct amdgpu_device *adev = ip_block->adev;
985         bool enable = state == AMD_CG_STATE_GATE;
986         int i;
987
988         for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
989                 if (enable) {
990                         if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE)
991                                 return -EBUSY;
992                         vcn_v5_0_1_enable_clock_gating(adev, i);
993                 } else {
994                         vcn_v5_0_1_disable_clock_gating(adev, i);
995                 }
996         }
997
998         return 0;
999 }
1000
1001 /**
1002  * vcn_v5_0_1_set_powergating_state - set VCN block powergating state
1003  *
1004  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
1005  * @state: power gating state
1006  *
1007  * Set VCN block powergating state
1008  */
1009 static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
1010                                             enum amd_powergating_state state)
1011 {
1012         struct amdgpu_device *adev = ip_block->adev;
1013         int ret;
1014
1015         if (state == adev->vcn.cur_state)
1016                 return 0;
1017
1018         if (state == AMD_PG_STATE_GATE)
1019                 ret = vcn_v5_0_1_stop(adev);
1020         else
1021                 ret = vcn_v5_0_1_start(adev);
1022
1023         if (!ret)
1024                 adev->vcn.cur_state = state;
1025
1026         return ret;
1027 }
1028
1029 /**
1030  * vcn_v5_0_1_process_interrupt - process VCN block interrupt
1031  *
1032  * @adev: amdgpu_device pointer
1033  * @source: interrupt sources
1034  * @entry: interrupt entry from clients and sources
1035  *
1036  * Process VCN block interrupt
1037  */
1038 static int vcn_v5_0_1_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
1039         struct amdgpu_iv_entry *entry)
1040 {
1041         uint32_t i, inst;
1042
1043         i = node_id_to_phys_map[entry->node_id];
1044
1045         DRM_DEV_DEBUG(adev->dev, "IH: VCN TRAP\n");
1046
1047         for (inst = 0; inst < adev->vcn.num_vcn_inst; ++inst)
1048                 if (adev->vcn.inst[inst].aid_id == i)
1049                         break;
1050         if (inst >= adev->vcn.num_vcn_inst) {
1051                 dev_WARN_ONCE(adev->dev, 1,
1052                                 "Interrupt received for unknown VCN instance %d",
1053                                 entry->node_id);
1054                 return 0;
1055         }
1056
1057         switch (entry->src_id) {
1058         case VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
1059                 amdgpu_fence_process(&adev->vcn.inst[inst].ring_enc[0]);
1060                 break;
1061         default:
1062                 DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
1063                           entry->src_id, entry->src_data[0]);
1064                 break;
1065         }
1066
1067         return 0;
1068 }
1069
1070 static const struct amdgpu_irq_src_funcs vcn_v5_0_1_irq_funcs = {
1071         .process = vcn_v5_0_1_process_interrupt,
1072 };
1073
1074 /**
1075  * vcn_v5_0_1_set_irq_funcs - set VCN block interrupt irq functions
1076  *
1077  * @adev: amdgpu_device pointer
1078  *
1079  * Set VCN block interrupt irq functions
1080  */
1081 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev)
1082 {
1083         int i;
1084
1085         for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
1086                 adev->vcn.inst->irq.num_types++;
1087         adev->vcn.inst->irq.funcs = &vcn_v5_0_1_irq_funcs;
1088 }
1089
1090 static const struct amd_ip_funcs vcn_v5_0_1_ip_funcs = {
1091         .name = "vcn_v5_0_1",
1092         .early_init = vcn_v5_0_1_early_init,
1093         .late_init = NULL,
1094         .sw_init = vcn_v5_0_1_sw_init,
1095         .sw_fini = vcn_v5_0_1_sw_fini,
1096         .hw_init = vcn_v5_0_1_hw_init,
1097         .hw_fini = vcn_v5_0_1_hw_fini,
1098         .suspend = vcn_v5_0_1_suspend,
1099         .resume = vcn_v5_0_1_resume,
1100         .is_idle = vcn_v5_0_1_is_idle,
1101         .wait_for_idle = vcn_v5_0_1_wait_for_idle,
1102         .check_soft_reset = NULL,
1103         .pre_soft_reset = NULL,
1104         .soft_reset = NULL,
1105         .post_soft_reset = NULL,
1106         .set_clockgating_state = vcn_v5_0_1_set_clockgating_state,
1107         .set_powergating_state = vcn_v5_0_1_set_powergating_state,
1108         .dump_ip_state = vcn_v5_0_0_dump_ip_state,
1109         .print_ip_state = vcn_v5_0_0_print_ip_state,
1110 };
1111
1112 const struct amdgpu_ip_block_version vcn_v5_0_1_ip_block = {
1113         .type = AMD_IP_BLOCK_TYPE_VCN,
1114         .major = 5,
1115         .minor = 0,
1116         .rev = 1,
1117         .funcs = &vcn_v5_0_1_ip_funcs,
1118 };
This page took 0.094895 seconds and 4 git commands to generate.