xref: /linux/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c (revision 81aa6f190aa0e9ff752fcd0a9eda676458e23133)
1 /*
2  * Copyright 2025 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #include "amdgpu.h"
25 #include "amdgpu_jpeg.h"
26 #include "amdgpu_pm.h"
27 #include "soc15.h"
28 #include "soc15d.h"
29 #include "jpeg_v2_0.h"
30 #include "jpeg_v4_0_3.h"
31 
32 #include "vcn/vcn_5_3_0_offset.h"
33 #include "vcn/vcn_5_3_0_sh_mask.h"
34 #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
35 #include "jpeg_v5_0_0.h"
36 #include "jpeg_v5_3_0.h"
37 
38 static void jpeg_v5_3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
39 static void jpeg_v5_3_0_set_irq_funcs(struct amdgpu_device *adev);
40 static int jpeg_v5_3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
41 				enum amd_powergating_state state);
42 
43 
44 /**
45  * jpeg_v5_3_0_early_init - set function pointers
46  *
47  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
48  *
49  * Set ring and irq function pointers
50  */
51 static int jpeg_v5_3_0_early_init(struct amdgpu_ip_block *ip_block)
52 {
53 	struct amdgpu_device *adev = ip_block->adev;
54 
55 	adev->jpeg.num_jpeg_inst = 1;
56 	adev->jpeg.num_jpeg_rings = 1;
57 
58 	jpeg_v5_3_0_set_dec_ring_funcs(adev);
59 	jpeg_v5_3_0_set_irq_funcs(adev);
60 
61 	return 0;
62 }
63 
64 /**
65  * jpeg_v5_3_0_sw_init - sw init for JPEG block
66  *
67  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
68  *
69  * Load firmware and sw initialization
70  */
71 static int jpeg_v5_3_0_sw_init(struct amdgpu_ip_block *ip_block)
72 {
73 	struct amdgpu_device *adev = ip_block->adev;
74 	struct amdgpu_ring *ring;
75 	int r;
76 
77 	/* JPEG TRAP */
78 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
79 		VCN_5_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);
80 	if (r)
81 		return r;
82 
83 	r = amdgpu_jpeg_sw_init(adev);
84 	if (r)
85 		return r;
86 
87 	r = amdgpu_jpeg_resume(adev);
88 	if (r)
89 		return r;
90 
91 	ring = adev->jpeg.inst->ring_dec;
92 	ring->use_doorbell = true;
93 	ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
94 	ring->vm_hub = AMDGPU_MMHUB0(0);
95 
96 	sprintf(ring->name, "jpeg_dec");
97 	r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
98 			     AMDGPU_RING_PRIO_DEFAULT, NULL);
99 	if (r)
100 		return r;
101 
102 	adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
103 	adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
104 
105 	/* TODO: Add queue reset mask when FW fully supports it */
106 	adev->jpeg.supported_reset =
107 		amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
108 	if (!amdgpu_sriov_vf(adev))
109 		adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
110 	r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
111 	if (r)
112 		return r;
113 	return 0;
114 }
115 
116 /**
117  * jpeg_v5_3_0_sw_fini - sw fini for JPEG block
118  *
119  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
120  *
121  * JPEG suspend and free up sw allocation
122  */
123 static int jpeg_v5_3_0_sw_fini(struct amdgpu_ip_block *ip_block)
124 {
125 	struct amdgpu_device *adev = ip_block->adev;
126 	int r;
127 
128 	r = amdgpu_jpeg_suspend(adev);
129 	if (r)
130 		return r;
131 
132 	amdgpu_jpeg_sysfs_reset_mask_fini(adev);
133 	r = amdgpu_jpeg_sw_fini(adev);
134 
135 	return r;
136 }
137 
138 /**
139  * jpeg_v5_3_0_hw_init - start and test JPEG block
140  *
141  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
142  *
143  */
144 static int jpeg_v5_3_0_hw_init(struct amdgpu_ip_block *ip_block)
145 {
146 	struct amdgpu_device *adev = ip_block->adev;
147 	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
148 	int r;
149 
150 	adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
151 			(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
152 
153 	/* Skip ring test because pause DPG is not implemented. */
154 	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG)
155 		return 0;
156 
157 	r = amdgpu_ring_test_helper(ring);
158 	if (r)
159 		return r;
160 
161 	return 0;
162 }
163 
164 /**
165  * jpeg_v5_3_0_hw_fini - stop the hardware block
166  *
167  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
168  *
169  * Stop the JPEG block, mark ring as not ready any more
170  */
171 static int jpeg_v5_3_0_hw_fini(struct amdgpu_ip_block *ip_block)
172 {
173 	struct amdgpu_device *adev = ip_block->adev;
174 
175 	cancel_delayed_work_sync(&adev->jpeg.idle_work);
176 
177 	if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
178 	      RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS))
179 		jpeg_v5_3_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
180 
181 	return 0;
182 }
183 
184 /**
185  * jpeg_v5_3_0_suspend - suspend JPEG block
186  *
187  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
188  *
189  * HW fini and suspend JPEG block
190  */
191 static int jpeg_v5_3_0_suspend(struct amdgpu_ip_block *ip_block)
192 {
193 	int r;
194 
195 	r = jpeg_v5_3_0_hw_fini(ip_block);
196 	if (r)
197 		return r;
198 
199 	r = amdgpu_jpeg_suspend(ip_block->adev);
200 
201 	return r;
202 }
203 
204 /**
205  * jpeg_v5_3_0_resume - resume JPEG block
206  *
207  * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
208  *
209  * Resume firmware and hw init JPEG block
210  */
211 static int jpeg_v5_3_0_resume(struct amdgpu_ip_block *ip_block)
212 {
213 	int r;
214 
215 	r = amdgpu_jpeg_resume(ip_block->adev);
216 	if (r)
217 		return r;
218 
219 	r = jpeg_v5_3_0_hw_init(ip_block);
220 
221 	return r;
222 }
223 
224 static void jpeg_v5_3_0_disable_clock_gating(struct amdgpu_device *adev)
225 {
226 	uint32_t data = 0;
227 
228 	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
229 
230 	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
231 	data &= ~(JPEG_CGC_CTRL__JPEG0_DEC_MODE_MASK
232 		| JPEG_CGC_CTRL__JPEG_ENC_MODE_MASK);
233 	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
234 }
235 
236 static void jpeg_v5_3_0_enable_clock_gating(struct amdgpu_device *adev)
237 {
238 	uint32_t data = 0;
239 
240 	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
241 
242 	data |= 1 << JPEG_CGC_CTRL__JPEG0_DEC_MODE__SHIFT;
243 	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
244 
245 	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);
246 	data |= (JPEG_CGC_GATE__JPEG0_DEC_MASK
247 		|JPEG_CGC_GATE__JPEG_ENC_MASK
248 		|JPEG_CGC_GATE__JMCIF_MASK
249 		|JPEG_CGC_GATE__JRBBM_MASK);
250 	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
251 }
252 
253 static int jpeg_v5_3_0_disable_power_gating(struct amdgpu_device *adev)
254 {
255 	uint32_t data = 0;
256 
257 	data = 1 << UVD_IPX_DLDO_CONFIG_ONO1__ONO1_PWR_CONFIG__SHIFT;
258 	WREG32_SOC15(JPEG, 0, regUVD_IPX_DLDO_CONFIG_ONO1, data);
259 	SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS, 0,
260 			UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
261 
262 	/* disable anti hang mechanism */
263 	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
264 		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
265 
266 	return 0;
267 }
268 
269 static int jpeg_v5_3_0_enable_power_gating(struct amdgpu_device *adev)
270 {
271 	/* enable anti hang mechanism */
272 	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),
273 		UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
274 		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
275 
276 	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
277 		WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_IPX_DLDO_CONFIG_ONO1),
278 			2 << UVD_IPX_DLDO_CONFIG_ONO1__ONO1_PWR_CONFIG__SHIFT);
279 		SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS,
280 			1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT,
281 			UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
282 	}
283 
284 	return 0;
285 }
286 
287 static void jpeg_engine_5_0_0_dpg_clock_gating_mode(struct amdgpu_device *adev,
288 	       int inst_idx, uint8_t indirect)
289 {
290 	uint32_t data = 0;
291 
292 	// JPEG disable CGC
293 	if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
294 		data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
295 	else
296 		data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
297 
298 	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
299 	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
300 
301 	if (indirect) {
302 		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
303 
304 		// Turn on All JPEG clocks
305 		data = 0;
306 		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
307 	} else {
308 		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
309 
310 		// Turn on All JPEG clocks
311 		data = 0;
312 		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
313 	}
314 }
315 
316 /**
317  * jpeg_v5_3_0_start_dpg_mode - Jpeg start with dpg mode
318  *
319  * @adev: amdgpu_device pointer
320  * @inst_idx: instance number index
321  * @indirect: indirectly write sram
322  *
323  * Start JPEG block with dpg mode
324  */
325 static int jpeg_v5_3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
326 {
327 	struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec;
328 	uint32_t reg_data = 0;
329 
330 	jpeg_v5_3_0_enable_power_gating(adev);
331 
332 	// enable dynamic power gating mode
333 	reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
334 	reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
335 	WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
336 
337 	if (indirect)
338 		adev->jpeg.inst[inst_idx].dpg_sram_curr_addr =
339 			(uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr;
340 
341 	jpeg_engine_5_0_0_dpg_clock_gating_mode(adev, inst_idx, indirect);
342 
343 	/* MJPEG global tiling registers */
344 	if (indirect)
345 		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
346 			adev->gfx.config.gb_addr_config, indirect);
347 	else
348 		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
349 			adev->gfx.config.gb_addr_config, 1);
350 
351 	/* enable System Interrupt for JRBC */
352 	if (indirect)
353 		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_SYS_INT_EN,
354 			JPEG_SYS_INT_EN__DJRBC0_MASK, indirect);
355 	else
356 		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_SYS_INT_EN,
357 			JPEG_SYS_INT_EN__DJRBC0_MASK, 1);
358 
359 	if (indirect) {
360 		/* add nop to workaround PSP size check */
361 		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipUVD_NO_OP, 0, indirect);
362 
363 		amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0);
364 	}
365 
366 	WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
367 		ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
368 		VCN_JPEG_DB_CTRL__EN_MASK);
369 
370 	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0);
371 	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
372 	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
373 		lower_32_bits(ring->gpu_addr));
374 	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
375 		upper_32_bits(ring->gpu_addr));
376 	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_RPTR, 0);
377 	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_WPTR, 0);
378 	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_CNTL, 0x00000002L);
379 	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_SIZE, ring->ring_size / 4);
380 	ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC0_UVD_JRBC_RB_WPTR);
381 
382 	return 0;
383 }
384 
385 /**
386  * jpeg_v5_3_0_stop_dpg_mode - Jpeg stop with dpg mode
387  *
388  * @adev: amdgpu_device pointer
389  * @inst_idx: instance number index
390  *
391  * Stop JPEG block with dpg mode
392  */
393 static void jpeg_v5_3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
394 {
395 	uint32_t reg_data = 0;
396 
397 	reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
398 	reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
399 	WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
400 }
401 
402 /**
403  * jpeg_v5_3_0_start - start JPEG block
404  *
405  * @adev: amdgpu_device pointer
406  *
407  * Setup and start the JPEG block
408  */
409 static int jpeg_v5_3_0_start(struct amdgpu_device *adev)
410 {
411 	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
412 	int r;
413 
414 	if (adev->pm.dpm_enabled)
415 		amdgpu_dpm_enable_jpeg(adev, true);
416 
417 	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
418 		r = jpeg_v5_3_0_start_dpg_mode(adev, 0, adev->jpeg.indirect_sram);
419 		return r;
420 	}
421 
422 	/* disable power gating */
423 	r = jpeg_v5_3_0_disable_power_gating(adev);
424 	if (r)
425 		return r;
426 
427 	/* JPEG disable CGC */
428 	jpeg_v5_3_0_disable_clock_gating(adev);
429 
430 	/* MJPEG global tiling registers */
431 	WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
432 		adev->gfx.config.gb_addr_config);
433 
434 	/* enable JMI channel */
435 	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,
436 		~UVD_JMI_CNTL__SOFT_RESET_MASK);
437 
438 	/* enable System Interrupt for JRBC */
439 	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regJPEG_SYS_INT_EN),
440 		JPEG_SYS_INT_EN__DJRBC0_MASK,
441 		~JPEG_SYS_INT_EN__DJRBC0_MASK);
442 
443 	WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
444 		ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
445 		VCN_JPEG_DB_CTRL__EN_MASK);
446 
447 	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);
448 	WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
449 	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
450 		lower_32_bits(ring->gpu_addr));
451 	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
452 		upper_32_bits(ring->gpu_addr));
453 	WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_RPTR, 0);
454 	WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR, 0);
455 	WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_CNTL, 0x00000002L);
456 	WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_SIZE, ring->ring_size / 4);
457 	ring->wptr = RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR);
458 
459 	return 0;
460 }
461 
462 /**
463  * jpeg_v5_3_0_stop - stop JPEG block
464  *
465  * @adev: amdgpu_device pointer
466  *
467  * stop the JPEG block
468  */
469 static int jpeg_v5_3_0_stop(struct amdgpu_device *adev)
470 {
471 	int r;
472 
473 	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
474 		jpeg_v5_3_0_stop_dpg_mode(adev, 0);
475 	} else {
476 
477 		/* reset JMI */
478 		WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
479 			UVD_JMI_CNTL__SOFT_RESET_MASK,
480 			~UVD_JMI_CNTL__SOFT_RESET_MASK);
481 
482 		jpeg_v5_3_0_enable_clock_gating(adev);
483 
484 		/* enable power gating */
485 		r = jpeg_v5_3_0_enable_power_gating(adev);
486 		if (r)
487 			return r;
488 	}
489 
490 	if (adev->pm.dpm_enabled)
491 		amdgpu_dpm_enable_jpeg(adev, false);
492 
493 	return 0;
494 }
495 
496 /**
497  * jpeg_v5_3_0_dec_ring_get_rptr - get read pointer
498  *
499  * @ring: amdgpu_ring pointer
500  *
501  * Returns the current hardware read pointer
502  */
503 static uint64_t jpeg_v5_3_0_dec_ring_get_rptr(struct amdgpu_ring *ring)
504 {
505 	struct amdgpu_device *adev = ring->adev;
506 
507 	return RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_RPTR);
508 }
509 
510 /**
511  * jpeg_v5_3_0_dec_ring_get_wptr - get write pointer
512  *
513  * @ring: amdgpu_ring pointer
514  *
515  * Returns the current hardware write pointer
516  */
517 static uint64_t jpeg_v5_3_0_dec_ring_get_wptr(struct amdgpu_ring *ring)
518 {
519 	struct amdgpu_device *adev = ring->adev;
520 
521 	if (ring->use_doorbell)
522 		return *ring->wptr_cpu_addr;
523 	else
524 		return RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR);
525 }
526 
527 /**
528  * jpeg_v5_3_0_dec_ring_set_wptr - set write pointer
529  *
530  * @ring: amdgpu_ring pointer
531  *
532  * Commits the write pointer to the hardware
533  */
534 static void jpeg_v5_3_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
535 {
536 	struct amdgpu_device *adev = ring->adev;
537 
538 	if (ring->use_doorbell) {
539 		*ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
540 		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
541 	} else {
542 		WREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
543 	}
544 }
545 
546 static bool jpeg_v5_3_0_is_idle(struct amdgpu_ip_block *ip_block)
547 {
548 	struct amdgpu_device *adev = ip_block->adev;
549 	int ret = 1;
550 
551 	ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS) &
552 		UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
553 		UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
554 
555 	return ret;
556 }
557 
558 static int jpeg_v5_3_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
559 {
560 	struct amdgpu_device *adev = ip_block->adev;
561 
562 	return SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS,
563 		UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
564 		UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
565 }
566 
567 static int jpeg_v5_3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
568 					  enum amd_clockgating_state state)
569 {
570 	struct amdgpu_device *adev = ip_block->adev;
571 	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
572 
573 	if (enable) {
574 		if (!jpeg_v5_3_0_is_idle(ip_block))
575 			return -EBUSY;
576 		jpeg_v5_3_0_enable_clock_gating(adev);
577 	} else {
578 		jpeg_v5_3_0_disable_clock_gating(adev);
579 	}
580 
581 	return 0;
582 }
583 
584 static int jpeg_v5_3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
585 					  enum amd_powergating_state state)
586 {
587 	struct amdgpu_device *adev = ip_block->adev;
588 	int ret;
589 
590 	if (state == adev->jpeg.cur_state)
591 		return 0;
592 
593 	if (state == AMD_PG_STATE_GATE)
594 		ret = jpeg_v5_3_0_stop(adev);
595 	else
596 		ret = jpeg_v5_3_0_start(adev);
597 
598 	if (!ret)
599 		adev->jpeg.cur_state = state;
600 
601 	return ret;
602 }
603 
604 static int jpeg_v5_3_0_set_interrupt_state(struct amdgpu_device *adev,
605 					struct amdgpu_irq_src *source,
606 					unsigned int type,
607 					enum amdgpu_interrupt_state state)
608 {
609 	return 0;
610 }
611 
612 static int jpeg_v5_3_0_ring_reset(struct amdgpu_ring *ring,
613 				  unsigned int vmid,
614 				  struct amdgpu_fence *timedout_fence)
615 {
616 	int r;
617 
618 	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
619 	r = jpeg_v5_3_0_stop(ring->adev);
620 	if (r)
621 		return r;
622 	r = jpeg_v5_3_0_start(ring->adev);
623 	if (r)
624 		return r;
625 	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
626 }
627 
628 static const struct amd_ip_funcs jpeg_v5_3_0_ip_funcs = {
629 	.name = "jpeg_v5_3_0",
630 	.early_init = jpeg_v5_3_0_early_init,
631 	.sw_init = jpeg_v5_3_0_sw_init,
632 	.sw_fini = jpeg_v5_3_0_sw_fini,
633 	.hw_init = jpeg_v5_3_0_hw_init,
634 	.hw_fini = jpeg_v5_3_0_hw_fini,
635 	.suspend = jpeg_v5_3_0_suspend,
636 	.resume = jpeg_v5_3_0_resume,
637 	.is_idle = jpeg_v5_3_0_is_idle,
638 	.wait_for_idle = jpeg_v5_3_0_wait_for_idle,
639 	.set_clockgating_state = jpeg_v5_3_0_set_clockgating_state,
640 	.set_powergating_state = jpeg_v5_3_0_set_powergating_state,
641 };
642 
643 static const struct amdgpu_ring_funcs jpeg_v5_3_0_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_3_0_dec_ring_get_rptr,
648 	.get_wptr = jpeg_v5_3_0_dec_ring_get_wptr,
649 	.set_wptr = jpeg_v5_3_0_dec_ring_set_wptr,
650 	.parse_cs = amdgpu_jpeg_dec_parse_cs,
651 	.emit_frame_size =
652 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
653 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
654 		8 + /* jpeg_v5_3_0_dec_ring_emit_vm_flush */
655 		22 + 22 + /* jpeg_v5_3_0_dec_ring_emit_fence x2 vm fence */
656 		8 + 16,
657 	.emit_ib_size = 22, /* jpeg_v5_3_0_dec_ring_emit_ib */
658 	.emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
659 	.emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
660 	.emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_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_3_0_ring_reset,
673 };
674 
675 static void jpeg_v5_3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
676 {
677 	adev->jpeg.inst->ring_dec->funcs = &jpeg_v5_3_0_dec_ring_vm_funcs;
678 }
679 
680 static const struct amdgpu_irq_src_funcs jpeg_v5_3_0_irq_funcs = {
681 	.set = jpeg_v5_3_0_set_interrupt_state,
682 	.process = jpeg_v5_0_0_process_interrupt,
683 };
684 
685 static void jpeg_v5_3_0_set_irq_funcs(struct amdgpu_device *adev)
686 {
687 	adev->jpeg.inst->irq.num_types = 1;
688 	adev->jpeg.inst->irq.funcs = &jpeg_v5_3_0_irq_funcs;
689 }
690 
691 const struct amdgpu_ip_block_version jpeg_v5_3_0_ip_block = {
692 	.type = AMD_IP_BLOCK_TYPE_JPEG,
693 	.major = 5,
694 	.minor = 3,
695 	.rev = 0,
696 	.funcs = &jpeg_v5_3_0_ip_funcs,
697 };
698