xref: /linux/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_2.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
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_v4_0_3.h"
30 #include "jpeg_v5_0_2.h"
31 #include "mmsch_v5_0.h"
32 
33 #include "vcn/vcn_5_0_0_offset.h"
34 #include "vcn/vcn_5_0_0_sh_mask.h"
35 #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
36 
37 #include "jpeg_v5_0_1.h"
38 
39 static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev);
40 static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev);
41 static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block,
42 					     enum amd_powergating_state state);
43 static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring);
44 
45 static int amdgpu_ih_srcid_jpeg[] = {
46 	VCN_5_0__SRCID__JPEG_DECODE,
47 	VCN_5_0__SRCID__JPEG1_DECODE,
48 	VCN_5_0__SRCID__JPEG2_DECODE,
49 	VCN_5_0__SRCID__JPEG3_DECODE,
50 	VCN_5_0__SRCID__JPEG4_DECODE,
51 	VCN_5_0__SRCID__JPEG5_DECODE,
52 	VCN_5_0__SRCID__JPEG6_DECODE,
53 	VCN_5_0__SRCID__JPEG7_DECODE,
54 	VCN_5_0__SRCID__JPEG8_DECODE,
55 	VCN_5_0__SRCID__JPEG9_DECODE,
56 };
57 
58 static const struct amdgpu_hwip_reg_entry jpeg_reg_list_5_0_2[] = {
59 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_POWER_STATUS),
60 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_INT_STAT),
61 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_RPTR),
62 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR),
63 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS),
64 	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_ADDR_MODE),
65 	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG),
66 	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_Y_GFX10_TILING_SURFACE),
67 	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_UV_GFX10_TILING_SURFACE),
68 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_PITCH),
69 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_UV_PITCH),
70 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_RPTR),
71 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_WPTR),
72 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_STATUS),
73 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_RPTR),
74 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_WPTR),
75 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_STATUS),
76 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_RPTR),
77 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_WPTR),
78 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_STATUS),
79 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_RPTR),
80 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_WPTR),
81 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_STATUS),
82 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_RPTR),
83 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_WPTR),
84 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_STATUS),
85 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_RPTR),
86 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_WPTR),
87 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_STATUS),
88 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_RPTR),
89 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_WPTR),
90 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_STATUS),
91 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_RPTR),
92 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_WPTR),
93 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_STATUS),
94 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_RPTR),
95 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_WPTR),
96 	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_STATUS),
97 };
98 
99 static int jpeg_v5_0_2_core_reg_offset(u32 pipe)
100 {
101 	if (pipe <= AMDGPU_MAX_JPEG_RINGS_4_0_3)
102 		return ((0x40 * pipe) - 0xc80);
103 	else
104 		return ((0x40 * pipe) - 0x440);
105 }
106 
107 /**
108  * jpeg_v5_0_2_early_init - set function pointers
109  *
110  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
111  *
112  * Set ring and irq function pointers
113  */
114 static int jpeg_v5_0_2_early_init(struct amdgpu_ip_block *ip_block)
115 {
116 	struct amdgpu_device *adev = ip_block->adev;
117 
118 	if (!adev->jpeg.num_jpeg_inst || adev->jpeg.num_jpeg_inst > AMDGPU_MAX_JPEG_INSTANCES)
119 		return -ENOENT;
120 
121 	adev->jpeg.num_jpeg_rings = AMDGPU_MAX_JPEG_RINGS;
122 	jpeg_v5_0_2_set_dec_ring_funcs(adev);
123 	jpeg_v5_0_2_set_irq_funcs(adev);
124 
125 	return 0;
126 }
127 
128 /**
129  * jpeg_v5_0_2_sw_init - sw init for JPEG block
130  *
131  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
132  *
133  * Load firmware and sw initialization
134  */
135 static int jpeg_v5_0_2_sw_init(struct amdgpu_ip_block *ip_block)
136 {
137 	struct amdgpu_device *adev = ip_block->adev;
138 	struct amdgpu_ring *ring;
139 	int i, j, r, jpeg_inst;
140 
141 	for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
142 		/* JPEG TRAP */
143 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
144 				      amdgpu_ih_srcid_jpeg[j], &adev->jpeg.inst->irq);
145 		if (r)
146 			return r;
147 	}
148 
149 	r = amdgpu_jpeg_sw_init(adev);
150 	if (r)
151 		return r;
152 
153 	r = amdgpu_jpeg_resume(adev);
154 	if (r)
155 		return r;
156 
157 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
158 		jpeg_inst = GET_INST(JPEG, i);
159 
160 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
161 			ring = &adev->jpeg.inst[i].ring_dec[j];
162 			ring->use_doorbell = false;
163 			ring->vm_hub = AMDGPU_MMHUB0(adev->jpeg.inst[i].aid_id);
164 			ring->doorbell_index =
165 				(adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
166 				1 + j + 11 * jpeg_inst;
167 			sprintf(ring->name, "jpeg_dec_%d.%d", adev->jpeg.inst[i].aid_id, j);
168 			r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
169 					     AMDGPU_RING_PRIO_DEFAULT, NULL);
170 			if (r)
171 				return r;
172 
173 			adev->jpeg.internal.jpeg_pitch[j] =
174 				regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET;
175 			adev->jpeg.inst[i].external.jpeg_pitch[j] =
176 				SOC15_REG_OFFSET1(JPEG, jpeg_inst, regUVD_JRBC_SCRATCH0,
177 						  (j ? jpeg_v5_0_2_core_reg_offset(j) : 0));
178 		}
179 	}
180 
181 	r = amdgpu_jpeg_reg_dump_init(adev, jpeg_reg_list_5_0_2, ARRAY_SIZE(jpeg_reg_list_5_0_2));
182 	if (r)
183 		return r;
184 
185 	adev->jpeg.supported_reset =
186 		amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
187 	adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
188 	r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
189 
190 	return r;
191 }
192 
193 /**
194  * jpeg_v5_0_2_sw_fini - sw fini for JPEG block
195  *
196  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
197  *
198  * JPEG suspend and free up sw allocation
199  */
200 static int jpeg_v5_0_2_sw_fini(struct amdgpu_ip_block *ip_block)
201 {
202 	struct amdgpu_device *adev = ip_block->adev;
203 	int r;
204 
205 	r = amdgpu_jpeg_suspend(adev);
206 	if (r)
207 		return r;
208 
209 	amdgpu_jpeg_sysfs_reset_mask_fini(adev);
210 
211 	r = amdgpu_jpeg_sw_fini(adev);
212 
213 	return r;
214 }
215 
216 /**
217  * jpeg_v5_0_2_hw_init - start and test JPEG block
218  *
219  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
220  *
221  */
222 static int jpeg_v5_0_2_hw_init(struct amdgpu_ip_block *ip_block)
223 {
224 	struct amdgpu_device *adev = ip_block->adev;
225 	struct amdgpu_ring *ring;
226 	int i, j, r, jpeg_inst, tmp;
227 
228 	if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100)
229 		adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED);
230 
231 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
232 		jpeg_inst = GET_INST(JPEG, i);
233 		ring = adev->jpeg.inst[i].ring_dec;
234 
235 		/* Remove JPEG Tile antihang mechanism */
236 		tmp = RREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS);
237 		tmp &= (~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
238 		WREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS, tmp);
239 
240 		if (ring->use_doorbell)
241 			adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
242 				 (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 11 * jpeg_inst,
243 				 adev->jpeg.inst[i].aid_id);
244 
245 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
246 			ring = &adev->jpeg.inst[i].ring_dec[j];
247 			if (ring->use_doorbell)
248 				WREG32_SOC15_OFFSET(VCN, GET_INST(VCN, i), regVCN_JPEG_DB_CTRL,
249 						    ring->pipe,
250 						    ring->doorbell_index <<
251 						    VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
252 						    VCN_JPEG_DB_CTRL__EN_MASK);
253 			r = amdgpu_ring_test_helper(ring);
254 			if (r)
255 				return r;
256 		}
257 	}
258 
259 	return 0;
260 }
261 
262 /**
263  * jpeg_v5_0_2_hw_fini - stop the hardware block
264  *
265  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
266  *
267  * Stop the JPEG block, mark ring as not ready any more
268  */
269 static int jpeg_v5_0_2_hw_fini(struct amdgpu_ip_block *ip_block)
270 {
271 	struct amdgpu_device *adev = ip_block->adev;
272 	int ret = 0;
273 
274 	cancel_delayed_work_sync(&adev->jpeg.idle_work);
275 
276 		if (adev->jpeg.cur_state != AMD_PG_STATE_GATE)
277 			ret = jpeg_v5_0_2_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
278 
279 	return ret;
280 }
281 
282 /**
283  * jpeg_v5_0_2_suspend - suspend JPEG block
284  *
285  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
286  *
287  * HW fini and suspend JPEG block
288  */
289 static int jpeg_v5_0_2_suspend(struct amdgpu_ip_block *ip_block)
290 {
291 	struct amdgpu_device *adev = ip_block->adev;
292 	int r;
293 
294 	r = jpeg_v5_0_2_hw_fini(ip_block);
295 	if (r)
296 		return r;
297 
298 	r = amdgpu_jpeg_suspend(adev);
299 
300 	return r;
301 }
302 
303 /**
304  * jpeg_v5_0_2_resume - resume JPEG block
305  *
306  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
307  *
308  * Resume firmware and hw init JPEG block
309  */
310 static int jpeg_v5_0_2_resume(struct amdgpu_ip_block *ip_block)
311 {
312 	struct amdgpu_device *adev = ip_block->adev;
313 	int r;
314 
315 	r = amdgpu_jpeg_resume(adev);
316 	if (r)
317 		return r;
318 
319 	r = jpeg_v5_0_2_hw_init(ip_block);
320 
321 	return r;
322 }
323 
324 static void jpeg_v5_0_2_init_inst(struct amdgpu_device *adev, int i)
325 {
326 	int jpeg_inst = GET_INST(JPEG, i);
327 
328 	/* disable anti hang mechanism */
329 	WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
330 		 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
331 
332 	/* keep the JPEG in static PG mode */
333 	WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
334 		 ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
335 
336 	/* MJPEG global tiling registers */
337 	WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
338 		     adev->gfx.config.gb_addr_config);
339 
340 	/* enable JMI channel */
341 	WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0,
342 		 ~UVD_JMI_CNTL__SOFT_RESET_MASK);
343 }
344 
345 static void jpeg_v5_0_2_deinit_inst(struct amdgpu_device *adev, int i)
346 {
347 	int jpeg_inst = GET_INST(JPEG, i);
348 	/* reset JMI */
349 	WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL),
350 		 UVD_JMI_CNTL__SOFT_RESET_MASK,
351 		 ~UVD_JMI_CNTL__SOFT_RESET_MASK);
352 
353 	/* enable anti hang mechanism */
354 	WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS),
355 		 UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
356 		 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
357 }
358 
359 static void jpeg_v5_0_2_init_jrbc(struct amdgpu_ring *ring)
360 {
361 	struct amdgpu_device *adev = ring->adev;
362 	u32 reg, data, mask;
363 	int jpeg_inst = GET_INST(JPEG, ring->me);
364 	int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0;
365 
366 	/* enable System Interrupt for JRBC */
367 	reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN);
368 	if (ring->pipe < AMDGPU_MAX_JPEG_RINGS_4_0_3) {
369 		data = JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe;
370 		mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe);
371 		WREG32_P(reg, data, mask);
372 	} else {
373 		data = JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12);
374 		mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12));
375 		WREG32_P(reg, data, mask);
376 	}
377 
378 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
379 			    regUVD_LMI_JRBC_RB_VMID,
380 			    reg_offset, 0);
381 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
382 			    regUVD_JRBC_RB_CNTL,
383 			    reg_offset,
384 			    (0x00000001L | 0x00000002L));
385 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
386 			    regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
387 			    reg_offset, lower_32_bits(ring->gpu_addr));
388 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
389 			    regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
390 			    reg_offset, upper_32_bits(ring->gpu_addr));
391 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
392 			    regUVD_JRBC_RB_RPTR,
393 			    reg_offset, 0);
394 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
395 			    regUVD_JRBC_RB_WPTR,
396 			    reg_offset, 0);
397 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
398 			    regUVD_JRBC_RB_CNTL,
399 			    reg_offset, 0x00000002L);
400 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
401 			    regUVD_JRBC_RB_SIZE,
402 			    reg_offset, ring->ring_size / 4);
403 	ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR,
404 					 reg_offset);
405 }
406 
407 /**
408  * jpeg_v5_0_2_start - start JPEG block
409  *
410  * @adev: amdgpu_device pointer
411  *
412  * Setup and start the JPEG block
413  */
414 static int jpeg_v5_0_2_start(struct amdgpu_device *adev)
415 {
416 	struct amdgpu_ring *ring;
417 	int i, j;
418 
419 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
420 		jpeg_v5_0_2_init_inst(adev, i);
421 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
422 			ring = &adev->jpeg.inst[i].ring_dec[j];
423 			jpeg_v5_0_2_init_jrbc(ring);
424 		}
425 	}
426 
427 	return 0;
428 }
429 
430 /**
431  * jpeg_v5_0_2_stop - stop JPEG block
432  *
433  * @adev: amdgpu_device pointer
434  *
435  * stop the JPEG block
436  */
437 static int jpeg_v5_0_2_stop(struct amdgpu_device *adev)
438 {
439 	int i;
440 
441 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i)
442 		jpeg_v5_0_2_deinit_inst(adev, i);
443 
444 	return 0;
445 }
446 
447 /**
448  * jpeg_v5_0_2_dec_ring_get_rptr - get read pointer
449  *
450  * @ring: amdgpu_ring pointer
451  *
452  * Returns the current hardware read pointer
453  */
454 static uint64_t jpeg_v5_0_2_dec_ring_get_rptr(struct amdgpu_ring *ring)
455 {
456 	struct amdgpu_device *adev = ring->adev;
457 
458 	return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_RPTR,
459 				   ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0);
460 }
461 
462 /**
463  * jpeg_v5_0_2_dec_ring_get_wptr - get write pointer
464  *
465  * @ring: amdgpu_ring pointer
466  *
467  * Returns the current hardware write pointer
468  */
469 static uint64_t jpeg_v5_0_2_dec_ring_get_wptr(struct amdgpu_ring *ring)
470 {
471 	struct amdgpu_device *adev = ring->adev;
472 
473 	if (ring->use_doorbell)
474 		return adev->wb.wb[ring->wptr_offs];
475 
476 	return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_WPTR,
477 				   ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0);
478 }
479 
480 /**
481  * jpeg_v5_0_2_dec_ring_set_wptr - set write pointer
482  *
483  * @ring: amdgpu_ring pointer
484  *
485  * Commits the write pointer to the hardware
486  */
487 static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring)
488 {
489 	struct amdgpu_device *adev = ring->adev;
490 
491 	if (ring->use_doorbell) {
492 		adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
493 		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
494 	} else {
495 		WREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me),
496 				    regUVD_JRBC_RB_WPTR,
497 				    (ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0),
498 				    lower_32_bits(ring->wptr));
499 	}
500 }
501 
502 static bool jpeg_v5_0_2_is_idle(struct amdgpu_ip_block *ip_block)
503 {
504 	struct amdgpu_device *adev = ip_block->adev;
505 	bool ret = false;
506 	int i, j;
507 
508 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
509 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
510 			int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0);
511 
512 			ret &= ((RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, i),
513 				regUVD_JRBC_STATUS, reg_offset) &
514 				UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
515 				UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
516 		}
517 	}
518 
519 	return ret;
520 }
521 
522 static int jpeg_v5_0_2_wait_for_idle(struct amdgpu_ip_block *ip_block)
523 {
524 	struct amdgpu_device *adev = ip_block->adev;
525 	int ret = 0;
526 	int i, j;
527 
528 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
529 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
530 			int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0);
531 
532 			ret &= SOC15_WAIT_ON_RREG_OFFSET(JPEG, GET_INST(JPEG, i),
533 							 regUVD_JRBC_STATUS, reg_offset,
534 							 UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
535 							 UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
536 		}
537 	}
538 	return ret;
539 }
540 
541 static int jpeg_v5_0_2_set_clockgating_state(struct amdgpu_ip_block *ip_block,
542 					     enum amd_clockgating_state state)
543 {
544 	struct amdgpu_device *adev = ip_block->adev;
545 	bool enable = state == AMD_CG_STATE_GATE;
546 
547 	int i;
548 
549 	if (!enable)
550 		return 0;
551 
552 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
553 		if (!jpeg_v5_0_2_is_idle(ip_block))
554 			return -EBUSY;
555 	}
556 
557 	return 0;
558 }
559 
560 static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block,
561 					     enum amd_powergating_state state)
562 {
563 	struct amdgpu_device *adev = ip_block->adev;
564 	int ret;
565 
566 	if (state == adev->jpeg.cur_state)
567 		return 0;
568 
569 	if (state == AMD_PG_STATE_GATE)
570 		ret = jpeg_v5_0_2_stop(adev);
571 	else
572 		ret = jpeg_v5_0_2_start(adev);
573 
574 	if (!ret)
575 		adev->jpeg.cur_state = state;
576 
577 	return ret;
578 }
579 
580 static int jpeg_v5_0_2_set_interrupt_state(struct amdgpu_device *adev,
581 					   struct amdgpu_irq_src *source,
582 					   unsigned int type,
583 					   enum amdgpu_interrupt_state state)
584 {
585 	return 0;
586 }
587 
588 
589 static void jpeg_v5_0_2_core_stall_reset(struct amdgpu_ring *ring)
590 {
591 	struct amdgpu_device *adev = ring->adev;
592 	int jpeg_inst = GET_INST(JPEG, ring->me);
593 	int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0;
594 
595 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
596 			    regUVD_JMI0_UVD_JMI_CLIENT_STALL,
597 			    reg_offset, 0x1F);
598 	SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst,
599 				  regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS,
600 				  reg_offset, 0x1F, 0x1F);
601 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
602 			    regUVD_JMI0_JPEG_LMI_DROP,
603 			    reg_offset, 0x1F);
604 	WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe);
605 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
606 			    regUVD_JMI0_UVD_JMI_CLIENT_STALL,
607 			    reg_offset, 0x00);
608 	WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
609 			    regUVD_JMI0_JPEG_LMI_DROP,
610 			    reg_offset, 0x00);
611 	WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
612 }
613 
614 static int jpeg_v5_0_2_ring_reset(struct amdgpu_ring *ring,
615 				  unsigned int vmid,
616 				  struct amdgpu_fence *timedout_fence)
617 {
618 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
619 	jpeg_v5_0_2_core_stall_reset(ring);
620 	jpeg_v5_0_2_init_jrbc(ring);
621 	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
622 }
623 
624 static const struct amd_ip_funcs jpeg_v5_0_2_ip_funcs = {
625 	.name = "jpeg_v5_0_2",
626 	.early_init = jpeg_v5_0_2_early_init,
627 	.late_init = NULL,
628 	.sw_init = jpeg_v5_0_2_sw_init,
629 	.sw_fini = jpeg_v5_0_2_sw_fini,
630 	.hw_init = jpeg_v5_0_2_hw_init,
631 	.hw_fini = jpeg_v5_0_2_hw_fini,
632 	.suspend = jpeg_v5_0_2_suspend,
633 	.resume = jpeg_v5_0_2_resume,
634 	.is_idle = jpeg_v5_0_2_is_idle,
635 	.wait_for_idle = jpeg_v5_0_2_wait_for_idle,
636 	.soft_reset = NULL,
637 	.set_clockgating_state = jpeg_v5_0_2_set_clockgating_state,
638 	.set_powergating_state = jpeg_v5_0_2_set_powergating_state,
639 	.dump_ip_state = amdgpu_jpeg_dump_ip_state,
640 	.print_ip_state = amdgpu_jpeg_print_ip_state,
641 };
642 
643 static const struct amdgpu_ring_funcs jpeg_v5_0_2_dec_ring_vm_funcs = {
644 	.type = AMDGPU_RING_TYPE_VCN_JPEG,
645 	.align_mask = 0xf,
646 	.no_user_fence = true,
647 	.get_rptr = jpeg_v5_0_2_dec_ring_get_rptr,
648 	.get_wptr = jpeg_v5_0_2_dec_ring_get_wptr,
649 	.set_wptr = jpeg_v5_0_2_dec_ring_set_wptr,
650 	.emit_frame_size =
651 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
652 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
653 		8 + /* jpeg_v5_0_2_dec_ring_emit_vm_flush */
654 		22 + 22 + /* jpeg_v5_0_2_dec_ring_emit_fence x2 vm fence */
655 		8 + 16,
656 	.emit_ib_size = 22, /* jpeg_v5_0_2_dec_ring_emit_ib */
657 	.emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
658 	.emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
659 	.emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush,
660 	.emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush,
661 	.test_ring = amdgpu_jpeg_dec_ring_test_ring,
662 	.test_ib = amdgpu_jpeg_dec_ring_test_ib,
663 	.insert_nop = jpeg_v4_0_3_dec_ring_nop,
664 	.insert_start = jpeg_v4_0_3_dec_ring_insert_start,
665 	.insert_end = jpeg_v4_0_3_dec_ring_insert_end,
666 	.pad_ib = amdgpu_ring_generic_pad_ib,
667 	.begin_use = amdgpu_jpeg_ring_begin_use,
668 	.end_use = amdgpu_jpeg_ring_end_use,
669 	.emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
670 	.emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
671 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
672 	.reset = jpeg_v5_0_2_ring_reset,
673 };
674 
675 static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev)
676 {
677 	int i, j, jpeg_inst;
678 
679 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
680 		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
681 			adev->jpeg.inst[i].ring_dec[j].funcs = &jpeg_v5_0_2_dec_ring_vm_funcs;
682 			adev->jpeg.inst[i].ring_dec[j].me = i;
683 			adev->jpeg.inst[i].ring_dec[j].pipe = j;
684 		}
685 		jpeg_inst = GET_INST(JPEG, i);
686 		adev->jpeg.inst[i].aid_id =
687 			jpeg_inst / adev->jpeg.num_inst_per_aid;
688 	}
689 }
690 
691 static const struct amdgpu_irq_src_funcs jpeg_v5_0_2_irq_funcs = {
692 	.set = jpeg_v5_0_2_set_interrupt_state,
693 	.process = jpeg_v5_0_1_process_interrupt,
694 };
695 
696 static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev)
697 {
698 	int i;
699 
700 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i)
701 		adev->jpeg.inst->irq.num_types += adev->jpeg.num_jpeg_rings;
702 
703 	adev->jpeg.inst->irq.funcs = &jpeg_v5_0_2_irq_funcs;
704 }
705 
706 const struct amdgpu_ip_block_version jpeg_v5_0_2_ip_block = {
707 	.type = AMD_IP_BLOCK_TYPE_JPEG,
708 	.major = 5,
709 	.minor = 0,
710 	.rev = 2,
711 	.funcs = &jpeg_v5_0_2_ip_funcs,
712 };
713 
714 #if 0
715 static int jpeg_v5_0_2_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank,
716 					enum aca_smu_type type, void *data)
717 {
718 	struct aca_bank_info info;
719 	u64 misc0;
720 	int ret;
721 
722 	ret = aca_bank_info_decode(bank, &info);
723 	if (ret)
724 		return ret;
725 
726 	misc0 = bank->regs[ACA_REG_IDX_MISC0];
727 	switch (type) {
728 	case ACA_SMU_TYPE_UE:
729 		bank->aca_err_type = ACA_ERROR_TYPE_UE;
730 		ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE,
731 						1ULL);
732 		break;
733 	case ACA_SMU_TYPE_CE:
734 		bank->aca_err_type = ACA_ERROR_TYPE_CE;
735 		ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type,
736 						ACA_REG__MISC0__ERRCNT(misc0));
737 		break;
738 	default:
739 		return -EINVAL;
740 	}
741 
742 	return ret;
743 }
744 
745 /* reference to smu driver if header file */
746 static int jpeg_v5_0_2_err_codes[] = {
747 	16, 17, 18, 19, 20, 21, 22, 23, /* JPEG[0-9][S|D] */
748 	24, 25, 26, 27, 28, 29, 30, 31,
749 	48, 49, 50, 51,
750 };
751 
752 static bool jpeg_v5_0_2_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank,
753 					enum aca_smu_type type, void *data)
754 {
755 	u32 instlo;
756 
757 	instlo = ACA_REG__IPID__INSTANCEIDLO(bank->regs[ACA_REG_IDX_IPID]);
758 	instlo &= GENMASK(31, 1);
759 
760 	if (instlo != mmSMNAID_AID0_MCA_SMU)
761 		return false;
762 
763 	if (aca_bank_check_error_codes(handle->adev, bank,
764 					jpeg_v5_0_2_err_codes,
765 					ARRAY_SIZE(jpeg_v5_0_2_err_codes)))
766 		return false;
767 
768 	return true;
769 }
770 
771 static const struct aca_bank_ops jpeg_v5_0_2_aca_bank_ops = {
772 	.aca_bank_parser = jpeg_v5_0_2_aca_bank_parser,
773 	.aca_bank_is_valid = jpeg_v5_0_2_aca_bank_is_valid,
774 };
775 
776 static const struct aca_info jpeg_v5_0_2_aca_info = {
777 	.hwip = ACA_HWIP_TYPE_SMU,
778 	.mask = ACA_ERROR_UE_MASK,
779 	.bank_ops = &jpeg_v5_0_2_aca_bank_ops,
780 };
781 #endif
782