1 | /* |
2 | * Copyright 2023 Advanced Micro Devices, Inc. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice shall be included in |
12 | * all copies or substantial portions of the Software. |
13 | * |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * |
22 | */ |
23 | |
24 | #include "amdgpu.h" |
25 | #include "amdgpu_jpeg.h" |
26 | #include "amdgpu_pm.h" |
27 | #include "soc15.h" |
28 | #include "soc15d.h" |
29 | #include "jpeg_v2_0.h" |
30 | #include "jpeg_v4_0_5.h" |
31 | #include "mmsch_v4_0.h" |
32 | |
33 | #include "vcn/vcn_4_0_5_offset.h" |
34 | #include "vcn/vcn_4_0_5_sh_mask.h" |
35 | #include "ivsrcid/vcn/irqsrcs_vcn_4_0.h" |
36 | |
37 | #define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL |
38 | #define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX |
39 | #define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA |
40 | #define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX |
41 | |
42 | #define regUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f |
43 | #define regJPEG_DEC_GFX10_ADDR_CONFIG_INTERNAL_OFFSET 0x4026 |
44 | #define regJPEG_SYS_INT_EN_INTERNAL_OFFSET 0x4141 |
45 | #define regJPEG_CGC_CTRL_INTERNAL_OFFSET 0x4161 |
46 | #define regJPEG_CGC_GATE_INTERNAL_OFFSET 0x4160 |
47 | #define regUVD_NO_OP_INTERNAL_OFFSET 0x0029 |
48 | |
49 | static const struct amdgpu_hwip_reg_entry jpeg_reg_list_4_0_5[] = { |
50 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_POWER_STATUS), |
51 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_INT_STAT), |
52 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_RPTR), |
53 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_WPTR), |
54 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_CNTL), |
55 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_SIZE), |
56 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_STATUS), |
57 | SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_ADDR_MODE), |
58 | SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG), |
59 | SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_Y_GFX10_TILING_SURFACE), |
60 | SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_UV_GFX10_TILING_SURFACE), |
61 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_PITCH), |
62 | SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_UV_PITCH), |
63 | }; |
64 | |
65 | static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev); |
66 | static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev); |
67 | static int jpeg_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, |
68 | enum amd_powergating_state state); |
69 | static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring); |
70 | |
71 | static int amdgpu_ih_clientid_jpeg[] = { |
72 | SOC15_IH_CLIENTID_VCN, |
73 | SOC15_IH_CLIENTID_VCN1 |
74 | }; |
75 | |
76 | |
77 | |
78 | /** |
79 | * jpeg_v4_0_5_early_init - set function pointers |
80 | * |
81 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
82 | * |
83 | * Set ring and irq function pointers |
84 | */ |
85 | static int jpeg_v4_0_5_early_init(struct amdgpu_ip_block *ip_block) |
86 | { |
87 | struct amdgpu_device *adev = ip_block->adev; |
88 | |
89 | switch (amdgpu_ip_version(adev, ip: UVD_HWIP, inst: 0)) { |
90 | case IP_VERSION(4, 0, 5): |
91 | adev->jpeg.num_jpeg_inst = 1; |
92 | break; |
93 | case IP_VERSION(4, 0, 6): |
94 | adev->jpeg.num_jpeg_inst = 2; |
95 | break; |
96 | default: |
97 | DRM_DEV_ERROR(adev->dev, |
98 | "Failed to init vcn ip block(UVD_HWIP:0x%x)\n" , |
99 | amdgpu_ip_version(adev, UVD_HWIP, 0)); |
100 | return -EINVAL; |
101 | } |
102 | |
103 | adev->jpeg.num_jpeg_rings = 1; |
104 | |
105 | jpeg_v4_0_5_set_dec_ring_funcs(adev); |
106 | jpeg_v4_0_5_set_irq_funcs(adev); |
107 | |
108 | return 0; |
109 | } |
110 | |
111 | /** |
112 | * jpeg_v4_0_5_sw_init - sw init for JPEG block |
113 | * |
114 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
115 | * |
116 | * Load firmware and sw initialization |
117 | */ |
118 | static int jpeg_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block) |
119 | { |
120 | struct amdgpu_device *adev = ip_block->adev; |
121 | struct amdgpu_ring *ring; |
122 | int r, i; |
123 | |
124 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
125 | if (adev->jpeg.harvest_config & (1 << i)) |
126 | continue; |
127 | |
128 | /* JPEG TRAP */ |
129 | r = amdgpu_irq_add_id(adev, client_id: amdgpu_ih_clientid_jpeg[i], |
130 | VCN_4_0__SRCID__JPEG_DECODE, source: &adev->jpeg.inst[i].irq); |
131 | if (r) |
132 | return r; |
133 | |
134 | /* JPEG DJPEG POISON EVENT */ |
135 | r = amdgpu_irq_add_id(adev, client_id: amdgpu_ih_clientid_jpeg[i], |
136 | VCN_4_0__SRCID_DJPEG0_POISON, source: &adev->jpeg.inst[i].irq); |
137 | if (r) |
138 | return r; |
139 | |
140 | /* JPEG EJPEG POISON EVENT */ |
141 | r = amdgpu_irq_add_id(adev, client_id: amdgpu_ih_clientid_jpeg[i], |
142 | VCN_4_0__SRCID_EJPEG0_POISON, source: &adev->jpeg.inst[i].irq); |
143 | if (r) |
144 | return r; |
145 | } |
146 | |
147 | r = amdgpu_jpeg_sw_init(adev); |
148 | if (r) |
149 | return r; |
150 | |
151 | r = amdgpu_jpeg_resume(adev); |
152 | if (r) |
153 | return r; |
154 | |
155 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
156 | if (adev->jpeg.harvest_config & (1 << i)) |
157 | continue; |
158 | |
159 | ring = adev->jpeg.inst[i].ring_dec; |
160 | ring->use_doorbell = true; |
161 | ring->vm_hub = AMDGPU_MMHUB0(0); |
162 | ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i; |
163 | sprintf(buf: ring->name, fmt: "jpeg_dec_%d" , i); |
164 | r = amdgpu_ring_init(adev, ring, max_dw: 512, irq_src: &adev->jpeg.inst[i].irq, |
165 | irq_type: 0, hw_prio: AMDGPU_RING_PRIO_DEFAULT, NULL); |
166 | if (r) |
167 | return r; |
168 | |
169 | adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET; |
170 | adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, regUVD_JPEG_PITCH); |
171 | } |
172 | |
173 | r = amdgpu_jpeg_reg_dump_init(adev, reg: jpeg_reg_list_4_0_5, ARRAY_SIZE(jpeg_reg_list_4_0_5)); |
174 | if (r) |
175 | return r; |
176 | |
177 | /* TODO: Add queue reset mask when FW fully supports it */ |
178 | adev->jpeg.supported_reset = |
179 | amdgpu_get_soft_full_reset_mask(ring: &adev->jpeg.inst[0].ring_dec[0]); |
180 | r = amdgpu_jpeg_sysfs_reset_mask_init(adev); |
181 | if (r) |
182 | return r; |
183 | |
184 | return 0; |
185 | } |
186 | |
187 | /** |
188 | * jpeg_v4_0_5_sw_fini - sw fini for JPEG block |
189 | * |
190 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
191 | * |
192 | * JPEG suspend and free up sw allocation |
193 | */ |
194 | static int jpeg_v4_0_5_sw_fini(struct amdgpu_ip_block *ip_block) |
195 | { |
196 | struct amdgpu_device *adev = ip_block->adev; |
197 | int r; |
198 | |
199 | r = amdgpu_jpeg_suspend(adev); |
200 | if (r) |
201 | return r; |
202 | |
203 | amdgpu_jpeg_sysfs_reset_mask_fini(adev); |
204 | r = amdgpu_jpeg_sw_fini(adev); |
205 | |
206 | return r; |
207 | } |
208 | |
209 | /** |
210 | * jpeg_v4_0_5_hw_init - start and test JPEG block |
211 | * |
212 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
213 | * |
214 | */ |
215 | static int jpeg_v4_0_5_hw_init(struct amdgpu_ip_block *ip_block) |
216 | { |
217 | struct amdgpu_device *adev = ip_block->adev; |
218 | struct amdgpu_ring *ring; |
219 | int i, r = 0; |
220 | |
221 | // TODO: Enable ring test with DPG support |
222 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) { |
223 | return 0; |
224 | } |
225 | |
226 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
227 | if (adev->jpeg.harvest_config & (1 << i)) |
228 | continue; |
229 | |
230 | ring = adev->jpeg.inst[i].ring_dec; |
231 | r = amdgpu_ring_test_helper(ring); |
232 | if (r) |
233 | return r; |
234 | } |
235 | |
236 | return 0; |
237 | } |
238 | |
239 | /** |
240 | * jpeg_v4_0_5_hw_fini - stop the hardware block |
241 | * |
242 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
243 | * |
244 | * Stop the JPEG block, mark ring as not ready any more |
245 | */ |
246 | static int jpeg_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block) |
247 | { |
248 | struct amdgpu_device *adev = ip_block->adev; |
249 | int i; |
250 | |
251 | cancel_delayed_work_sync(dwork: &adev->jpeg.idle_work); |
252 | |
253 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
254 | if (adev->jpeg.harvest_config & (1 << i)) |
255 | continue; |
256 | |
257 | if (!amdgpu_sriov_vf(adev)) { |
258 | if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && |
259 | RREG32_SOC15(JPEG, i, regUVD_JRBC_STATUS)) |
260 | jpeg_v4_0_5_set_powergating_state(ip_block, state: AMD_PG_STATE_GATE); |
261 | } |
262 | } |
263 | return 0; |
264 | } |
265 | |
266 | /** |
267 | * jpeg_v4_0_5_suspend - suspend JPEG block |
268 | * |
269 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
270 | * |
271 | * HW fini and suspend JPEG block |
272 | */ |
273 | static int jpeg_v4_0_5_suspend(struct amdgpu_ip_block *ip_block) |
274 | { |
275 | int r; |
276 | |
277 | r = jpeg_v4_0_5_hw_fini(ip_block); |
278 | if (r) |
279 | return r; |
280 | |
281 | r = amdgpu_jpeg_suspend(adev: ip_block->adev); |
282 | |
283 | return r; |
284 | } |
285 | |
286 | /** |
287 | * jpeg_v4_0_5_resume - resume JPEG block |
288 | * |
289 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
290 | * |
291 | * Resume firmware and hw init JPEG block |
292 | */ |
293 | static int jpeg_v4_0_5_resume(struct amdgpu_ip_block *ip_block) |
294 | { |
295 | int r; |
296 | |
297 | r = amdgpu_jpeg_resume(adev: ip_block->adev); |
298 | if (r) |
299 | return r; |
300 | |
301 | r = jpeg_v4_0_5_hw_init(ip_block); |
302 | |
303 | return r; |
304 | } |
305 | |
306 | static void jpeg_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst) |
307 | { |
308 | uint32_t data = 0; |
309 | |
310 | data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL); |
311 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) { |
312 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
313 | data &= (~JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK); |
314 | } else { |
315 | data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
316 | } |
317 | |
318 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
319 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
320 | WREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL, data); |
321 | |
322 | data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE); |
323 | data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK |
324 | | JPEG_CGC_GATE__JPEG2_DEC_MASK |
325 | | JPEG_CGC_GATE__JMCIF_MASK |
326 | | JPEG_CGC_GATE__JRBBM_MASK); |
327 | WREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE, data); |
328 | } |
329 | |
330 | static void jpeg_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst) |
331 | { |
332 | uint32_t data = 0; |
333 | |
334 | data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL); |
335 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) { |
336 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
337 | data |= JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK; |
338 | } else { |
339 | data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
340 | } |
341 | |
342 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
343 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
344 | WREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL, data); |
345 | |
346 | data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE); |
347 | data |= (JPEG_CGC_GATE__JPEG_DEC_MASK |
348 | |JPEG_CGC_GATE__JPEG2_DEC_MASK |
349 | |JPEG_CGC_GATE__JMCIF_MASK |
350 | |JPEG_CGC_GATE__JRBBM_MASK); |
351 | WREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE, data); |
352 | } |
353 | |
354 | static void jpeg_engine_4_0_5_dpg_clock_gating_mode(struct amdgpu_device *adev, |
355 | int inst_idx, uint8_t indirect) |
356 | { |
357 | uint32_t data = 0; |
358 | |
359 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) |
360 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
361 | else |
362 | data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
363 | |
364 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
365 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
366 | WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_CGC_CTRL_INTERNAL_OFFSET, data, indirect); |
367 | |
368 | data = 0; |
369 | WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_CGC_GATE_INTERNAL_OFFSET, |
370 | data, indirect); |
371 | } |
372 | |
373 | static int jpeg_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst) |
374 | { |
375 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
376 | WREG32(SOC15_REG_OFFSET(JPEG, inst, regUVD_IPX_DLDO_CONFIG), |
377 | 1 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT); |
378 | SOC15_WAIT_ON_RREG(JPEG, inst, regUVD_IPX_DLDO_STATUS, |
379 | 0, UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK); |
380 | } |
381 | |
382 | /* disable anti hang mechanism */ |
383 | WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS), 0, |
384 | ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); |
385 | |
386 | /* keep the JPEG in static PG mode */ |
387 | WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS), 0, |
388 | ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK); |
389 | |
390 | return 0; |
391 | } |
392 | |
393 | static int jpeg_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst) |
394 | { |
395 | /* enable anti hang mechanism */ |
396 | WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS), |
397 | UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK, |
398 | ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); |
399 | |
400 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
401 | WREG32(SOC15_REG_OFFSET(JPEG, inst, regUVD_IPX_DLDO_CONFIG), |
402 | 2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT); |
403 | SOC15_WAIT_ON_RREG(JPEG, inst, regUVD_IPX_DLDO_STATUS, |
404 | 1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT, |
405 | UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK); |
406 | } |
407 | |
408 | return 0; |
409 | } |
410 | |
411 | /** |
412 | * jpeg_v4_0_5_start_dpg_mode - Jpeg start with dpg mode |
413 | * |
414 | * @adev: amdgpu_device pointer |
415 | * @inst_idx: instance number index |
416 | * @indirect: indirectly write sram |
417 | * |
418 | * Start JPEG block with dpg mode |
419 | */ |
420 | static void jpeg_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) |
421 | { |
422 | struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec; |
423 | uint32_t reg_data = 0; |
424 | |
425 | /* enable anti hang mechanism */ |
426 | reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS); |
427 | reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK; |
428 | reg_data |= 0x1; |
429 | WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data); |
430 | |
431 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
432 | WREG32(SOC15_REG_OFFSET(JPEG, inst_idx, regUVD_IPX_DLDO_CONFIG), |
433 | 2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT); |
434 | SOC15_WAIT_ON_RREG(JPEG, inst_idx, regUVD_IPX_DLDO_STATUS, |
435 | 1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT, |
436 | UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK); |
437 | } |
438 | |
439 | reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS); |
440 | reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK; |
441 | WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data); |
442 | |
443 | if (indirect) |
444 | adev->jpeg.inst[inst_idx].dpg_sram_curr_addr = |
445 | (uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr; |
446 | |
447 | jpeg_engine_4_0_5_dpg_clock_gating_mode(adev, inst_idx, indirect); |
448 | |
449 | /* MJPEG global tiling registers */ |
450 | WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_DEC_GFX10_ADDR_CONFIG_INTERNAL_OFFSET, |
451 | adev->gfx.config.gb_addr_config, indirect); |
452 | /* enable System Interrupt for JRBC */ |
453 | WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_SYS_INT_EN_INTERNAL_OFFSET, |
454 | JPEG_SYS_INT_EN__DJRBC_MASK, indirect); |
455 | |
456 | /* add nop to workaround PSP size check */ |
457 | WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regUVD_NO_OP_INTERNAL_OFFSET, 0, indirect); |
458 | |
459 | if (indirect) |
460 | amdgpu_jpeg_psp_update_sram(adev, inst_idx, ucode_id: 0); |
461 | |
462 | WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0); |
463 | WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); |
464 | WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, |
465 | lower_32_bits(ring->gpu_addr)); |
466 | WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, |
467 | upper_32_bits(ring->gpu_addr)); |
468 | WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0); |
469 | WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0); |
470 | WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L); |
471 | WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4); |
472 | ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR); |
473 | } |
474 | |
475 | /** |
476 | * jpeg_v4_0_5_stop_dpg_mode - Jpeg stop with dpg mode |
477 | * |
478 | * @adev: amdgpu_device pointer |
479 | * @inst_idx: instance number index |
480 | * |
481 | * Stop JPEG block with dpg mode |
482 | */ |
483 | static void jpeg_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) |
484 | { |
485 | uint32_t reg_data = 0; |
486 | |
487 | reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS); |
488 | reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK; |
489 | WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data); |
490 | |
491 | } |
492 | |
493 | /** |
494 | * jpeg_v4_0_5_start - start JPEG block |
495 | * |
496 | * @adev: amdgpu_device pointer |
497 | * |
498 | * Setup and start the JPEG block |
499 | */ |
500 | static int jpeg_v4_0_5_start(struct amdgpu_device *adev) |
501 | { |
502 | struct amdgpu_ring *ring; |
503 | int r, i; |
504 | |
505 | if (adev->pm.dpm_enabled) |
506 | amdgpu_dpm_enable_jpeg(adev, enable: true); |
507 | |
508 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
509 | if (adev->jpeg.harvest_config & (1 << i)) |
510 | continue; |
511 | |
512 | ring = adev->jpeg.inst[i].ring_dec; |
513 | /* doorbell programming is done for every playback */ |
514 | adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, |
515 | (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i); |
516 | |
517 | WREG32_SOC15(VCN, i, regVCN_JPEG_DB_CTRL, |
518 | ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | |
519 | VCN_JPEG_DB_CTRL__EN_MASK); |
520 | |
521 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) { |
522 | jpeg_v4_0_5_start_dpg_mode(adev, inst_idx: i, indirect: adev->jpeg.indirect_sram); |
523 | continue; |
524 | } |
525 | |
526 | /* disable power gating */ |
527 | r = jpeg_v4_0_5_disable_static_power_gating(adev, inst: i); |
528 | if (r) |
529 | return r; |
530 | |
531 | /* JPEG disable CGC */ |
532 | jpeg_v4_0_5_disable_clock_gating(adev, inst: i); |
533 | |
534 | /* MJPEG global tiling registers */ |
535 | WREG32_SOC15(JPEG, i, regJPEG_DEC_GFX10_ADDR_CONFIG, |
536 | adev->gfx.config.gb_addr_config); |
537 | |
538 | /* enable JMI channel */ |
539 | WREG32_P(SOC15_REG_OFFSET(JPEG, i, regUVD_JMI_CNTL), 0, |
540 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
541 | |
542 | /* enable System Interrupt for JRBC */ |
543 | WREG32_P(SOC15_REG_OFFSET(JPEG, i, regJPEG_SYS_INT_EN), |
544 | JPEG_SYS_INT_EN__DJRBC_MASK, |
545 | ~JPEG_SYS_INT_EN__DJRBC_MASK); |
546 | |
547 | WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_VMID, 0); |
548 | WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); |
549 | WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, |
550 | lower_32_bits(ring->gpu_addr)); |
551 | WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, |
552 | upper_32_bits(ring->gpu_addr)); |
553 | WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_RPTR, 0); |
554 | WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_WPTR, 0); |
555 | WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_CNTL, 0x00000002L); |
556 | WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_SIZE, ring->ring_size / 4); |
557 | ring->wptr = RREG32_SOC15(JPEG, i, regUVD_JRBC_RB_WPTR); |
558 | } |
559 | |
560 | return 0; |
561 | } |
562 | |
563 | /** |
564 | * jpeg_v4_0_5_stop - stop JPEG block |
565 | * |
566 | * @adev: amdgpu_device pointer |
567 | * |
568 | * stop the JPEG block |
569 | */ |
570 | static int jpeg_v4_0_5_stop(struct amdgpu_device *adev) |
571 | { |
572 | int r, i; |
573 | |
574 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
575 | if (adev->jpeg.harvest_config & (1 << i)) |
576 | continue; |
577 | |
578 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) { |
579 | jpeg_v4_0_5_stop_dpg_mode(adev, inst_idx: i); |
580 | continue; |
581 | } |
582 | |
583 | /* reset JMI */ |
584 | WREG32_P(SOC15_REG_OFFSET(JPEG, i, regUVD_JMI_CNTL), |
585 | UVD_JMI_CNTL__SOFT_RESET_MASK, |
586 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
587 | |
588 | jpeg_v4_0_5_enable_clock_gating(adev, inst: i); |
589 | |
590 | /* enable power gating */ |
591 | r = jpeg_v4_0_5_enable_static_power_gating(adev, inst: i); |
592 | if (r) |
593 | return r; |
594 | } |
595 | if (adev->pm.dpm_enabled) |
596 | amdgpu_dpm_enable_jpeg(adev, enable: false); |
597 | |
598 | return 0; |
599 | } |
600 | |
601 | /** |
602 | * jpeg_v4_0_5_dec_ring_get_rptr - get read pointer |
603 | * |
604 | * @ring: amdgpu_ring pointer |
605 | * |
606 | * Returns the current hardware read pointer |
607 | */ |
608 | static uint64_t jpeg_v4_0_5_dec_ring_get_rptr(struct amdgpu_ring *ring) |
609 | { |
610 | struct amdgpu_device *adev = ring->adev; |
611 | |
612 | return RREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_RPTR); |
613 | } |
614 | |
615 | /** |
616 | * jpeg_v4_0_5_dec_ring_get_wptr - get write pointer |
617 | * |
618 | * @ring: amdgpu_ring pointer |
619 | * |
620 | * Returns the current hardware write pointer |
621 | */ |
622 | static uint64_t jpeg_v4_0_5_dec_ring_get_wptr(struct amdgpu_ring *ring) |
623 | { |
624 | struct amdgpu_device *adev = ring->adev; |
625 | |
626 | if (ring->use_doorbell) |
627 | return *ring->wptr_cpu_addr; |
628 | else |
629 | return RREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_WPTR); |
630 | } |
631 | |
632 | /** |
633 | * jpeg_v4_0_5_dec_ring_set_wptr - set write pointer |
634 | * |
635 | * @ring: amdgpu_ring pointer |
636 | * |
637 | * Commits the write pointer to the hardware |
638 | */ |
639 | static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring) |
640 | { |
641 | struct amdgpu_device *adev = ring->adev; |
642 | |
643 | if (ring->use_doorbell) { |
644 | *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); |
645 | WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); |
646 | } else { |
647 | WREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr)); |
648 | } |
649 | } |
650 | |
651 | static bool jpeg_v4_0_5_is_idle(struct amdgpu_ip_block *ip_block) |
652 | { |
653 | struct amdgpu_device *adev = ip_block->adev; |
654 | int i, ret = 1; |
655 | |
656 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
657 | if (adev->jpeg.harvest_config & (1 << i)) |
658 | continue; |
659 | |
660 | ret &= (((RREG32_SOC15(JPEG, i, regUVD_JRBC_STATUS) & |
661 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK) == |
662 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK)); |
663 | } |
664 | return ret; |
665 | } |
666 | |
667 | static int jpeg_v4_0_5_wait_for_idle(struct amdgpu_ip_block *ip_block) |
668 | { |
669 | struct amdgpu_device *adev = ip_block->adev; |
670 | int i; |
671 | |
672 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
673 | if (adev->jpeg.harvest_config & (1 << i)) |
674 | continue; |
675 | |
676 | return SOC15_WAIT_ON_RREG(JPEG, i, regUVD_JRBC_STATUS, |
677 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK, |
678 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK); |
679 | } |
680 | |
681 | return 0; |
682 | } |
683 | |
684 | static int jpeg_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block, |
685 | enum amd_clockgating_state state) |
686 | { |
687 | struct amdgpu_device *adev = ip_block->adev; |
688 | bool enable = (state == AMD_CG_STATE_GATE) ? true : false; |
689 | int i; |
690 | |
691 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
692 | if (adev->jpeg.harvest_config & (1 << i)) |
693 | continue; |
694 | |
695 | if (enable) { |
696 | if (!jpeg_v4_0_5_is_idle(ip_block)) |
697 | return -EBUSY; |
698 | |
699 | jpeg_v4_0_5_enable_clock_gating(adev, inst: i); |
700 | } else { |
701 | jpeg_v4_0_5_disable_clock_gating(adev, inst: i); |
702 | } |
703 | } |
704 | |
705 | return 0; |
706 | } |
707 | |
708 | static int jpeg_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block, |
709 | enum amd_powergating_state state) |
710 | { |
711 | struct amdgpu_device *adev = ip_block->adev; |
712 | int ret; |
713 | |
714 | if (amdgpu_sriov_vf(adev)) { |
715 | adev->jpeg.cur_state = AMD_PG_STATE_UNGATE; |
716 | return 0; |
717 | } |
718 | |
719 | if (state == adev->jpeg.cur_state) |
720 | return 0; |
721 | |
722 | if (state == AMD_PG_STATE_GATE) |
723 | ret = jpeg_v4_0_5_stop(adev); |
724 | else |
725 | ret = jpeg_v4_0_5_start(adev); |
726 | |
727 | if (!ret) |
728 | adev->jpeg.cur_state = state; |
729 | |
730 | return ret; |
731 | } |
732 | |
733 | static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev, |
734 | struct amdgpu_irq_src *source, |
735 | struct amdgpu_iv_entry *entry) |
736 | { |
737 | uint32_t ip_instance; |
738 | |
739 | DRM_DEBUG("IH: JPEG TRAP\n" ); |
740 | |
741 | switch (entry->client_id) { |
742 | case SOC15_IH_CLIENTID_VCN: |
743 | ip_instance = 0; |
744 | break; |
745 | case SOC15_IH_CLIENTID_VCN1: |
746 | ip_instance = 1; |
747 | break; |
748 | default: |
749 | DRM_ERROR("Unhandled client id: %d\n" , entry->client_id); |
750 | return 0; |
751 | } |
752 | |
753 | switch (entry->src_id) { |
754 | case VCN_4_0__SRCID__JPEG_DECODE: |
755 | amdgpu_fence_process(ring: adev->jpeg.inst[ip_instance].ring_dec); |
756 | break; |
757 | case VCN_4_0__SRCID_DJPEG0_POISON: |
758 | case VCN_4_0__SRCID_EJPEG0_POISON: |
759 | amdgpu_jpeg_process_poison_irq(adev, source, entry); |
760 | break; |
761 | default: |
762 | DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n" , |
763 | entry->src_id, entry->src_data[0]); |
764 | break; |
765 | } |
766 | |
767 | return 0; |
768 | } |
769 | |
770 | static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = { |
771 | .name = "jpeg_v4_0_5" , |
772 | .early_init = jpeg_v4_0_5_early_init, |
773 | .sw_init = jpeg_v4_0_5_sw_init, |
774 | .sw_fini = jpeg_v4_0_5_sw_fini, |
775 | .hw_init = jpeg_v4_0_5_hw_init, |
776 | .hw_fini = jpeg_v4_0_5_hw_fini, |
777 | .suspend = jpeg_v4_0_5_suspend, |
778 | .resume = jpeg_v4_0_5_resume, |
779 | .is_idle = jpeg_v4_0_5_is_idle, |
780 | .wait_for_idle = jpeg_v4_0_5_wait_for_idle, |
781 | .set_clockgating_state = jpeg_v4_0_5_set_clockgating_state, |
782 | .set_powergating_state = jpeg_v4_0_5_set_powergating_state, |
783 | .dump_ip_state = amdgpu_jpeg_dump_ip_state, |
784 | .print_ip_state = amdgpu_jpeg_print_ip_state, |
785 | }; |
786 | |
787 | static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = { |
788 | .type = AMDGPU_RING_TYPE_VCN_JPEG, |
789 | .align_mask = 0xf, |
790 | .get_rptr = jpeg_v4_0_5_dec_ring_get_rptr, |
791 | .get_wptr = jpeg_v4_0_5_dec_ring_get_wptr, |
792 | .set_wptr = jpeg_v4_0_5_dec_ring_set_wptr, |
793 | .parse_cs = jpeg_v2_dec_ring_parse_cs, |
794 | .emit_frame_size = |
795 | SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + |
796 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + |
797 | 8 + /* jpeg_v4_0_5_dec_ring_emit_vm_flush */ |
798 | 18 + 18 + /* jpeg_v4_0_5_dec_ring_emit_fence x2 vm fence */ |
799 | 8 + 16, |
800 | .emit_ib_size = 22, /* jpeg_v4_0_5_dec_ring_emit_ib */ |
801 | .emit_ib = jpeg_v2_0_dec_ring_emit_ib, |
802 | .emit_fence = jpeg_v2_0_dec_ring_emit_fence, |
803 | .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush, |
804 | .test_ring = amdgpu_jpeg_dec_ring_test_ring, |
805 | .test_ib = amdgpu_jpeg_dec_ring_test_ib, |
806 | .insert_nop = jpeg_v2_0_dec_ring_nop, |
807 | .insert_start = jpeg_v2_0_dec_ring_insert_start, |
808 | .insert_end = jpeg_v2_0_dec_ring_insert_end, |
809 | .pad_ib = amdgpu_ring_generic_pad_ib, |
810 | .begin_use = amdgpu_jpeg_ring_begin_use, |
811 | .end_use = amdgpu_jpeg_ring_end_use, |
812 | .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg, |
813 | .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait, |
814 | .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, |
815 | }; |
816 | |
817 | static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev) |
818 | { |
819 | int i; |
820 | |
821 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
822 | if (adev->jpeg.harvest_config & (1 << i)) |
823 | continue; |
824 | |
825 | adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v4_0_5_dec_ring_vm_funcs; |
826 | adev->jpeg.inst[i].ring_dec->me = i; |
827 | } |
828 | } |
829 | |
830 | static const struct amdgpu_irq_src_funcs jpeg_v4_0_5_irq_funcs = { |
831 | .process = jpeg_v4_0_5_process_interrupt, |
832 | }; |
833 | |
834 | static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev) |
835 | { |
836 | int i; |
837 | |
838 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
839 | if (adev->jpeg.harvest_config & (1 << i)) |
840 | continue; |
841 | |
842 | adev->jpeg.inst[i].irq.num_types = 1; |
843 | adev->jpeg.inst[i].irq.funcs = &jpeg_v4_0_5_irq_funcs; |
844 | } |
845 | } |
846 | |
847 | const struct amdgpu_ip_block_version jpeg_v4_0_5_ip_block = { |
848 | .type = AMD_IP_BLOCK_TYPE_JPEG, |
849 | .major = 4, |
850 | .minor = 0, |
851 | .rev = 5, |
852 | .funcs = &jpeg_v4_0_5_ip_funcs, |
853 | }; |
854 | |
855 | |