File Index
Files and directories
Sign in
FILE

jpeg_v5_0_0.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c C
  1/*
  2 * Copyright 2023 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_0_0_offset.h"
 33#include "vcn/vcn_5_0_0_sh_mask.h"
 34#include "ivsrcid/vcn/irqsrcs_vcn_5_0.h"
 35#include "jpeg_v5_0_0.h"
 36
 37static const struct amdgpu_hwip_reg_entry jpeg_reg_list_5_0[] = {
 38	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_POWER_STATUS),
 39	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_INT_STAT),
 40	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_RPTR),
 41	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_WPTR),
 42	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_CNTL),
 43	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_RB_SIZE),
 44	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC_STATUS),
 45	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_ADDR_MODE),
 46	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG),
 47	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_Y_GFX10_TILING_SURFACE),
 48	SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_UV_GFX10_TILING_SURFACE),
 49	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_PITCH),
 50	SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_UV_PITCH),
 51};
 52
 53static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 54static void jpeg_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
 55static int jpeg_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 56				enum amd_powergating_state state);
 57
 58/**
 59 * jpeg_v5_0_0_early_init - set function pointers
 60 *
 61 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
 62 *
 63 * Set ring and irq function pointers
 64 */
 65static int jpeg_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
 66{
 67	struct amdgpu_device *adev = ip_block->adev;
 68
 69	adev->jpeg.num_jpeg_inst = 1;
 70	adev->jpeg.num_jpeg_rings = 1;
 71
 72	jpeg_v5_0_0_set_dec_ring_funcs(adev);
 73	jpeg_v5_0_0_set_irq_funcs(adev);
 74
 75	return 0;
 76}
 77
 78/**
 79 * jpeg_v5_0_0_sw_init - sw init for JPEG block
 80 *
 81 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
 82 *
 83 * Load firmware and sw initialization
 84 */
 85static int jpeg_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
 86{
 87	struct amdgpu_device *adev = ip_block->adev;
 88	struct amdgpu_ring *ring;
 89	int r;
 90
 91	/* JPEG TRAP */
 92	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
 93		VCN_5_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);
 94	if (r)
 95		return r;
 96
 97	r = amdgpu_jpeg_sw_init(adev);
 98	if (r)
 99		return r;
100
101	r = amdgpu_jpeg_resume(adev);
102	if (r)
103		return r;
104
105	ring = adev->jpeg.inst->ring_dec;
106	ring->use_doorbell = true;
107	ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
108	ring->vm_hub = AMDGPU_MMHUB0(0);
109
110	sprintf(ring->name, "jpeg_dec");
111	r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
112			     AMDGPU_RING_PRIO_DEFAULT, NULL);
113	if (r)
114		return r;
115
116	adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
117	adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
118
119	r = amdgpu_jpeg_reg_dump_init(adev, jpeg_reg_list_5_0, ARRAY_SIZE(jpeg_reg_list_5_0));
120	if (r)
121		return r;
122
123	adev->jpeg.supported_reset =
124		amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
125	if (!amdgpu_sriov_vf(adev))
126		adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
127	r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
128
129	return r;
130}
131
132/**
133 * jpeg_v5_0_0_sw_fini - sw fini for JPEG block
134 *
135 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
136 *
137 * JPEG suspend and free up sw allocation
138 */
139static int jpeg_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
140{
141	struct amdgpu_device *adev = ip_block->adev;
142	int r;
143
144	r = amdgpu_jpeg_suspend(adev);
145	if (r)
146		return r;
147
148	amdgpu_jpeg_sysfs_reset_mask_fini(adev);
149	r = amdgpu_jpeg_sw_fini(adev);
150
151	return r;
152}
153
154/**
155 * jpeg_v5_0_0_hw_init - start and test JPEG block
156 *
157 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
158 *
159 */
160static int jpeg_v5_0_0_hw_init(struct amdgpu_ip_block *ip_block)
161{
162	struct amdgpu_device *adev = ip_block->adev;
163	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
164	int r;
165
166	adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
167			(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
168
169	/* Skip ring test because pause DPG is not implemented. */
170	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG)
171		return 0;
172
173	r = amdgpu_ring_test_helper(ring);
174	if (r)
175		return r;
176
177	return 0;
178}
179
180/**
181 * jpeg_v5_0_0_hw_fini - stop the hardware block
182 *
183 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
184 *
185 * Stop the JPEG block, mark ring as not ready any more
186 */
187static int jpeg_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
188{
189	struct amdgpu_device *adev = ip_block->adev;
190
191	cancel_delayed_work_sync(&adev->jpeg.idle_work);
192
193	if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
194	      RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
195		jpeg_v5_0_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
196
197	return 0;
198}
199
200/**
201 * jpeg_v5_0_0_suspend - suspend JPEG block
202 *
203 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
204 *
205 * HW fini and suspend JPEG block
206 */
207static int jpeg_v5_0_0_suspend(struct amdgpu_ip_block *ip_block)
208{
209	int r;
210
211	r = jpeg_v5_0_0_hw_fini(ip_block);
212	if (r)
213		return r;
214
215	r = amdgpu_jpeg_suspend(ip_block->adev);
216
217	return r;
218}
219
220/**
221 * jpeg_v5_0_0_resume - resume JPEG block
222 *
223 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
224 *
225 * Resume firmware and hw init JPEG block
226 */
227static int jpeg_v5_0_0_resume(struct amdgpu_ip_block *ip_block)
228{
229	int r;
230
231	r = amdgpu_jpeg_resume(ip_block->adev);
232	if (r)
233		return r;
234
235	r = jpeg_v5_0_0_hw_init(ip_block);
236
237	return r;
238}
239
240static void jpeg_v5_0_0_disable_clock_gating(struct amdgpu_device *adev)
241{
242	uint32_t data = 0;
243
244	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
245
246	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
247	data &= ~(JPEG_CGC_CTRL__JPEG0_DEC_MODE_MASK
248		| JPEG_CGC_CTRL__JPEG_ENC_MODE_MASK);
249	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
250}
251
252static void jpeg_v5_0_0_enable_clock_gating(struct amdgpu_device *adev)
253{
254	uint32_t data = 0;
255
256	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);
257
258	data |= 1 << JPEG_CGC_CTRL__JPEG0_DEC_MODE__SHIFT;
259	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);
260
261	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);
262	data |= (JPEG_CGC_GATE__JPEG0_DEC_MASK
263		|JPEG_CGC_GATE__JPEG_ENC_MASK
264		|JPEG_CGC_GATE__JMCIF_MASK
265		|JPEG_CGC_GATE__JRBBM_MASK);
266	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
267}
268
269static int jpeg_v5_0_0_disable_power_gating(struct amdgpu_device *adev)
270{
271	uint32_t data = 0;
272
273	data = 1 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT;
274	WREG32_SOC15(JPEG, 0, regUVD_IPX_DLDO_CONFIG, data);
275	SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS, 0,
276			UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
277
278	/* disable anti hang mechanism */
279	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
280		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
281
282	return 0;
283}
284
285static int jpeg_v5_0_0_enable_power_gating(struct amdgpu_device *adev)
286{
287	/* enable anti hang mechanism */
288	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),
289		UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
290		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
291
292	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
293		WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_IPX_DLDO_CONFIG),
294			2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);
295		SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_IPX_DLDO_STATUS,
296			1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT,
297			UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);
298	}
299
300	return 0;
301}
302
303static void jpeg_engine_5_0_0_dpg_clock_gating_mode(struct amdgpu_device *adev,
304	       int inst_idx, uint8_t indirect)
305{
306	uint32_t data = 0;
307
308	// JPEG disable CGC
309	if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
310		data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
311	else
312		data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
313
314	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
315	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
316
317	if (indirect) {
318		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
319
320		// Turn on All JPEG clocks
321		data = 0;
322		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
323	} else {
324		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
325
326		// Turn on All JPEG clocks
327		data = 0;
328		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
329	}
330}
331
332/**
333 * jpeg_v5_0_0_start_dpg_mode - Jpeg start with dpg mode
334 *
335 * @adev: amdgpu_device pointer
336 * @inst_idx: instance number index
337 * @indirect: indirectly write sram
338 *
339 * Start JPEG block with dpg mode
340 */
341static int jpeg_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
342{
343	struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec;
344	uint32_t reg_data = 0;
345
346	jpeg_v5_0_0_enable_power_gating(adev);
347
348	// enable dynamic power gating mode
349	reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
350	reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
351	WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
352
353	if (indirect)
354		adev->jpeg.inst[inst_idx].dpg_sram_curr_addr =
355			(uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr;
356
357	jpeg_engine_5_0_0_dpg_clock_gating_mode(adev, inst_idx, indirect);
358
359	/* MJPEG global tiling registers */
360	if (indirect)
361		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
362			adev->gfx.config.gb_addr_config, indirect);
363	else
364		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
365			adev->gfx.config.gb_addr_config, 1);
366
367	/* enable System Interrupt for JRBC */
368	if (indirect)
369		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_SYS_INT_EN,
370			JPEG_SYS_INT_EN__DJRBC0_MASK, indirect);
371	else
372		WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_SYS_INT_EN,
373			JPEG_SYS_INT_EN__DJRBC0_MASK, 1);
374
375	if (indirect) {
376		/* add nop to workaround PSP size check */
377		ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipUVD_NO_OP, 0, indirect);
378
379		amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0);
380	}
381
382	WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
383		ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
384		VCN_JPEG_DB_CTRL__EN_MASK);
385
386	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0);
387	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
388	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
389		lower_32_bits(ring->gpu_addr));
390	WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
391		upper_32_bits(ring->gpu_addr));
392	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0);
393	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0);
394	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L);
395	WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);
396	ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR);
397
398	return 0;
399}
400
401/**
402 * jpeg_v5_0_0_stop_dpg_mode - Jpeg stop with dpg mode
403 *
404 * @adev: amdgpu_device pointer
405 * @inst_idx: instance number index
406 *
407 * Stop JPEG block with dpg mode
408 */
409static void jpeg_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
410{
411	uint32_t reg_data = 0;
412
413	reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
414	reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
415	WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
416}
417
418/**
419 * jpeg_v5_0_0_start - start JPEG block
420 *
421 * @adev: amdgpu_device pointer
422 *
423 * Setup and start the JPEG block
424 */
425static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
426{
427	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
428	int r;
429
430	if (adev->pm.dpm_enabled)
431		amdgpu_dpm_enable_jpeg(adev, true);
432
433	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
434		r = jpeg_v5_0_0_start_dpg_mode(adev, 0, adev->jpeg.indirect_sram);
435		return r;
436	}
437
438	/* disable power gating */
439	r = jpeg_v5_0_0_disable_power_gating(adev);
440	if (r)
441		return r;
442
443	/* JPEG disable CGC */
444	jpeg_v5_0_0_disable_clock_gating(adev);
445
446	/* MJPEG global tiling registers */
447	WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
448		adev->gfx.config.gb_addr_config);
449
450	/* enable JMI channel */
451	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,
452		~UVD_JMI_CNTL__SOFT_RESET_MASK);
453
454	/* enable System Interrupt for JRBC */
455	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regJPEG_SYS_INT_EN),
456		JPEG_SYS_INT_EN__DJRBC0_MASK,
457		~JPEG_SYS_INT_EN__DJRBC0_MASK);
458
459	WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
460		ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
461		VCN_JPEG_DB_CTRL__EN_MASK);
462
463	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);
464	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
465	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
466		lower_32_bits(ring->gpu_addr));
467	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
468		upper_32_bits(ring->gpu_addr));
469	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR, 0);
470	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, 0);
471	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, 0x00000002L);
472	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);
473	ring->wptr = RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);
474
475	return 0;
476}
477
478/**
479 * jpeg_v5_0_0_stop - stop JPEG block
480 *
481 * @adev: amdgpu_device pointer
482 *
483 * stop the JPEG block
484 */
485static int jpeg_v5_0_0_stop(struct amdgpu_device *adev)
486{
487	int r;
488
489	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
490		jpeg_v5_0_0_stop_dpg_mode(adev, 0);
491	} else {
492
493		/* reset JMI */
494		WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
495			UVD_JMI_CNTL__SOFT_RESET_MASK,
496			~UVD_JMI_CNTL__SOFT_RESET_MASK);
497
498		jpeg_v5_0_0_enable_clock_gating(adev);
499
500		/* enable power gating */
501		r = jpeg_v5_0_0_enable_power_gating(adev);
502		if (r)
503			return r;
504	}
505
506	if (adev->pm.dpm_enabled)
507		amdgpu_dpm_enable_jpeg(adev, false);
508
509	return 0;
510}
511
512/**
513 * jpeg_v5_0_0_dec_ring_get_rptr - get read pointer
514 *
515 * @ring: amdgpu_ring pointer
516 *
517 * Returns the current hardware read pointer
518 */
519static uint64_t jpeg_v5_0_0_dec_ring_get_rptr(struct amdgpu_ring *ring)
520{
521	struct amdgpu_device *adev = ring->adev;
522
523	return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR);
524}
525
526/**
527 * jpeg_v5_0_0_dec_ring_get_wptr - get write pointer
528 *
529 * @ring: amdgpu_ring pointer
530 *
531 * Returns the current hardware write pointer
532 */
533static uint64_t jpeg_v5_0_0_dec_ring_get_wptr(struct amdgpu_ring *ring)
534{
535	struct amdgpu_device *adev = ring->adev;
536
537	if (ring->use_doorbell)
538		return *ring->wptr_cpu_addr;
539	else
540		return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);
541}
542
543/**
544 * jpeg_v5_0_0_dec_ring_set_wptr - set write pointer
545 *
546 * @ring: amdgpu_ring pointer
547 *
548 * Commits the write pointer to the hardware
549 */
550static void jpeg_v5_0_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
551{
552	struct amdgpu_device *adev = ring->adev;
553
554	if (ring->use_doorbell) {
555		*ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
556		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
557	} else {
558		WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
559	}
560}
561
562static bool jpeg_v5_0_0_is_idle(struct amdgpu_ip_block *ip_block)
563{
564	struct amdgpu_device *adev = ip_block->adev;
565	int ret = 1;
566
567	ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &
568		UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
569		UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
570
571	return ret;
572}
573
574static int jpeg_v5_0_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
575{
576	struct amdgpu_device *adev = ip_block->adev;
577
578	return SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_JRBC_STATUS,
579		UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
580		UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
581}
582
583static int jpeg_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
584					  enum amd_clockgating_state state)
585{
586	struct amdgpu_device *adev = ip_block->adev;
587	bool enable = state == AMD_CG_STATE_GATE;
588
589	if (enable) {
590		if (!jpeg_v5_0_0_is_idle(ip_block))
591			return -EBUSY;
592		jpeg_v5_0_0_enable_clock_gating(adev);
593	} else {
594		jpeg_v5_0_0_disable_clock_gating(adev);
595	}
596
597	return 0;
598}
599
600static int jpeg_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
601					  enum amd_powergating_state state)
602{
603	struct amdgpu_device *adev = ip_block->adev;
604	int ret;
605
606	if (state == adev->jpeg.cur_state)
607		return 0;
608
609	if (state == AMD_PG_STATE_GATE)
610		ret = jpeg_v5_0_0_stop(adev);
611	else
612		ret = jpeg_v5_0_0_start(adev);
613
614	if (!ret)
615		adev->jpeg.cur_state = state;
616
617	return ret;
618}
619
620static int jpeg_v5_0_0_set_interrupt_state(struct amdgpu_device *adev,
621					struct amdgpu_irq_src *source,
622					unsigned int type,
623					enum amdgpu_interrupt_state state)
624{
625	return 0;
626}
627
628static int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev,
629				      struct amdgpu_irq_src *source,
630				      struct amdgpu_iv_entry *entry)
631{
632	DRM_DEBUG("IH: JPEG TRAP\n");
633
634	switch (entry->src_id) {
635	case VCN_5_0__SRCID__JPEG_DECODE:
636		amdgpu_fence_process(adev->jpeg.inst->ring_dec);
637		break;
638	default:
639		DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
640			  entry->src_id, entry->src_data[0]);
641		break;
642	}
643
644	return 0;
645}
646
647static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring,
648				  unsigned int vmid,
649				  struct amdgpu_fence *timedout_fence)
650{
651	int r;
652
653	amdgpu_ring_reset_helper_begin(ring, timedout_fence);
654	r = jpeg_v5_0_0_stop(ring->adev);
655	if (r)
656		return r;
657	r = jpeg_v5_0_0_start(ring->adev);
658	if (r)
659		return r;
660	return amdgpu_ring_reset_helper_end(ring, timedout_fence);
661}
662
663static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
664	.name = "jpeg_v5_0_0",
665	.early_init = jpeg_v5_0_0_early_init,
666	.sw_init = jpeg_v5_0_0_sw_init,
667	.sw_fini = jpeg_v5_0_0_sw_fini,
668	.hw_init = jpeg_v5_0_0_hw_init,
669	.hw_fini = jpeg_v5_0_0_hw_fini,
670	.suspend = jpeg_v5_0_0_suspend,
671	.resume = jpeg_v5_0_0_resume,
672	.is_idle = jpeg_v5_0_0_is_idle,
673	.wait_for_idle = jpeg_v5_0_0_wait_for_idle,
674	.set_clockgating_state = jpeg_v5_0_0_set_clockgating_state,
675	.set_powergating_state = jpeg_v5_0_0_set_powergating_state,
676	.dump_ip_state = amdgpu_jpeg_dump_ip_state,
677	.print_ip_state = amdgpu_jpeg_print_ip_state,
678};
679
680static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
681	.type = AMDGPU_RING_TYPE_VCN_JPEG,
682	.align_mask = 0xf,
683	.get_rptr = jpeg_v5_0_0_dec_ring_get_rptr,
684	.get_wptr = jpeg_v5_0_0_dec_ring_get_wptr,
685	.set_wptr = jpeg_v5_0_0_dec_ring_set_wptr,
686	.parse_cs = amdgpu_jpeg_dec_parse_cs,
687	.emit_frame_size =
688		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
689		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
690		8 + /* jpeg_v5_0_0_dec_ring_emit_vm_flush */
691		22 + 22 + /* jpeg_v5_0_0_dec_ring_emit_fence x2 vm fence */
692		8 + 16,
693	.emit_ib_size = 22, /* jpeg_v5_0_0_dec_ring_emit_ib */
694	.emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
695	.emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
696	.emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush,
697	.test_ring = amdgpu_jpeg_dec_ring_test_ring,
698	.test_ib = amdgpu_jpeg_dec_ring_test_ib,
699	.insert_nop = jpeg_v4_0_3_dec_ring_nop,
700	.insert_start = jpeg_v4_0_3_dec_ring_insert_start,
701	.insert_end = jpeg_v4_0_3_dec_ring_insert_end,
702	.pad_ib = amdgpu_ring_generic_pad_ib,
703	.begin_use = amdgpu_jpeg_ring_begin_use,
704	.end_use = amdgpu_jpeg_ring_end_use,
705	.emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
706	.emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
707	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
708	.reset = jpeg_v5_0_0_ring_reset,
709};
710
711static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev)
712{
713	adev->jpeg.inst->ring_dec->funcs = &jpeg_v5_0_0_dec_ring_vm_funcs;
714}
715
716static const struct amdgpu_irq_src_funcs jpeg_v5_0_0_irq_funcs = {
717	.set = jpeg_v5_0_0_set_interrupt_state,
718	.process = jpeg_v5_0_0_process_interrupt,
719};
720
721static void jpeg_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)
722{
723	adev->jpeg.inst->irq.num_types = 1;
724	adev->jpeg.inst->irq.funcs = &jpeg_v5_0_0_irq_funcs;
725}
726
727const struct amdgpu_ip_block_version jpeg_v5_0_0_ip_block = {
728	.type = AMD_IP_BLOCK_TYPE_JPEG,
729	.major = 5,
730	.minor = 0,
731	.rev = 0,
732	.funcs = &jpeg_v5_0_0_ip_funcs,
733};
~/ Read-only file preview.