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_3_0_0_offset.h" |
32 | #include "vcn/vcn_3_0_0_sh_mask.h" |
33 | #include "ivsrcid/vcn/irqsrcs_vcn_2_0.h" |
34 | |
35 | #define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f |
36 | |
37 | static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev); |
38 | static void jpeg_v3_0_set_irq_funcs(struct amdgpu_device *adev); |
39 | static int jpeg_v3_0_set_powergating_state(void *handle, |
40 | enum amd_powergating_state state); |
41 | |
42 | /** |
43 | * jpeg_v3_0_early_init - set function pointers |
44 | * |
45 | * @handle: amdgpu_device pointer |
46 | * |
47 | * Set ring and irq function pointers |
48 | */ |
49 | static int jpeg_v3_0_early_init(void *handle) |
50 | { |
51 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
52 | |
53 | u32 harvest; |
54 | |
55 | switch (amdgpu_ip_version(adev, ip: UVD_HWIP, inst: 0)) { |
56 | case IP_VERSION(3, 1, 1): |
57 | case IP_VERSION(3, 1, 2): |
58 | break; |
59 | default: |
60 | harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING); |
61 | if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) |
62 | return -ENOENT; |
63 | break; |
64 | } |
65 | |
66 | adev->jpeg.num_jpeg_inst = 1; |
67 | adev->jpeg.num_jpeg_rings = 1; |
68 | |
69 | jpeg_v3_0_set_dec_ring_funcs(adev); |
70 | jpeg_v3_0_set_irq_funcs(adev); |
71 | |
72 | return 0; |
73 | } |
74 | |
75 | /** |
76 | * jpeg_v3_0_sw_init - sw init for JPEG block |
77 | * |
78 | * @handle: amdgpu_device pointer |
79 | * |
80 | * Load firmware and sw initialization |
81 | */ |
82 | static int jpeg_v3_0_sw_init(void *handle) |
83 | { |
84 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
85 | struct amdgpu_ring *ring; |
86 | int r; |
87 | |
88 | /* JPEG TRAP */ |
89 | r = amdgpu_irq_add_id(adev, client_id: SOC15_IH_CLIENTID_VCN, |
90 | VCN_2_0__SRCID__JPEG_DECODE, source: &adev->jpeg.inst->irq); |
91 | if (r) |
92 | return r; |
93 | |
94 | r = amdgpu_jpeg_sw_init(adev); |
95 | if (r) |
96 | return r; |
97 | |
98 | r = amdgpu_jpeg_resume(adev); |
99 | if (r) |
100 | return r; |
101 | |
102 | ring = adev->jpeg.inst->ring_dec; |
103 | ring->use_doorbell = true; |
104 | ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1; |
105 | ring->vm_hub = AMDGPU_MMHUB0(0); |
106 | sprintf(buf: ring->name, fmt: "jpeg_dec" ); |
107 | r = amdgpu_ring_init(adev, ring, max_dw: 512, irq_src: &adev->jpeg.inst->irq, irq_type: 0, |
108 | hw_prio: AMDGPU_RING_PRIO_DEFAULT, NULL); |
109 | if (r) |
110 | return r; |
111 | |
112 | adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET; |
113 | adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH); |
114 | |
115 | return 0; |
116 | } |
117 | |
118 | /** |
119 | * jpeg_v3_0_sw_fini - sw fini for JPEG block |
120 | * |
121 | * @handle: amdgpu_device pointer |
122 | * |
123 | * JPEG suspend and free up sw allocation |
124 | */ |
125 | static int jpeg_v3_0_sw_fini(void *handle) |
126 | { |
127 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
128 | int r; |
129 | |
130 | r = amdgpu_jpeg_suspend(adev); |
131 | if (r) |
132 | return r; |
133 | |
134 | r = amdgpu_jpeg_sw_fini(adev); |
135 | |
136 | return r; |
137 | } |
138 | |
139 | /** |
140 | * jpeg_v3_0_hw_init - start and test JPEG block |
141 | * |
142 | * @handle: amdgpu_device pointer |
143 | * |
144 | */ |
145 | static int jpeg_v3_0_hw_init(void *handle) |
146 | { |
147 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
148 | struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec; |
149 | int r; |
150 | |
151 | adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, |
152 | (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); |
153 | |
154 | r = amdgpu_ring_test_helper(ring); |
155 | if (r) |
156 | return r; |
157 | |
158 | DRM_INFO("JPEG decode initialized successfully.\n" ); |
159 | |
160 | return 0; |
161 | } |
162 | |
163 | /** |
164 | * jpeg_v3_0_hw_fini - stop the hardware block |
165 | * |
166 | * @handle: amdgpu_device pointer |
167 | * |
168 | * Stop the JPEG block, mark ring as not ready any more |
169 | */ |
170 | static int jpeg_v3_0_hw_fini(void *handle) |
171 | { |
172 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
173 | |
174 | cancel_delayed_work_sync(dwork: &adev->vcn.idle_work); |
175 | |
176 | if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && |
177 | RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS)) |
178 | jpeg_v3_0_set_powergating_state(handle: adev, state: AMD_PG_STATE_GATE); |
179 | |
180 | return 0; |
181 | } |
182 | |
183 | /** |
184 | * jpeg_v3_0_suspend - suspend JPEG block |
185 | * |
186 | * @handle: amdgpu_device pointer |
187 | * |
188 | * HW fini and suspend JPEG block |
189 | */ |
190 | static int jpeg_v3_0_suspend(void *handle) |
191 | { |
192 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
193 | int r; |
194 | |
195 | r = jpeg_v3_0_hw_fini(handle: adev); |
196 | if (r) |
197 | return r; |
198 | |
199 | r = amdgpu_jpeg_suspend(adev); |
200 | |
201 | return r; |
202 | } |
203 | |
204 | /** |
205 | * jpeg_v3_0_resume - resume JPEG block |
206 | * |
207 | * @handle: amdgpu_device pointer |
208 | * |
209 | * Resume firmware and hw init JPEG block |
210 | */ |
211 | static int jpeg_v3_0_resume(void *handle) |
212 | { |
213 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
214 | int r; |
215 | |
216 | r = amdgpu_jpeg_resume(adev); |
217 | if (r) |
218 | return r; |
219 | |
220 | r = jpeg_v3_0_hw_init(handle: adev); |
221 | |
222 | return r; |
223 | } |
224 | |
225 | static void jpeg_v3_0_disable_clock_gating(struct amdgpu_device *adev) |
226 | { |
227 | uint32_t data = 0; |
228 | |
229 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL); |
230 | if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) |
231 | data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
232 | else |
233 | data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; |
234 | |
235 | data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; |
236 | data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; |
237 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data); |
238 | |
239 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE); |
240 | data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK |
241 | | JPEG_CGC_GATE__JPEG2_DEC_MASK |
242 | | JPEG_CGC_GATE__JPEG_ENC_MASK |
243 | | JPEG_CGC_GATE__JMCIF_MASK |
244 | | JPEG_CGC_GATE__JRBBM_MASK); |
245 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data); |
246 | |
247 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL); |
248 | data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK |
249 | | JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK |
250 | | JPEG_CGC_CTRL__JMCIF_MODE_MASK |
251 | | JPEG_CGC_CTRL__JRBBM_MODE_MASK); |
252 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data); |
253 | } |
254 | |
255 | static void jpeg_v3_0_enable_clock_gating(struct amdgpu_device *adev) |
256 | { |
257 | uint32_t data = 0; |
258 | |
259 | data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE); |
260 | data |= (JPEG_CGC_GATE__JPEG_DEC_MASK |
261 | |JPEG_CGC_GATE__JPEG2_DEC_MASK |
262 | |JPEG_CGC_GATE__JPEG_ENC_MASK |
263 | |JPEG_CGC_GATE__JMCIF_MASK |
264 | |JPEG_CGC_GATE__JRBBM_MASK); |
265 | WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data); |
266 | } |
267 | |
268 | static int jpeg_v3_0_disable_static_power_gating(struct amdgpu_device *adev) |
269 | { |
270 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
271 | uint32_t data = 0; |
272 | int r = 0; |
273 | |
274 | data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT; |
275 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data); |
276 | |
277 | r = SOC15_WAIT_ON_RREG(JPEG, 0, |
278 | mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON, |
279 | UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK); |
280 | |
281 | if (r) { |
282 | DRM_ERROR("amdgpu: JPEG disable power gating failed\n" ); |
283 | return r; |
284 | } |
285 | } |
286 | |
287 | /* disable anti hang mechanism */ |
288 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), 0, |
289 | ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); |
290 | |
291 | /* keep the JPEG in static PG mode */ |
292 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), 0, |
293 | ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK); |
294 | |
295 | return 0; |
296 | } |
297 | |
298 | static int jpeg_v3_0_enable_static_power_gating(struct amdgpu_device *adev) |
299 | { |
300 | /* enable anti hang mechanism */ |
301 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), |
302 | UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK, |
303 | ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); |
304 | |
305 | if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) { |
306 | uint32_t data = 0; |
307 | int r = 0; |
308 | |
309 | data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT; |
310 | WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data); |
311 | |
312 | r = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_PGFSM_STATUS, |
313 | (2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT), |
314 | UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK); |
315 | |
316 | if (r) { |
317 | DRM_ERROR("amdgpu: JPEG enable power gating failed\n" ); |
318 | return r; |
319 | } |
320 | } |
321 | |
322 | return 0; |
323 | } |
324 | |
325 | /** |
326 | * jpeg_v3_0_start - start JPEG block |
327 | * |
328 | * @adev: amdgpu_device pointer |
329 | * |
330 | * Setup and start the JPEG block |
331 | */ |
332 | static int jpeg_v3_0_start(struct amdgpu_device *adev) |
333 | { |
334 | struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec; |
335 | int r; |
336 | |
337 | if (adev->pm.dpm_enabled) |
338 | amdgpu_dpm_enable_jpeg(adev, enable: true); |
339 | |
340 | /* disable power gating */ |
341 | r = jpeg_v3_0_disable_static_power_gating(adev); |
342 | if (r) |
343 | return r; |
344 | |
345 | /* JPEG disable CGC */ |
346 | jpeg_v3_0_disable_clock_gating(adev); |
347 | |
348 | /* MJPEG global tiling registers */ |
349 | WREG32_SOC15(JPEG, 0, mmJPEG_DEC_GFX10_ADDR_CONFIG, |
350 | adev->gfx.config.gb_addr_config); |
351 | WREG32_SOC15(JPEG, 0, mmJPEG_ENC_GFX10_ADDR_CONFIG, |
352 | adev->gfx.config.gb_addr_config); |
353 | |
354 | /* enable JMI channel */ |
355 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), 0, |
356 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
357 | |
358 | /* enable System Interrupt for JRBC */ |
359 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmJPEG_SYS_INT_EN), |
360 | JPEG_SYS_INT_EN__DJRBC_MASK, |
361 | ~JPEG_SYS_INT_EN__DJRBC_MASK); |
362 | |
363 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0); |
364 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); |
365 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, |
366 | lower_32_bits(ring->gpu_addr)); |
367 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, |
368 | upper_32_bits(ring->gpu_addr)); |
369 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0); |
370 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0); |
371 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L); |
372 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4); |
373 | ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); |
374 | |
375 | return 0; |
376 | } |
377 | |
378 | /** |
379 | * jpeg_v3_0_stop - stop JPEG block |
380 | * |
381 | * @adev: amdgpu_device pointer |
382 | * |
383 | * stop the JPEG block |
384 | */ |
385 | static int jpeg_v3_0_stop(struct amdgpu_device *adev) |
386 | { |
387 | int r; |
388 | |
389 | /* reset JMI */ |
390 | WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), |
391 | UVD_JMI_CNTL__SOFT_RESET_MASK, |
392 | ~UVD_JMI_CNTL__SOFT_RESET_MASK); |
393 | |
394 | jpeg_v3_0_enable_clock_gating(adev); |
395 | |
396 | /* enable power gating */ |
397 | r = jpeg_v3_0_enable_static_power_gating(adev); |
398 | if (r) |
399 | return r; |
400 | |
401 | if (adev->pm.dpm_enabled) |
402 | amdgpu_dpm_enable_jpeg(adev, enable: false); |
403 | |
404 | return 0; |
405 | } |
406 | |
407 | /** |
408 | * jpeg_v3_0_dec_ring_get_rptr - get read pointer |
409 | * |
410 | * @ring: amdgpu_ring pointer |
411 | * |
412 | * Returns the current hardware read pointer |
413 | */ |
414 | static uint64_t jpeg_v3_0_dec_ring_get_rptr(struct amdgpu_ring *ring) |
415 | { |
416 | struct amdgpu_device *adev = ring->adev; |
417 | |
418 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR); |
419 | } |
420 | |
421 | /** |
422 | * jpeg_v3_0_dec_ring_get_wptr - get write pointer |
423 | * |
424 | * @ring: amdgpu_ring pointer |
425 | * |
426 | * Returns the current hardware write pointer |
427 | */ |
428 | static uint64_t jpeg_v3_0_dec_ring_get_wptr(struct amdgpu_ring *ring) |
429 | { |
430 | struct amdgpu_device *adev = ring->adev; |
431 | |
432 | if (ring->use_doorbell) |
433 | return *ring->wptr_cpu_addr; |
434 | else |
435 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); |
436 | } |
437 | |
438 | /** |
439 | * jpeg_v3_0_dec_ring_set_wptr - set write pointer |
440 | * |
441 | * @ring: amdgpu_ring pointer |
442 | * |
443 | * Commits the write pointer to the hardware |
444 | */ |
445 | static void jpeg_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring) |
446 | { |
447 | struct amdgpu_device *adev = ring->adev; |
448 | |
449 | if (ring->use_doorbell) { |
450 | *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); |
451 | WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); |
452 | } else { |
453 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr)); |
454 | } |
455 | } |
456 | |
457 | static bool jpeg_v3_0_is_idle(void *handle) |
458 | { |
459 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
460 | int ret = 1; |
461 | |
462 | ret &= (((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) & |
463 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK) == |
464 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK)); |
465 | |
466 | return ret; |
467 | } |
468 | |
469 | static int jpeg_v3_0_wait_for_idle(void *handle) |
470 | { |
471 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
472 | |
473 | return SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, |
474 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK, |
475 | UVD_JRBC_STATUS__RB_JOB_DONE_MASK); |
476 | } |
477 | |
478 | static int jpeg_v3_0_set_clockgating_state(void *handle, |
479 | enum amd_clockgating_state state) |
480 | { |
481 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
482 | bool enable = state == AMD_CG_STATE_GATE; |
483 | |
484 | if (enable) { |
485 | if (!jpeg_v3_0_is_idle(handle)) |
486 | return -EBUSY; |
487 | jpeg_v3_0_enable_clock_gating(adev); |
488 | } else { |
489 | jpeg_v3_0_disable_clock_gating(adev); |
490 | } |
491 | |
492 | return 0; |
493 | } |
494 | |
495 | static int jpeg_v3_0_set_powergating_state(void *handle, |
496 | enum amd_powergating_state state) |
497 | { |
498 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
499 | int ret; |
500 | |
501 | if(state == adev->jpeg.cur_state) |
502 | return 0; |
503 | |
504 | if (state == AMD_PG_STATE_GATE) |
505 | ret = jpeg_v3_0_stop(adev); |
506 | else |
507 | ret = jpeg_v3_0_start(adev); |
508 | |
509 | if(!ret) |
510 | adev->jpeg.cur_state = state; |
511 | |
512 | return ret; |
513 | } |
514 | |
515 | static int jpeg_v3_0_set_interrupt_state(struct amdgpu_device *adev, |
516 | struct amdgpu_irq_src *source, |
517 | unsigned type, |
518 | enum amdgpu_interrupt_state state) |
519 | { |
520 | return 0; |
521 | } |
522 | |
523 | static int jpeg_v3_0_process_interrupt(struct amdgpu_device *adev, |
524 | struct amdgpu_irq_src *source, |
525 | struct amdgpu_iv_entry *entry) |
526 | { |
527 | DRM_DEBUG("IH: JPEG TRAP\n" ); |
528 | |
529 | switch (entry->src_id) { |
530 | case VCN_2_0__SRCID__JPEG_DECODE: |
531 | amdgpu_fence_process(ring: adev->jpeg.inst->ring_dec); |
532 | break; |
533 | default: |
534 | DRM_ERROR("Unhandled interrupt: %d %d\n" , |
535 | entry->src_id, entry->src_data[0]); |
536 | break; |
537 | } |
538 | |
539 | return 0; |
540 | } |
541 | |
542 | static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = { |
543 | .name = "jpeg_v3_0" , |
544 | .early_init = jpeg_v3_0_early_init, |
545 | .late_init = NULL, |
546 | .sw_init = jpeg_v3_0_sw_init, |
547 | .sw_fini = jpeg_v3_0_sw_fini, |
548 | .hw_init = jpeg_v3_0_hw_init, |
549 | .hw_fini = jpeg_v3_0_hw_fini, |
550 | .suspend = jpeg_v3_0_suspend, |
551 | .resume = jpeg_v3_0_resume, |
552 | .is_idle = jpeg_v3_0_is_idle, |
553 | .wait_for_idle = jpeg_v3_0_wait_for_idle, |
554 | .check_soft_reset = NULL, |
555 | .pre_soft_reset = NULL, |
556 | .soft_reset = NULL, |
557 | .post_soft_reset = NULL, |
558 | .set_clockgating_state = jpeg_v3_0_set_clockgating_state, |
559 | .set_powergating_state = jpeg_v3_0_set_powergating_state, |
560 | }; |
561 | |
562 | static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = { |
563 | .type = AMDGPU_RING_TYPE_VCN_JPEG, |
564 | .align_mask = 0xf, |
565 | .get_rptr = jpeg_v3_0_dec_ring_get_rptr, |
566 | .get_wptr = jpeg_v3_0_dec_ring_get_wptr, |
567 | .set_wptr = jpeg_v3_0_dec_ring_set_wptr, |
568 | .emit_frame_size = |
569 | SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + |
570 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + |
571 | 8 + /* jpeg_v3_0_dec_ring_emit_vm_flush */ |
572 | 18 + 18 + /* jpeg_v3_0_dec_ring_emit_fence x2 vm fence */ |
573 | 8 + 16, |
574 | .emit_ib_size = 22, /* jpeg_v3_0_dec_ring_emit_ib */ |
575 | .emit_ib = jpeg_v2_0_dec_ring_emit_ib, |
576 | .emit_fence = jpeg_v2_0_dec_ring_emit_fence, |
577 | .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush, |
578 | .test_ring = amdgpu_jpeg_dec_ring_test_ring, |
579 | .test_ib = amdgpu_jpeg_dec_ring_test_ib, |
580 | .insert_nop = jpeg_v2_0_dec_ring_nop, |
581 | .insert_start = jpeg_v2_0_dec_ring_insert_start, |
582 | .insert_end = jpeg_v2_0_dec_ring_insert_end, |
583 | .pad_ib = amdgpu_ring_generic_pad_ib, |
584 | .begin_use = amdgpu_jpeg_ring_begin_use, |
585 | .end_use = amdgpu_jpeg_ring_end_use, |
586 | .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg, |
587 | .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait, |
588 | .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, |
589 | }; |
590 | |
591 | static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev) |
592 | { |
593 | adev->jpeg.inst->ring_dec->funcs = &jpeg_v3_0_dec_ring_vm_funcs; |
594 | DRM_INFO("JPEG decode is enabled in VM mode\n" ); |
595 | } |
596 | |
597 | static const struct amdgpu_irq_src_funcs jpeg_v3_0_irq_funcs = { |
598 | .set = jpeg_v3_0_set_interrupt_state, |
599 | .process = jpeg_v3_0_process_interrupt, |
600 | }; |
601 | |
602 | static void jpeg_v3_0_set_irq_funcs(struct amdgpu_device *adev) |
603 | { |
604 | adev->jpeg.inst->irq.num_types = 1; |
605 | adev->jpeg.inst->irq.funcs = &jpeg_v3_0_irq_funcs; |
606 | } |
607 | |
608 | const struct amdgpu_ip_block_version jpeg_v3_0_ip_block = |
609 | { |
610 | .type = AMD_IP_BLOCK_TYPE_JPEG, |
611 | .major = 3, |
612 | .minor = 0, |
613 | .rev = 0, |
614 | .funcs = &jpeg_v3_0_ip_funcs, |
615 | }; |
616 | |