Line data Source code
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 "soc15.h"
27 : #include "soc15d.h"
28 : #include "jpeg_v2_0.h"
29 : #include "jpeg_v2_5.h"
30 :
31 : #include "vcn/vcn_2_5_offset.h"
32 : #include "vcn/vcn_2_5_sh_mask.h"
33 : #include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
34 :
35 : #define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
36 :
37 : #define JPEG25_MAX_HW_INSTANCES_ARCTURUS 2
38 :
39 : static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
40 : static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev);
41 : static int jpeg_v2_5_set_powergating_state(void *handle,
42 : enum amd_powergating_state state);
43 : static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev);
44 :
45 : static int amdgpu_ih_clientid_jpeg[] = {
46 : SOC15_IH_CLIENTID_VCN,
47 : SOC15_IH_CLIENTID_VCN1
48 : };
49 :
50 : /**
51 : * jpeg_v2_5_early_init - set function pointers
52 : *
53 : * @handle: amdgpu_device pointer
54 : *
55 : * Set ring and irq function pointers
56 : */
57 0 : static int jpeg_v2_5_early_init(void *handle)
58 : {
59 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
60 : u32 harvest;
61 : int i;
62 :
63 0 : adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS;
64 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
65 0 : harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING);
66 0 : if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
67 0 : adev->jpeg.harvest_config |= 1 << i;
68 : }
69 0 : if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 |
70 : AMDGPU_JPEG_HARVEST_JPEG1))
71 : return -ENOENT;
72 :
73 0 : jpeg_v2_5_set_dec_ring_funcs(adev);
74 0 : jpeg_v2_5_set_irq_funcs(adev);
75 0 : jpeg_v2_5_set_ras_funcs(adev);
76 :
77 0 : return 0;
78 : }
79 :
80 : /**
81 : * jpeg_v2_5_sw_init - sw init for JPEG block
82 : *
83 : * @handle: amdgpu_device pointer
84 : *
85 : * Load firmware and sw initialization
86 : */
87 0 : static int jpeg_v2_5_sw_init(void *handle)
88 : {
89 : struct amdgpu_ring *ring;
90 : int i, r;
91 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
92 :
93 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
94 0 : if (adev->jpeg.harvest_config & (1 << i))
95 0 : continue;
96 :
97 : /* JPEG TRAP */
98 0 : r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
99 : VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst[i].irq);
100 0 : if (r)
101 : return r;
102 :
103 : /* JPEG DJPEG POISON EVENT */
104 0 : r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
105 : VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].irq);
106 0 : if (r)
107 : return r;
108 :
109 : /* JPEG EJPEG POISON EVENT */
110 0 : r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
111 : VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].irq);
112 0 : if (r)
113 : return r;
114 : }
115 :
116 0 : r = amdgpu_jpeg_sw_init(adev);
117 0 : if (r)
118 : return r;
119 :
120 0 : r = amdgpu_jpeg_resume(adev);
121 0 : if (r)
122 : return r;
123 :
124 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
125 0 : if (adev->jpeg.harvest_config & (1 << i))
126 0 : continue;
127 :
128 0 : ring = &adev->jpeg.inst[i].ring_dec;
129 0 : ring->use_doorbell = true;
130 0 : ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;
131 0 : sprintf(ring->name, "jpeg_dec_%d", i);
132 0 : r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,
133 : 0, AMDGPU_RING_PRIO_DEFAULT, NULL);
134 0 : if (r)
135 : return r;
136 :
137 0 : adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
138 0 : adev->jpeg.inst[i].external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
139 : }
140 :
141 : return 0;
142 : }
143 :
144 : /**
145 : * jpeg_v2_5_sw_fini - sw fini for JPEG block
146 : *
147 : * @handle: amdgpu_device pointer
148 : *
149 : * JPEG suspend and free up sw allocation
150 : */
151 0 : static int jpeg_v2_5_sw_fini(void *handle)
152 : {
153 : int r;
154 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
155 :
156 0 : r = amdgpu_jpeg_suspend(adev);
157 0 : if (r)
158 : return r;
159 :
160 0 : r = amdgpu_jpeg_sw_fini(adev);
161 :
162 0 : return r;
163 : }
164 :
165 : /**
166 : * jpeg_v2_5_hw_init - start and test JPEG block
167 : *
168 : * @handle: amdgpu_device pointer
169 : *
170 : */
171 0 : static int jpeg_v2_5_hw_init(void *handle)
172 : {
173 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
174 : struct amdgpu_ring *ring;
175 : int i, r;
176 :
177 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
178 0 : if (adev->jpeg.harvest_config & (1 << i))
179 0 : continue;
180 :
181 0 : ring = &adev->jpeg.inst[i].ring_dec;
182 0 : adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
183 0 : (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);
184 :
185 0 : r = amdgpu_ring_test_helper(ring);
186 0 : if (r)
187 : return r;
188 : }
189 :
190 0 : DRM_INFO("JPEG decode initialized successfully.\n");
191 :
192 0 : return 0;
193 : }
194 :
195 : /**
196 : * jpeg_v2_5_hw_fini - stop the hardware block
197 : *
198 : * @handle: amdgpu_device pointer
199 : *
200 : * Stop the JPEG block, mark ring as not ready any more
201 : */
202 0 : static int jpeg_v2_5_hw_fini(void *handle)
203 : {
204 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
205 : int i;
206 :
207 0 : cancel_delayed_work_sync(&adev->vcn.idle_work);
208 :
209 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
210 0 : if (adev->jpeg.harvest_config & (1 << i))
211 0 : continue;
212 :
213 0 : if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
214 0 : RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
215 0 : jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
216 : }
217 :
218 0 : return 0;
219 : }
220 :
221 : /**
222 : * jpeg_v2_5_suspend - suspend JPEG block
223 : *
224 : * @handle: amdgpu_device pointer
225 : *
226 : * HW fini and suspend JPEG block
227 : */
228 0 : static int jpeg_v2_5_suspend(void *handle)
229 : {
230 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
231 : int r;
232 :
233 0 : r = jpeg_v2_5_hw_fini(adev);
234 0 : if (r)
235 : return r;
236 :
237 0 : r = amdgpu_jpeg_suspend(adev);
238 :
239 0 : return r;
240 : }
241 :
242 : /**
243 : * jpeg_v2_5_resume - resume JPEG block
244 : *
245 : * @handle: amdgpu_device pointer
246 : *
247 : * Resume firmware and hw init JPEG block
248 : */
249 0 : static int jpeg_v2_5_resume(void *handle)
250 : {
251 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
252 : int r;
253 :
254 0 : r = amdgpu_jpeg_resume(adev);
255 0 : if (r)
256 : return r;
257 :
258 0 : r = jpeg_v2_5_hw_init(adev);
259 :
260 0 : return r;
261 : }
262 :
263 0 : static void jpeg_v2_5_disable_clock_gating(struct amdgpu_device *adev, int inst)
264 : {
265 : uint32_t data;
266 :
267 0 : data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
268 0 : if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
269 0 : data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
270 : else
271 : data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
272 :
273 0 : data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
274 0 : data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
275 0 : WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
276 :
277 0 : data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
278 0 : data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
279 : | JPEG_CGC_GATE__JPEG2_DEC_MASK
280 : | JPEG_CGC_GATE__JMCIF_MASK
281 : | JPEG_CGC_GATE__JRBBM_MASK);
282 0 : WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
283 :
284 0 : data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
285 0 : data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK
286 : | JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK
287 : | JPEG_CGC_CTRL__JMCIF_MODE_MASK
288 : | JPEG_CGC_CTRL__JRBBM_MODE_MASK);
289 0 : WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
290 0 : }
291 :
292 0 : static void jpeg_v2_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
293 : {
294 : uint32_t data;
295 :
296 0 : data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
297 0 : data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
298 : |JPEG_CGC_GATE__JPEG2_DEC_MASK
299 : |JPEG_CGC_GATE__JPEG_ENC_MASK
300 : |JPEG_CGC_GATE__JMCIF_MASK
301 : |JPEG_CGC_GATE__JRBBM_MASK);
302 0 : WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
303 0 : }
304 :
305 : /**
306 : * jpeg_v2_5_start - start JPEG block
307 : *
308 : * @adev: amdgpu_device pointer
309 : *
310 : * Setup and start the JPEG block
311 : */
312 0 : static int jpeg_v2_5_start(struct amdgpu_device *adev)
313 : {
314 : struct amdgpu_ring *ring;
315 : int i;
316 :
317 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
318 0 : if (adev->jpeg.harvest_config & (1 << i))
319 0 : continue;
320 :
321 0 : ring = &adev->jpeg.inst[i].ring_dec;
322 : /* disable anti hang mechanism */
323 0 : WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS), 0,
324 : ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
325 :
326 : /* JPEG disable CGC */
327 0 : jpeg_v2_5_disable_clock_gating(adev, i);
328 :
329 : /* MJPEG global tiling registers */
330 0 : WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX8_ADDR_CONFIG,
331 : adev->gfx.config.gb_addr_config);
332 0 : WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX10_ADDR_CONFIG,
333 : adev->gfx.config.gb_addr_config);
334 :
335 : /* enable JMI channel */
336 0 : WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL), 0,
337 : ~UVD_JMI_CNTL__SOFT_RESET_MASK);
338 :
339 : /* enable System Interrupt for JRBC */
340 0 : WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmJPEG_SYS_INT_EN),
341 : JPEG_SYS_INT_EN__DJRBC_MASK,
342 : ~JPEG_SYS_INT_EN__DJRBC_MASK);
343 :
344 0 : WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_VMID, 0);
345 0 : WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
346 0 : WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
347 : lower_32_bits(ring->gpu_addr));
348 0 : WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
349 : upper_32_bits(ring->gpu_addr));
350 0 : WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_RPTR, 0);
351 0 : WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR, 0);
352 0 : WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, 0x00000002L);
353 0 : WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
354 0 : ring->wptr = RREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR);
355 : }
356 :
357 0 : return 0;
358 : }
359 :
360 : /**
361 : * jpeg_v2_5_stop - stop JPEG block
362 : *
363 : * @adev: amdgpu_device pointer
364 : *
365 : * stop the JPEG block
366 : */
367 0 : static int jpeg_v2_5_stop(struct amdgpu_device *adev)
368 : {
369 : int i;
370 :
371 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
372 0 : if (adev->jpeg.harvest_config & (1 << i))
373 0 : continue;
374 :
375 : /* reset JMI */
376 0 : WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL),
377 : UVD_JMI_CNTL__SOFT_RESET_MASK,
378 : ~UVD_JMI_CNTL__SOFT_RESET_MASK);
379 :
380 0 : jpeg_v2_5_enable_clock_gating(adev, i);
381 :
382 : /* enable anti hang mechanism */
383 0 : WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS),
384 : UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
385 : ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
386 : }
387 :
388 0 : return 0;
389 : }
390 :
391 : /**
392 : * jpeg_v2_5_dec_ring_get_rptr - get read pointer
393 : *
394 : * @ring: amdgpu_ring pointer
395 : *
396 : * Returns the current hardware read pointer
397 : */
398 0 : static uint64_t jpeg_v2_5_dec_ring_get_rptr(struct amdgpu_ring *ring)
399 : {
400 0 : struct amdgpu_device *adev = ring->adev;
401 :
402 0 : return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_RPTR);
403 : }
404 :
405 : /**
406 : * jpeg_v2_5_dec_ring_get_wptr - get write pointer
407 : *
408 : * @ring: amdgpu_ring pointer
409 : *
410 : * Returns the current hardware write pointer
411 : */
412 0 : static uint64_t jpeg_v2_5_dec_ring_get_wptr(struct amdgpu_ring *ring)
413 : {
414 0 : struct amdgpu_device *adev = ring->adev;
415 :
416 0 : if (ring->use_doorbell)
417 0 : return *ring->wptr_cpu_addr;
418 : else
419 0 : return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR);
420 : }
421 :
422 : /**
423 : * jpeg_v2_5_dec_ring_set_wptr - set write pointer
424 : *
425 : * @ring: amdgpu_ring pointer
426 : *
427 : * Commits the write pointer to the hardware
428 : */
429 0 : static void jpeg_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
430 : {
431 0 : struct amdgpu_device *adev = ring->adev;
432 :
433 0 : if (ring->use_doorbell) {
434 0 : *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
435 0 : WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
436 : } else {
437 0 : WREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
438 : }
439 0 : }
440 :
441 : /**
442 : * jpeg_v2_6_dec_ring_insert_start - insert a start command
443 : *
444 : * @ring: amdgpu_ring pointer
445 : *
446 : * Write a start command to the ring.
447 : */
448 0 : static void jpeg_v2_6_dec_ring_insert_start(struct amdgpu_ring *ring)
449 : {
450 0 : amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
451 : 0, 0, PACKETJ_TYPE0));
452 0 : amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
453 :
454 0 : amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
455 : 0, 0, PACKETJ_TYPE0));
456 0 : amdgpu_ring_write(ring, 0x80000000 | (1 << (ring->me * 2 + 14)));
457 0 : }
458 :
459 : /**
460 : * jpeg_v2_6_dec_ring_insert_end - insert a end command
461 : *
462 : * @ring: amdgpu_ring pointer
463 : *
464 : * Write a end command to the ring.
465 : */
466 0 : static void jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring *ring)
467 : {
468 0 : amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
469 : 0, 0, PACKETJ_TYPE0));
470 0 : amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
471 :
472 0 : amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
473 : 0, 0, PACKETJ_TYPE0));
474 0 : amdgpu_ring_write(ring, (1 << (ring->me * 2 + 14)));
475 0 : }
476 :
477 0 : static bool jpeg_v2_5_is_idle(void *handle)
478 : {
479 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
480 0 : int i, ret = 1;
481 :
482 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
483 0 : if (adev->jpeg.harvest_config & (1 << i))
484 0 : continue;
485 :
486 0 : ret &= (((RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS) &
487 0 : UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
488 : UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
489 : }
490 :
491 0 : return ret;
492 : }
493 :
494 0 : static int jpeg_v2_5_wait_for_idle(void *handle)
495 : {
496 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
497 : int i, ret;
498 :
499 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
500 0 : if (adev->jpeg.harvest_config & (1 << i))
501 0 : continue;
502 :
503 0 : ret = SOC15_WAIT_ON_RREG(JPEG, i, mmUVD_JRBC_STATUS,
504 : UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
505 : UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
506 0 : if (ret)
507 : return ret;
508 : }
509 :
510 : return 0;
511 : }
512 :
513 0 : static int jpeg_v2_5_set_clockgating_state(void *handle,
514 : enum amd_clockgating_state state)
515 : {
516 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
517 0 : bool enable = (state == AMD_CG_STATE_GATE);
518 : int i;
519 :
520 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
521 0 : if (adev->jpeg.harvest_config & (1 << i))
522 0 : continue;
523 :
524 0 : if (enable) {
525 0 : if (!jpeg_v2_5_is_idle(handle))
526 : return -EBUSY;
527 0 : jpeg_v2_5_enable_clock_gating(adev, i);
528 : } else {
529 0 : jpeg_v2_5_disable_clock_gating(adev, i);
530 : }
531 : }
532 :
533 : return 0;
534 : }
535 :
536 0 : static int jpeg_v2_5_set_powergating_state(void *handle,
537 : enum amd_powergating_state state)
538 : {
539 0 : struct amdgpu_device *adev = (struct amdgpu_device *)handle;
540 : int ret;
541 :
542 0 : if(state == adev->jpeg.cur_state)
543 : return 0;
544 :
545 0 : if (state == AMD_PG_STATE_GATE)
546 0 : ret = jpeg_v2_5_stop(adev);
547 : else
548 0 : ret = jpeg_v2_5_start(adev);
549 :
550 0 : if(!ret)
551 0 : adev->jpeg.cur_state = state;
552 :
553 : return ret;
554 : }
555 :
556 0 : static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev,
557 : struct amdgpu_irq_src *source,
558 : unsigned type,
559 : enum amdgpu_interrupt_state state)
560 : {
561 0 : return 0;
562 : }
563 :
564 0 : static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
565 : struct amdgpu_irq_src *source,
566 : struct amdgpu_iv_entry *entry)
567 : {
568 : uint32_t ip_instance;
569 :
570 0 : switch (entry->client_id) {
571 : case SOC15_IH_CLIENTID_VCN:
572 : ip_instance = 0;
573 : break;
574 : case SOC15_IH_CLIENTID_VCN1:
575 0 : ip_instance = 1;
576 0 : break;
577 : default:
578 0 : DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
579 0 : return 0;
580 : }
581 :
582 0 : DRM_DEBUG("IH: JPEG TRAP\n");
583 :
584 0 : switch (entry->src_id) {
585 : case VCN_2_0__SRCID__JPEG_DECODE:
586 0 : amdgpu_fence_process(&adev->jpeg.inst[ip_instance].ring_dec);
587 0 : break;
588 : case VCN_2_6__SRCID_DJPEG0_POISON:
589 : case VCN_2_6__SRCID_EJPEG0_POISON:
590 0 : amdgpu_jpeg_process_poison_irq(adev, source, entry);
591 0 : break;
592 : default:
593 0 : DRM_ERROR("Unhandled interrupt: %d %d\n",
594 : entry->src_id, entry->src_data[0]);
595 0 : break;
596 : }
597 :
598 : return 0;
599 : }
600 :
601 : static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
602 : .name = "jpeg_v2_5",
603 : .early_init = jpeg_v2_5_early_init,
604 : .late_init = NULL,
605 : .sw_init = jpeg_v2_5_sw_init,
606 : .sw_fini = jpeg_v2_5_sw_fini,
607 : .hw_init = jpeg_v2_5_hw_init,
608 : .hw_fini = jpeg_v2_5_hw_fini,
609 : .suspend = jpeg_v2_5_suspend,
610 : .resume = jpeg_v2_5_resume,
611 : .is_idle = jpeg_v2_5_is_idle,
612 : .wait_for_idle = jpeg_v2_5_wait_for_idle,
613 : .check_soft_reset = NULL,
614 : .pre_soft_reset = NULL,
615 : .soft_reset = NULL,
616 : .post_soft_reset = NULL,
617 : .set_clockgating_state = jpeg_v2_5_set_clockgating_state,
618 : .set_powergating_state = jpeg_v2_5_set_powergating_state,
619 : };
620 :
621 : static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {
622 : .name = "jpeg_v2_6",
623 : .early_init = jpeg_v2_5_early_init,
624 : .late_init = NULL,
625 : .sw_init = jpeg_v2_5_sw_init,
626 : .sw_fini = jpeg_v2_5_sw_fini,
627 : .hw_init = jpeg_v2_5_hw_init,
628 : .hw_fini = jpeg_v2_5_hw_fini,
629 : .suspend = jpeg_v2_5_suspend,
630 : .resume = jpeg_v2_5_resume,
631 : .is_idle = jpeg_v2_5_is_idle,
632 : .wait_for_idle = jpeg_v2_5_wait_for_idle,
633 : .check_soft_reset = NULL,
634 : .pre_soft_reset = NULL,
635 : .soft_reset = NULL,
636 : .post_soft_reset = NULL,
637 : .set_clockgating_state = jpeg_v2_5_set_clockgating_state,
638 : .set_powergating_state = jpeg_v2_5_set_powergating_state,
639 : };
640 :
641 : static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
642 : .type = AMDGPU_RING_TYPE_VCN_JPEG,
643 : .align_mask = 0xf,
644 : .vmhub = AMDGPU_MMHUB_1,
645 : .get_rptr = jpeg_v2_5_dec_ring_get_rptr,
646 : .get_wptr = jpeg_v2_5_dec_ring_get_wptr,
647 : .set_wptr = jpeg_v2_5_dec_ring_set_wptr,
648 : .emit_frame_size =
649 : SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
650 : SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
651 : 8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */
652 : 18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */
653 : 8 + 16,
654 : .emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */
655 : .emit_ib = jpeg_v2_0_dec_ring_emit_ib,
656 : .emit_fence = jpeg_v2_0_dec_ring_emit_fence,
657 : .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
658 : .test_ring = amdgpu_jpeg_dec_ring_test_ring,
659 : .test_ib = amdgpu_jpeg_dec_ring_test_ib,
660 : .insert_nop = jpeg_v2_0_dec_ring_nop,
661 : .insert_start = jpeg_v2_0_dec_ring_insert_start,
662 : .insert_end = jpeg_v2_0_dec_ring_insert_end,
663 : .pad_ib = amdgpu_ring_generic_pad_ib,
664 : .begin_use = amdgpu_jpeg_ring_begin_use,
665 : .end_use = amdgpu_jpeg_ring_end_use,
666 : .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
667 : .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
668 : .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
669 : };
670 :
671 : static const struct amdgpu_ring_funcs jpeg_v2_6_dec_ring_vm_funcs = {
672 : .type = AMDGPU_RING_TYPE_VCN_JPEG,
673 : .align_mask = 0xf,
674 : .vmhub = AMDGPU_MMHUB_0,
675 : .get_rptr = jpeg_v2_5_dec_ring_get_rptr,
676 : .get_wptr = jpeg_v2_5_dec_ring_get_wptr,
677 : .set_wptr = jpeg_v2_5_dec_ring_set_wptr,
678 : .emit_frame_size =
679 : SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
680 : SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
681 : 8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */
682 : 18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */
683 : 8 + 16,
684 : .emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */
685 : .emit_ib = jpeg_v2_0_dec_ring_emit_ib,
686 : .emit_fence = jpeg_v2_0_dec_ring_emit_fence,
687 : .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
688 : .test_ring = amdgpu_jpeg_dec_ring_test_ring,
689 : .test_ib = amdgpu_jpeg_dec_ring_test_ib,
690 : .insert_nop = jpeg_v2_0_dec_ring_nop,
691 : .insert_start = jpeg_v2_6_dec_ring_insert_start,
692 : .insert_end = jpeg_v2_6_dec_ring_insert_end,
693 : .pad_ib = amdgpu_ring_generic_pad_ib,
694 : .begin_use = amdgpu_jpeg_ring_begin_use,
695 : .end_use = amdgpu_jpeg_ring_end_use,
696 : .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
697 : .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
698 : .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
699 : };
700 :
701 0 : static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
702 : {
703 : int i;
704 :
705 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
706 0 : if (adev->jpeg.harvest_config & (1 << i))
707 0 : continue;
708 0 : if (adev->asic_type == CHIP_ARCTURUS)
709 0 : adev->jpeg.inst[i].ring_dec.funcs = &jpeg_v2_5_dec_ring_vm_funcs;
710 : else /* CHIP_ALDEBARAN */
711 0 : adev->jpeg.inst[i].ring_dec.funcs = &jpeg_v2_6_dec_ring_vm_funcs;
712 0 : adev->jpeg.inst[i].ring_dec.me = i;
713 0 : DRM_INFO("JPEG(%d) JPEG decode is enabled in VM mode\n", i);
714 : }
715 0 : }
716 :
717 : static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = {
718 : .set = jpeg_v2_5_set_interrupt_state,
719 : .process = jpeg_v2_5_process_interrupt,
720 : };
721 :
722 : static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)
723 : {
724 : int i;
725 :
726 0 : for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
727 0 : if (adev->jpeg.harvest_config & (1 << i))
728 0 : continue;
729 :
730 0 : adev->jpeg.inst[i].irq.num_types = 1;
731 0 : adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs;
732 : }
733 : }
734 :
735 : const struct amdgpu_ip_block_version jpeg_v2_5_ip_block =
736 : {
737 : .type = AMD_IP_BLOCK_TYPE_JPEG,
738 : .major = 2,
739 : .minor = 5,
740 : .rev = 0,
741 : .funcs = &jpeg_v2_5_ip_funcs,
742 : };
743 :
744 : const struct amdgpu_ip_block_version jpeg_v2_6_ip_block =
745 : {
746 : .type = AMD_IP_BLOCK_TYPE_JPEG,
747 : .major = 2,
748 : .minor = 6,
749 : .rev = 0,
750 : .funcs = &jpeg_v2_6_ip_funcs,
751 : };
752 :
753 0 : static uint32_t jpeg_v2_6_query_poison_by_instance(struct amdgpu_device *adev,
754 : uint32_t instance, uint32_t sub_block)
755 : {
756 0 : uint32_t poison_stat = 0, reg_value = 0;
757 :
758 0 : switch (sub_block) {
759 : case AMDGPU_JPEG_V2_6_JPEG0:
760 0 : reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG0_STATUS);
761 0 : poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);
762 0 : break;
763 : case AMDGPU_JPEG_V2_6_JPEG1:
764 0 : reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG1_STATUS);
765 0 : poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);
766 0 : break;
767 : default:
768 : break;
769 : }
770 :
771 0 : if (poison_stat)
772 0 : dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",
773 : instance, sub_block);
774 :
775 0 : return poison_stat;
776 : }
777 :
778 0 : static bool jpeg_v2_6_query_ras_poison_status(struct amdgpu_device *adev)
779 : {
780 0 : uint32_t inst = 0, sub = 0, poison_stat = 0;
781 :
782 0 : for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)
783 0 : for (sub = 0; sub < AMDGPU_JPEG_V2_6_MAX_SUB_BLOCK; sub++)
784 0 : poison_stat +=
785 0 : jpeg_v2_6_query_poison_by_instance(adev, inst, sub);
786 :
787 0 : return !!poison_stat;
788 : }
789 :
790 : const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = {
791 : .query_poison_status = jpeg_v2_6_query_ras_poison_status,
792 : };
793 :
794 : static struct amdgpu_jpeg_ras jpeg_v2_6_ras = {
795 : .ras_block = {
796 : .hw_ops = &jpeg_v2_6_ras_hw_ops,
797 : },
798 : };
799 :
800 0 : static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)
801 : {
802 0 : switch (adev->ip_versions[JPEG_HWIP][0]) {
803 : case IP_VERSION(2, 6, 0):
804 0 : adev->jpeg.ras = &jpeg_v2_6_ras;
805 0 : break;
806 : default:
807 : break;
808 : }
809 :
810 0 : if (adev->jpeg.ras) {
811 0 : amdgpu_ras_register_ras_block(adev, &adev->jpeg.ras->ras_block);
812 :
813 0 : strcpy(adev->jpeg.ras->ras_block.ras_comm.name, "jpeg");
814 0 : adev->jpeg.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG;
815 0 : adev->jpeg.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
816 0 : adev->jpeg.ras_if = &adev->jpeg.ras->ras_block.ras_comm;
817 :
818 : /* If don't define special ras_late_init function, use default ras_late_init */
819 0 : if (!adev->jpeg.ras->ras_block.ras_late_init)
820 0 : adev->jpeg.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
821 : }
822 0 : }
|