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