1 | /* |
2 | * Copyright 2019 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 | |
31 | #include "vcn/vcn_2_0_0_offset.h" |
32 | #include "vcn/vcn_2_0_0_sh_mask.h" |
33 | #include "ivsrcid/vcn/irqsrcs_vcn_2_0.h" |
34 | |
35 | static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev); |
36 | static void jpeg_v2_0_set_irq_funcs(struct amdgpu_device *adev); |
37 | static int jpeg_v2_0_set_powergating_state(void *handle, |
38 | enum amd_powergating_state state); |
39 | |
40 | /** |
41 | * jpeg_v2_0_early_init - set function pointers |
42 | * |
43 | * @handle: amdgpu_device pointer |
44 | * |
45 | * Set ring and irq function pointers |
46 | */ |
47 | static int jpeg_v2_0_early_init(void *handle) |
48 | { |
49 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
50 | |
51 | adev->jpeg.num_jpeg_inst = 1; |
52 | adev->jpeg.num_jpeg_rings = 1; |
53 | |
54 | jpeg_v2_0_set_dec_ring_funcs(adev); |
55 | jpeg_v2_0_set_irq_funcs(adev); |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | /** |
61 | * jpeg_v2_0_sw_init - sw init for JPEG block |
62 | * |
63 | * @handle: amdgpu_device pointer |
64 | * |
65 | * Load firmware and sw initialization |
66 | */ |
67 | static int jpeg_v2_0_sw_init(void *handle) |
68 | { |
69 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
70 | struct amdgpu_ring *ring; |
71 | int r; |
72 | |
73 | /* JPEG TRAP */ |
74 | r = amdgpu_irq_add_id(adev, client_id: SOC15_IH_CLIENTID_VCN, |
75 | VCN_2_0__SRCID__JPEG_DECODE, source: &adev->jpeg.inst->irq); |
76 | if (r) |
77 | return r; |
78 | |
79 | r = amdgpu_jpeg_sw_init(adev); |
80 | if (r) |
81 | return r; |
82 | |
83 | r = amdgpu_jpeg_resume(adev); |
84 | if (r) |
85 | return r; |
86 | |
87 | ring = adev->jpeg.inst->ring_dec; |
88 | ring->use_doorbell = true; |
89 | ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1; |
90 | ring->vm_hub = AMDGPU_MMHUB0(0); |
91 | sprintf(buf: ring->name, fmt: "jpeg_dec" ); |
92 | r = amdgpu_ring_init(adev, ring, max_dw: 512, irq_src: &adev->jpeg.inst->irq, |
93 | irq_type: 0, hw_prio: AMDGPU_RING_PRIO_DEFAULT, NULL); |
94 | if (r) |
95 | return r; |
96 | |
97 | adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET; |
98 | adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH); |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | /** |
104 | * jpeg_v2_0_sw_fini - sw fini for JPEG block |
105 | * |
106 | * @handle: amdgpu_device pointer |
107 | * |
108 | * JPEG suspend and free up sw allocation |
109 | */ |
110 | static int jpeg_v2_0_sw_fini(void *handle) |
111 | { |
112 | int r; |
113 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
114 | |
115 | r = amdgpu_jpeg_suspend(adev); |
116 | if (r) |
117 | return r; |
118 | |
119 | r = amdgpu_jpeg_sw_fini(adev); |
120 | |
121 | return r; |
122 | } |
123 | |
124 | /** |
125 | * jpeg_v2_0_hw_init - start and test JPEG block |
126 | * |
127 | * @handle: amdgpu_device pointer |
128 | * |
129 | */ |
130 | static int jpeg_v2_0_hw_init(void *handle) |
131 | { |
132 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
133 | struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec; |
134 | int r; |
135 | |
136 | adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, |
137 | (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); |
138 | |
139 | r = amdgpu_ring_test_helper(ring); |
140 | if (!r) |
141 | DRM_INFO("JPEG decode initialized successfully.\n" ); |
142 | |
143 | return r; |
144 | } |
145 | |
146 | /** |
147 | * jpeg_v2_0_hw_fini - stop the hardware block |
148 | * |
149 | * @handle: amdgpu_device pointer |
150 | * |
151 | * Stop the JPEG block, mark ring as not ready any more |
152 | */ |
153 | static int jpeg_v2_0_hw_fini(void *handle) |
154 | { |
155 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
156 | |
157 | cancel_delayed_work_sync(dwork: &adev->vcn.idle_work); |
158 | |
159 | if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && |
160 | RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS)) |
161 | jpeg_v2_0_set_powergating_state(handle: adev, state: AMD_PG_STATE_GATE); |
162 | |
163 | return 0; |
164 | } |
165 | |
166 | /** |
167 | * jpeg_v2_0_suspend - suspend JPEG block |
168 | * |
169 | * @handle: amdgpu_device pointer |
170 | * |
171 | * HW fini and suspend JPEG block |
172 | */ |
173 | static int jpeg_v2_0_suspend(void *handle) |
174 | { |
175 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
176 | int r; |
177 | |
178 | r = jpeg_v2_0_hw_fini(handle: adev); |
179 | if (r) |
180 | return r; |
181 | |
182 | r = amdgpu_jpeg_suspend(adev); |
183 | |
184 | return r; |
185 | } |
186 | |
187 | /** |
188 | * jpeg_v2_0_resume - resume JPEG block |
189 | * |
190 | * @handle: amdgpu_device pointer |
191 | * |
192 | * Resume firmware and hw init JPEG block |
193 | */ |
194 | static int jpeg_v2_0_resume(void *handle) |
195 | { |
196 | int r; |
197 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
198 | |
199 | r = amdgpu_jpeg_resume(adev); |
200 | if (r) |
201 | return r; |
202 | |
203 | r = jpeg_v2_0_hw_init(handle: adev); |
204 | |
205 | return r; |
206 | } |
207 | |
208 | static int jpeg_v2_0_disable_power_gating(struct amdgpu_device *adev) |
209 | { |
210 | uint32_t data; |
211 | int r = 0; |
212 | |
213 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
214 | data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT; |
215 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data); |
216 | |
217 | r = SOC15_WAIT_ON_RREG(JPEG, 0, |
218 | mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON, |
219 | UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK); |
220 | |
221 | if (r) { |
222 | DRM_ERROR("amdgpu: JPEG disable power gating failed\n" ); |
223 | return r; |
224 | } |
225 | } |
226 | |
227 | /* Removing the anti hang mechanism to indicate the UVDJ tile is ON */ |
228 | data = RREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS)) & ~0x1; |
229 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), data); |
230 | |
231 | return 0; |
232 | } |
233 | |
234 | static int jpeg_v2_0_enable_power_gating(struct amdgpu_device *adev) |
235 | { |
236 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
237 | uint32_t data; |
238 | int r = 0; |
239 | |
240 | data = RREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS)); |
241 | data &= ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK; |
242 | data |= 0x1; //UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_TILES_OFF; |
243 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), data); |
244 | |
245 | data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT; |
246 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data); |
247 | |
248 | r = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_PGFSM_STATUS, |
249 | (2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT), |
250 | UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK); |
251 | |
252 | if (r) { |
253 | DRM_ERROR("amdgpu: JPEG enable power gating failed\n" ); |
254 | return r; |
255 | } |
256 | } |
257 | |
258 | return 0; |
259 | } |
260 | |
261 | static void jpeg_v2_0_disable_clock_gating(struct amdgpu_device *adev) |
262 | { |
263 | uint32_t data; |
264 | |
265 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL); |
266 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) |
267 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
268 | else |
269 | data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
270 | |
271 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
272 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
273 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data); |
274 | |
275 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE); |
276 | data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK |
277 | | JPEG_CGC_GATE__JPEG2_DEC_MASK |
278 | | JPEG_CGC_GATE__JPEG_ENC_MASK |
279 | | JPEG_CGC_GATE__JMCIF_MASK |
280 | | JPEG_CGC_GATE__JRBBM_MASK); |
281 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data); |
282 | } |
283 | |
284 | static void jpeg_v2_0_enable_clock_gating(struct amdgpu_device *adev) |
285 | { |
286 | uint32_t data; |
287 | |
288 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL); |
289 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) |
290 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
291 | else |
292 | data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
293 | |
294 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
295 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
296 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data); |
297 | |
298 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE); |
299 | data |= (JPEG_CGC_GATE__JPEG_DEC_MASK |
300 | |JPEG_CGC_GATE__JPEG2_DEC_MASK |
301 | |JPEG_CGC_GATE__JPEG_ENC_MASK |
302 | |JPEG_CGC_GATE__JMCIF_MASK |
303 | |JPEG_CGC_GATE__JRBBM_MASK); |
304 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data); |
305 | } |
306 | |
307 | /** |
308 | * jpeg_v2_0_start - start JPEG block |
309 | * |
310 | * @adev: amdgpu_device pointer |
311 | * |
312 | * Setup and start the JPEG block |
313 | */ |
314 | static int jpeg_v2_0_start(struct amdgpu_device *adev) |
315 | { |
316 | struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec; |
317 | int r; |
318 | |
319 | if (adev->pm.dpm_enabled) |
320 | amdgpu_dpm_enable_jpeg(adev, enable: true); |
321 | |
322 | /* disable power gating */ |
323 | r = jpeg_v2_0_disable_power_gating(adev); |
324 | if (r) |
325 | return r; |
326 | |
327 | /* JPEG disable CGC */ |
328 | jpeg_v2_0_disable_clock_gating(adev); |
329 | |
330 | WREG32_SOC15(JPEG, 0, mmJPEG_DEC_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config); |
331 | |
332 | /* enable JMI channel */ |
333 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), 0, |
334 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
335 | |
336 | /* enable System Interrupt for JRBC */ |
337 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmJPEG_SYS_INT_EN), |
338 | JPEG_SYS_INT_EN__DJRBC_MASK, |
339 | ~JPEG_SYS_INT_EN__DJRBC_MASK); |
340 | |
341 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0); |
342 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); |
343 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, |
344 | lower_32_bits(ring->gpu_addr)); |
345 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, |
346 | upper_32_bits(ring->gpu_addr)); |
347 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0); |
348 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0); |
349 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L); |
350 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4); |
351 | ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); |
352 | |
353 | return 0; |
354 | } |
355 | |
356 | /** |
357 | * jpeg_v2_0_stop - stop JPEG block |
358 | * |
359 | * @adev: amdgpu_device pointer |
360 | * |
361 | * stop the JPEG block |
362 | */ |
363 | static int jpeg_v2_0_stop(struct amdgpu_device *adev) |
364 | { |
365 | int r; |
366 | |
367 | /* reset JMI */ |
368 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), |
369 | UVD_JMI_CNTL__SOFT_RESET_MASK, |
370 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
371 | |
372 | /* enable JPEG CGC */ |
373 | jpeg_v2_0_enable_clock_gating(adev); |
374 | |
375 | /* enable power gating */ |
376 | r = jpeg_v2_0_enable_power_gating(adev); |
377 | if (r) |
378 | return r; |
379 | |
380 | if (adev->pm.dpm_enabled) |
381 | amdgpu_dpm_enable_jpeg(adev, enable: false); |
382 | |
383 | return 0; |
384 | } |
385 | |
386 | /** |
387 | * jpeg_v2_0_dec_ring_get_rptr - get read pointer |
388 | * |
389 | * @ring: amdgpu_ring pointer |
390 | * |
391 | * Returns the current hardware read pointer |
392 | */ |
393 | static uint64_t jpeg_v2_0_dec_ring_get_rptr(struct amdgpu_ring *ring) |
394 | { |
395 | struct amdgpu_device *adev = ring->adev; |
396 | |
397 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR); |
398 | } |
399 | |
400 | /** |
401 | * jpeg_v2_0_dec_ring_get_wptr - get write pointer |
402 | * |
403 | * @ring: amdgpu_ring pointer |
404 | * |
405 | * Returns the current hardware write pointer |
406 | */ |
407 | static uint64_t jpeg_v2_0_dec_ring_get_wptr(struct amdgpu_ring *ring) |
408 | { |
409 | struct amdgpu_device *adev = ring->adev; |
410 | |
411 | if (ring->use_doorbell) |
412 | return *ring->wptr_cpu_addr; |
413 | else |
414 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); |
415 | } |
416 | |
417 | /** |
418 | * jpeg_v2_0_dec_ring_set_wptr - set write pointer |
419 | * |
420 | * @ring: amdgpu_ring pointer |
421 | * |
422 | * Commits the write pointer to the hardware |
423 | */ |
424 | static void jpeg_v2_0_dec_ring_set_wptr(struct amdgpu_ring *ring) |
425 | { |
426 | struct amdgpu_device *adev = ring->adev; |
427 | |
428 | if (ring->use_doorbell) { |
429 | *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); |
430 | WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); |
431 | } else { |
432 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr)); |
433 | } |
434 | } |
435 | |
436 | /** |
437 | * jpeg_v2_0_dec_ring_insert_start - insert a start command |
438 | * |
439 | * @ring: amdgpu_ring pointer |
440 | * |
441 | * Write a start command to the ring. |
442 | */ |
443 | void jpeg_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring) |
444 | { |
445 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, |
446 | 0, 0, PACKETJ_TYPE0)); |
447 | amdgpu_ring_write(ring, v: 0x68e04); |
448 | |
449 | amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, |
450 | 0, 0, PACKETJ_TYPE0)); |
451 | amdgpu_ring_write(ring, v: 0x80010000); |
452 | } |
453 | |
454 | /** |
455 | * jpeg_v2_0_dec_ring_insert_end - insert a end command |
456 | * |
457 | * @ring: amdgpu_ring pointer |
458 | * |
459 | * Write a end command to the ring. |
460 | */ |
461 | void jpeg_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring) |
462 | { |
463 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, |
464 | 0, 0, PACKETJ_TYPE0)); |
465 | amdgpu_ring_write(ring, v: 0x68e04); |
466 | |
467 | amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, |
468 | 0, 0, PACKETJ_TYPE0)); |
469 | amdgpu_ring_write(ring, v: 0x00010000); |
470 | } |
471 | |
472 | /** |
473 | * jpeg_v2_0_dec_ring_emit_fence - emit an fence & trap command |
474 | * |
475 | * @ring: amdgpu_ring pointer |
476 | * @addr: address |
477 | * @seq: sequence number |
478 | * @flags: fence related flags |
479 | * |
480 | * Write a fence and a trap command to the ring. |
481 | */ |
482 | void jpeg_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, |
483 | unsigned flags) |
484 | { |
485 | WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); |
486 | |
487 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET, |
488 | 0, 0, PACKETJ_TYPE0)); |
489 | amdgpu_ring_write(ring, v: seq); |
490 | |
491 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET, |
492 | 0, 0, PACKETJ_TYPE0)); |
493 | amdgpu_ring_write(ring, v: seq); |
494 | |
495 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET, |
496 | 0, 0, PACKETJ_TYPE0)); |
497 | amdgpu_ring_write(ring, lower_32_bits(addr)); |
498 | |
499 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET, |
500 | 0, 0, PACKETJ_TYPE0)); |
501 | amdgpu_ring_write(ring, upper_32_bits(addr)); |
502 | |
503 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET, |
504 | 0, 0, PACKETJ_TYPE0)); |
505 | amdgpu_ring_write(ring, v: 0x8); |
506 | |
507 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET, |
508 | 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4)); |
509 | amdgpu_ring_write(ring, v: 0); |
510 | |
511 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, |
512 | 0, 0, PACKETJ_TYPE0)); |
513 | amdgpu_ring_write(ring, v: 0x3fbc); |
514 | |
515 | amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, |
516 | 0, 0, PACKETJ_TYPE0)); |
517 | amdgpu_ring_write(ring, v: 0x1); |
518 | |
519 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7)); |
520 | amdgpu_ring_write(ring, v: 0); |
521 | } |
522 | |
523 | /** |
524 | * jpeg_v2_0_dec_ring_emit_ib - execute indirect buffer |
525 | * |
526 | * @ring: amdgpu_ring pointer |
527 | * @job: job to retrieve vmid from |
528 | * @ib: indirect buffer to execute |
529 | * @flags: unused |
530 | * |
531 | * Write ring commands to execute the indirect buffer. |
532 | */ |
533 | void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, |
534 | struct amdgpu_job *job, |
535 | struct amdgpu_ib *ib, |
536 | uint32_t flags) |
537 | { |
538 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); |
539 | |
540 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_IH_CTRL_INTERNAL_OFFSET, |
541 | 0, 0, PACKETJ_TYPE0)); |
542 | amdgpu_ring_write(ring, v: (vmid << JPEG_IH_CTRL__IH_VMID__SHIFT)); |
543 | |
544 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, |
545 | 0, 0, PACKETJ_TYPE0)); |
546 | amdgpu_ring_write(ring, v: (vmid | (vmid << 4))); |
547 | |
548 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET, |
549 | 0, 0, PACKETJ_TYPE0)); |
550 | amdgpu_ring_write(ring, v: (vmid | (vmid << 4))); |
551 | |
552 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET, |
553 | 0, 0, PACKETJ_TYPE0)); |
554 | amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); |
555 | |
556 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET, |
557 | 0, 0, PACKETJ_TYPE0)); |
558 | amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); |
559 | |
560 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_IB_SIZE_INTERNAL_OFFSET, |
561 | 0, 0, PACKETJ_TYPE0)); |
562 | amdgpu_ring_write(ring, v: ib->length_dw); |
563 | |
564 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET, |
565 | 0, 0, PACKETJ_TYPE0)); |
566 | amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr)); |
567 | |
568 | amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET, |
569 | 0, 0, PACKETJ_TYPE0)); |
570 | amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr)); |
571 | |
572 | amdgpu_ring_write(ring, PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2)); |
573 | amdgpu_ring_write(ring, v: 0); |
574 | |
575 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET, |
576 | 0, 0, PACKETJ_TYPE0)); |
577 | amdgpu_ring_write(ring, v: 0x01400200); |
578 | |
579 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET, |
580 | 0, 0, PACKETJ_TYPE0)); |
581 | amdgpu_ring_write(ring, v: 0x2); |
582 | |
583 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_STATUS_INTERNAL_OFFSET, |
584 | 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3)); |
585 | amdgpu_ring_write(ring, v: 0x2); |
586 | } |
587 | |
588 | void jpeg_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, |
589 | uint32_t val, uint32_t mask) |
590 | { |
591 | uint32_t reg_offset = (reg << 2); |
592 | |
593 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET, |
594 | 0, 0, PACKETJ_TYPE0)); |
595 | amdgpu_ring_write(ring, v: 0x01400200); |
596 | |
597 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET, |
598 | 0, 0, PACKETJ_TYPE0)); |
599 | amdgpu_ring_write(ring, v: val); |
600 | |
601 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, |
602 | 0, 0, PACKETJ_TYPE0)); |
603 | if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) { |
604 | amdgpu_ring_write(ring, v: 0); |
605 | amdgpu_ring_write(ring, |
606 | PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3)); |
607 | } else { |
608 | amdgpu_ring_write(ring, v: reg_offset); |
609 | amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, |
610 | 0, 0, PACKETJ_TYPE3)); |
611 | } |
612 | amdgpu_ring_write(ring, v: mask); |
613 | } |
614 | |
615 | void jpeg_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring, |
616 | unsigned vmid, uint64_t pd_addr) |
617 | { |
618 | struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub]; |
619 | uint32_t data0, data1, mask; |
620 | |
621 | pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr); |
622 | |
623 | /* wait for register write */ |
624 | data0 = hub->ctx0_ptb_addr_lo32 + vmid * hub->ctx_addr_distance; |
625 | data1 = lower_32_bits(pd_addr); |
626 | mask = 0xffffffff; |
627 | jpeg_v2_0_dec_ring_emit_reg_wait(ring, reg: data0, val: data1, mask); |
628 | } |
629 | |
630 | void jpeg_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val) |
631 | { |
632 | uint32_t reg_offset = (reg << 2); |
633 | |
634 | amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, |
635 | 0, 0, PACKETJ_TYPE0)); |
636 | if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) { |
637 | amdgpu_ring_write(ring, v: 0); |
638 | amdgpu_ring_write(ring, |
639 | PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0)); |
640 | } else { |
641 | amdgpu_ring_write(ring, v: reg_offset); |
642 | amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, |
643 | 0, 0, PACKETJ_TYPE0)); |
644 | } |
645 | amdgpu_ring_write(ring, v: val); |
646 | } |
647 | |
648 | void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count) |
649 | { |
650 | int i; |
651 | |
652 | WARN_ON(ring->wptr % 2 || count % 2); |
653 | |
654 | for (i = 0; i < count / 2; i++) { |
655 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6)); |
656 | amdgpu_ring_write(ring, v: 0); |
657 | } |
658 | } |
659 | |
660 | static bool jpeg_v2_0_is_idle(void *handle) |
661 | { |
662 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
663 | |
664 | return ((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) & |
665 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK) == |
666 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK); |
667 | } |
668 | |
669 | static int jpeg_v2_0_wait_for_idle(void *handle) |
670 | { |
671 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
672 | int ret; |
673 | |
674 | ret = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, UVD_JRBC_STATUS__RB_JOB_DONE_MASK, |
675 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK); |
676 | |
677 | return ret; |
678 | } |
679 | |
680 | static int jpeg_v2_0_set_clockgating_state(void *handle, |
681 | enum amd_clockgating_state state) |
682 | { |
683 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
684 | bool enable = (state == AMD_CG_STATE_GATE); |
685 | |
686 | if (enable) { |
687 | if (!jpeg_v2_0_is_idle(handle)) |
688 | return -EBUSY; |
689 | jpeg_v2_0_enable_clock_gating(adev); |
690 | } else { |
691 | jpeg_v2_0_disable_clock_gating(adev); |
692 | } |
693 | |
694 | return 0; |
695 | } |
696 | |
697 | static int jpeg_v2_0_set_powergating_state(void *handle, |
698 | enum amd_powergating_state state) |
699 | { |
700 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
701 | int ret; |
702 | |
703 | if (state == adev->jpeg.cur_state) |
704 | return 0; |
705 | |
706 | if (state == AMD_PG_STATE_GATE) |
707 | ret = jpeg_v2_0_stop(adev); |
708 | else |
709 | ret = jpeg_v2_0_start(adev); |
710 | |
711 | if (!ret) |
712 | adev->jpeg.cur_state = state; |
713 | |
714 | return ret; |
715 | } |
716 | |
717 | static int jpeg_v2_0_set_interrupt_state(struct amdgpu_device *adev, |
718 | struct amdgpu_irq_src *source, |
719 | unsigned type, |
720 | enum amdgpu_interrupt_state state) |
721 | { |
722 | return 0; |
723 | } |
724 | |
725 | static int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev, |
726 | struct amdgpu_irq_src *source, |
727 | struct amdgpu_iv_entry *entry) |
728 | { |
729 | DRM_DEBUG("IH: JPEG TRAP\n" ); |
730 | |
731 | switch (entry->src_id) { |
732 | case VCN_2_0__SRCID__JPEG_DECODE: |
733 | amdgpu_fence_process(ring: adev->jpeg.inst->ring_dec); |
734 | break; |
735 | default: |
736 | DRM_ERROR("Unhandled interrupt: %d %d\n" , |
737 | entry->src_id, entry->src_data[0]); |
738 | break; |
739 | } |
740 | |
741 | return 0; |
742 | } |
743 | |
744 | static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = { |
745 | .name = "jpeg_v2_0" , |
746 | .early_init = jpeg_v2_0_early_init, |
747 | .late_init = NULL, |
748 | .sw_init = jpeg_v2_0_sw_init, |
749 | .sw_fini = jpeg_v2_0_sw_fini, |
750 | .hw_init = jpeg_v2_0_hw_init, |
751 | .hw_fini = jpeg_v2_0_hw_fini, |
752 | .suspend = jpeg_v2_0_suspend, |
753 | .resume = jpeg_v2_0_resume, |
754 | .is_idle = jpeg_v2_0_is_idle, |
755 | .wait_for_idle = jpeg_v2_0_wait_for_idle, |
756 | .check_soft_reset = NULL, |
757 | .pre_soft_reset = NULL, |
758 | .soft_reset = NULL, |
759 | .post_soft_reset = NULL, |
760 | .set_clockgating_state = jpeg_v2_0_set_clockgating_state, |
761 | .set_powergating_state = jpeg_v2_0_set_powergating_state, |
762 | }; |
763 | |
764 | static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = { |
765 | .type = AMDGPU_RING_TYPE_VCN_JPEG, |
766 | .align_mask = 0xf, |
767 | .get_rptr = jpeg_v2_0_dec_ring_get_rptr, |
768 | .get_wptr = jpeg_v2_0_dec_ring_get_wptr, |
769 | .set_wptr = jpeg_v2_0_dec_ring_set_wptr, |
770 | .emit_frame_size = |
771 | SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + |
772 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + |
773 | 8 + /* jpeg_v2_0_dec_ring_emit_vm_flush */ |
774 | 18 + 18 + /* jpeg_v2_0_dec_ring_emit_fence x2 vm fence */ |
775 | 8 + 16, |
776 | .emit_ib_size = 24, /* jpeg_v2_0_dec_ring_emit_ib */ |
777 | .emit_ib = jpeg_v2_0_dec_ring_emit_ib, |
778 | .emit_fence = jpeg_v2_0_dec_ring_emit_fence, |
779 | .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush, |
780 | .test_ring = amdgpu_jpeg_dec_ring_test_ring, |
781 | .test_ib = amdgpu_jpeg_dec_ring_test_ib, |
782 | .insert_nop = jpeg_v2_0_dec_ring_nop, |
783 | .insert_start = jpeg_v2_0_dec_ring_insert_start, |
784 | .insert_end = jpeg_v2_0_dec_ring_insert_end, |
785 | .pad_ib = amdgpu_ring_generic_pad_ib, |
786 | .begin_use = amdgpu_jpeg_ring_begin_use, |
787 | .end_use = amdgpu_jpeg_ring_end_use, |
788 | .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg, |
789 | .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait, |
790 | .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, |
791 | }; |
792 | |
793 | static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev) |
794 | { |
795 | adev->jpeg.inst->ring_dec->funcs = &jpeg_v2_0_dec_ring_vm_funcs; |
796 | DRM_INFO("JPEG decode is enabled in VM mode\n" ); |
797 | } |
798 | |
799 | static const struct amdgpu_irq_src_funcs jpeg_v2_0_irq_funcs = { |
800 | .set = jpeg_v2_0_set_interrupt_state, |
801 | .process = jpeg_v2_0_process_interrupt, |
802 | }; |
803 | |
804 | static void jpeg_v2_0_set_irq_funcs(struct amdgpu_device *adev) |
805 | { |
806 | adev->jpeg.inst->irq.num_types = 1; |
807 | adev->jpeg.inst->irq.funcs = &jpeg_v2_0_irq_funcs; |
808 | } |
809 | |
810 | const struct amdgpu_ip_block_version jpeg_v2_0_ip_block = { |
811 | .type = AMD_IP_BLOCK_TYPE_JPEG, |
812 | .major = 2, |
813 | .minor = 0, |
814 | .rev = 0, |
815 | .funcs = &jpeg_v2_0_ip_funcs, |
816 | }; |
817 | |