xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c (revision 769218209d8f00a4003dc9ee351198a473043eaf)
1bb0db70fSLeo Liu /*
2bb0db70fSLeo Liu  * Copyright 2019 Advanced Micro Devices, Inc.
3bb0db70fSLeo Liu  *
4bb0db70fSLeo Liu  * Permission is hereby granted, free of charge, to any person obtaining a
5bb0db70fSLeo Liu  * copy of this software and associated documentation files (the "Software"),
6bb0db70fSLeo Liu  * to deal in the Software without restriction, including without limitation
7bb0db70fSLeo Liu  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bb0db70fSLeo Liu  * and/or sell copies of the Software, and to permit persons to whom the
9bb0db70fSLeo Liu  * Software is furnished to do so, subject to the following conditions:
10bb0db70fSLeo Liu  *
11bb0db70fSLeo Liu  * The above copyright notice and this permission notice shall be included in
12bb0db70fSLeo Liu  * all copies or substantial portions of the Software.
13bb0db70fSLeo Liu  *
14bb0db70fSLeo Liu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bb0db70fSLeo Liu  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bb0db70fSLeo Liu  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bb0db70fSLeo Liu  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bb0db70fSLeo Liu  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bb0db70fSLeo Liu  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bb0db70fSLeo Liu  * OTHER DEALINGS IN THE SOFTWARE.
21bb0db70fSLeo Liu  *
22bb0db70fSLeo Liu  */
23bb0db70fSLeo Liu 
24bb0db70fSLeo Liu #include "amdgpu.h"
25bb0db70fSLeo Liu #include "amdgpu_jpeg.h"
26*ff65ae25SDavid (Ming Qiang) Wu #include "amdgpu_cs.h"
27bb0db70fSLeo Liu #include "soc15.h"
28bb0db70fSLeo Liu #include "soc15d.h"
29d58ed707SLeo Liu #include "vcn_v1_0.h"
30232e5d45SJames Zhu #include "jpeg_v1_0.h"
31bb0db70fSLeo Liu 
32bb0db70fSLeo Liu #include "vcn/vcn_1_0_offset.h"
33bb0db70fSLeo Liu #include "vcn/vcn_1_0_sh_mask.h"
34bb0db70fSLeo Liu 
35bb0db70fSLeo Liu static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
36bb0db70fSLeo Liu static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev);
37187561ddSVeerabadhran G static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring);
38*ff65ae25SDavid (Ming Qiang) Wu static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,
39*ff65ae25SDavid (Ming Qiang) Wu 				     struct amdgpu_job *job,
40*ff65ae25SDavid (Ming Qiang) Wu 				     struct amdgpu_ib *ib);
41bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring * ring,uint32_t * ptr,uint32_t reg_offset,uint32_t val)42bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
43bb0db70fSLeo Liu {
44bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
45bb0db70fSLeo Liu 	ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
46bb0db70fSLeo Liu 	if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
47bb0db70fSLeo Liu 		((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
48bb0db70fSLeo Liu 		ring->ring[(*ptr)++] = 0;
49bb0db70fSLeo Liu 		ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0);
50bb0db70fSLeo Liu 	} else {
51bb0db70fSLeo Liu 		ring->ring[(*ptr)++] = reg_offset;
52bb0db70fSLeo Liu 		ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0);
53bb0db70fSLeo Liu 	}
54bb0db70fSLeo Liu 	ring->ring[(*ptr)++] = val;
55bb0db70fSLeo Liu }
56bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_set_patch_ring(struct amdgpu_ring * ring,uint32_t ptr)57bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr)
58bb0db70fSLeo Liu {
59bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
60bb0db70fSLeo Liu 
61bb0db70fSLeo Liu 	uint32_t reg, reg_offset, val, mask, i;
62bb0db70fSLeo Liu 
63bb0db70fSLeo Liu 	// 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW
64bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW);
65bb0db70fSLeo Liu 	reg_offset = (reg << 2);
66bb0db70fSLeo Liu 	val = lower_32_bits(ring->gpu_addr);
67bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
68bb0db70fSLeo Liu 
69bb0db70fSLeo Liu 	// 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH
70bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH);
71bb0db70fSLeo Liu 	reg_offset = (reg << 2);
72bb0db70fSLeo Liu 	val = upper_32_bits(ring->gpu_addr);
73bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
74bb0db70fSLeo Liu 
75bb0db70fSLeo Liu 	// 3rd to 5th: issue MEM_READ commands
76bb0db70fSLeo Liu 	for (i = 0; i <= 2; i++) {
77bb0db70fSLeo Liu 		ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2);
78bb0db70fSLeo Liu 		ring->ring[ptr++] = 0;
79bb0db70fSLeo Liu 	}
80bb0db70fSLeo Liu 
81bb0db70fSLeo Liu 	// 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability
82bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
83bb0db70fSLeo Liu 	reg_offset = (reg << 2);
84bb0db70fSLeo Liu 	val = 0x13;
85bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
86bb0db70fSLeo Liu 
87bb0db70fSLeo Liu 	// 7th: program mmUVD_JRBC_RB_REF_DATA
88bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA);
89bb0db70fSLeo Liu 	reg_offset = (reg << 2);
90bb0db70fSLeo Liu 	val = 0x1;
91bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
92bb0db70fSLeo Liu 
93bb0db70fSLeo Liu 	// 8th: issue conditional register read mmUVD_JRBC_RB_CNTL
94bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
95bb0db70fSLeo Liu 	reg_offset = (reg << 2);
96bb0db70fSLeo Liu 	val = 0x1;
97bb0db70fSLeo Liu 	mask = 0x1;
98bb0db70fSLeo Liu 
99bb0db70fSLeo Liu 	ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0);
100bb0db70fSLeo Liu 	ring->ring[ptr++] = 0x01400200;
101bb0db70fSLeo Liu 	ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0);
102bb0db70fSLeo Liu 	ring->ring[ptr++] = val;
103bb0db70fSLeo Liu 	ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
104bb0db70fSLeo Liu 	if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
105bb0db70fSLeo Liu 		((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
106bb0db70fSLeo Liu 		ring->ring[ptr++] = 0;
107bb0db70fSLeo Liu 		ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3);
108bb0db70fSLeo Liu 	} else {
109bb0db70fSLeo Liu 		ring->ring[ptr++] = reg_offset;
110bb0db70fSLeo Liu 		ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3);
111bb0db70fSLeo Liu 	}
112bb0db70fSLeo Liu 	ring->ring[ptr++] = mask;
113bb0db70fSLeo Liu 
114bb0db70fSLeo Liu 	//9th to 21st: insert no-op
115bb0db70fSLeo Liu 	for (i = 0; i <= 12; i++) {
116bb0db70fSLeo Liu 		ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
117bb0db70fSLeo Liu 		ring->ring[ptr++] = 0;
118bb0db70fSLeo Liu 	}
119bb0db70fSLeo Liu 
120bb0db70fSLeo Liu 	//22nd: reset mmUVD_JRBC_RB_RPTR
121bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_RPTR);
122bb0db70fSLeo Liu 	reg_offset = (reg << 2);
123bb0db70fSLeo Liu 	val = 0;
124bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
125bb0db70fSLeo Liu 
126bb0db70fSLeo Liu 	//23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch
127bb0db70fSLeo Liu 	reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
128bb0db70fSLeo Liu 	reg_offset = (reg << 2);
129bb0db70fSLeo Liu 	val = 0x12;
130bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
131bb0db70fSLeo Liu }
132bb0db70fSLeo Liu 
133bb0db70fSLeo Liu /**
134bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_get_rptr - get read pointer
135bb0db70fSLeo Liu  *
136bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
137bb0db70fSLeo Liu  *
138bb0db70fSLeo Liu  * Returns the current hardware read pointer
139bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_get_rptr(struct amdgpu_ring * ring)140bb0db70fSLeo Liu static uint64_t jpeg_v1_0_decode_ring_get_rptr(struct amdgpu_ring *ring)
141bb0db70fSLeo Liu {
142bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
143bb0db70fSLeo Liu 
144bb0db70fSLeo Liu 	return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR);
145bb0db70fSLeo Liu }
146bb0db70fSLeo Liu 
147bb0db70fSLeo Liu /**
148bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_get_wptr - get write pointer
149bb0db70fSLeo Liu  *
150bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
151bb0db70fSLeo Liu  *
152bb0db70fSLeo Liu  * Returns the current hardware write pointer
153bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_get_wptr(struct amdgpu_ring * ring)154bb0db70fSLeo Liu static uint64_t jpeg_v1_0_decode_ring_get_wptr(struct amdgpu_ring *ring)
155bb0db70fSLeo Liu {
156bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
157bb0db70fSLeo Liu 
158bb0db70fSLeo Liu 	return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
159bb0db70fSLeo Liu }
160bb0db70fSLeo Liu 
161bb0db70fSLeo Liu /**
162bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_set_wptr - set write pointer
163bb0db70fSLeo Liu  *
164bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
165bb0db70fSLeo Liu  *
166bb0db70fSLeo Liu  * Commits the write pointer to the hardware
167bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_set_wptr(struct amdgpu_ring * ring)168bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_set_wptr(struct amdgpu_ring *ring)
169bb0db70fSLeo Liu {
170bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
171bb0db70fSLeo Liu 
172bb0db70fSLeo Liu 	WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
173bb0db70fSLeo Liu }
174bb0db70fSLeo Liu 
175bb0db70fSLeo Liu /**
176bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_insert_start - insert a start command
177bb0db70fSLeo Liu  *
178bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
179bb0db70fSLeo Liu  *
180bb0db70fSLeo Liu  * Write a start command to the ring.
181bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_insert_start(struct amdgpu_ring * ring)182bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_insert_start(struct amdgpu_ring *ring)
183bb0db70fSLeo Liu {
184bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
185bb0db70fSLeo Liu 
186bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
187bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
188bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x68e04);
189bb0db70fSLeo Liu 
190bb0db70fSLeo Liu 	amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
191bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x80010000);
192bb0db70fSLeo Liu }
193bb0db70fSLeo Liu 
194bb0db70fSLeo Liu /**
195bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_insert_end - insert a end command
196bb0db70fSLeo Liu  *
197bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
198bb0db70fSLeo Liu  *
199bb0db70fSLeo Liu  * Write a end command to the ring.
200bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_insert_end(struct amdgpu_ring * ring)201bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_insert_end(struct amdgpu_ring *ring)
202bb0db70fSLeo Liu {
203bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
204bb0db70fSLeo Liu 
205bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
206bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
207bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x68e04);
208bb0db70fSLeo Liu 
209bb0db70fSLeo Liu 	amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
210bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x00010000);
211bb0db70fSLeo Liu }
212bb0db70fSLeo Liu 
213bb0db70fSLeo Liu /**
214bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_emit_fence - emit an fence & trap command
215bb0db70fSLeo Liu  *
216bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
2178608c861SLee Jones  * @addr: address
2188608c861SLee Jones  * @seq: sequence number
2198608c861SLee Jones  * @flags: fence related flags
220bb0db70fSLeo Liu  *
221bb0db70fSLeo Liu  * Write a fence and a trap command to the ring.
222bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_emit_fence(struct amdgpu_ring * ring,u64 addr,u64 seq,unsigned flags)223bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
224bb0db70fSLeo Liu 				     unsigned flags)
225bb0db70fSLeo Liu {
226bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
227bb0db70fSLeo Liu 
228bb0db70fSLeo Liu 	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
229bb0db70fSLeo Liu 
230bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
231bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA0), 0, 0, PACKETJ_TYPE0));
232bb0db70fSLeo Liu 	amdgpu_ring_write(ring, seq);
233bb0db70fSLeo Liu 
234bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
235bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA1), 0, 0, PACKETJ_TYPE0));
236bb0db70fSLeo Liu 	amdgpu_ring_write(ring, seq);
237bb0db70fSLeo Liu 
238bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
239bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
240bb0db70fSLeo Liu 	amdgpu_ring_write(ring, lower_32_bits(addr));
241bb0db70fSLeo Liu 
242bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
243bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
244bb0db70fSLeo Liu 	amdgpu_ring_write(ring, upper_32_bits(addr));
245bb0db70fSLeo Liu 
246bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
247bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, 0, PACKETJ_TYPE0));
248bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x8);
249bb0db70fSLeo Liu 
250bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
251bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
252bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0);
253bb0db70fSLeo Liu 
254bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
255bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
256bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x01400200);
257bb0db70fSLeo Liu 
258bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
259bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
260bb0db70fSLeo Liu 	amdgpu_ring_write(ring, seq);
261bb0db70fSLeo Liu 
262bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
263bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
264bb0db70fSLeo Liu 	amdgpu_ring_write(ring, lower_32_bits(addr));
265bb0db70fSLeo Liu 
266bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
267bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
268bb0db70fSLeo Liu 	amdgpu_ring_write(ring, upper_32_bits(addr));
269bb0db70fSLeo Liu 
270bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
271bb0db70fSLeo Liu 		PACKETJ(0, 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE2));
272bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0xffffffff);
273bb0db70fSLeo Liu 
274bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
275bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
276bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x3fbc);
277bb0db70fSLeo Liu 
278bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
279bb0db70fSLeo Liu 		PACKETJ(0, 0, 0, PACKETJ_TYPE0));
280bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x1);
281bb0db70fSLeo Liu 
282bb0db70fSLeo Liu 	/* emit trap */
283bb0db70fSLeo Liu 	amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
284bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0);
285bb0db70fSLeo Liu }
286bb0db70fSLeo Liu 
287bb0db70fSLeo Liu /**
288bb0db70fSLeo Liu  * jpeg_v1_0_decode_ring_emit_ib - execute indirect buffer
289bb0db70fSLeo Liu  *
290bb0db70fSLeo Liu  * @ring: amdgpu_ring pointer
2918608c861SLee Jones  * @job: job to retrieve vmid from
292bb0db70fSLeo Liu  * @ib: indirect buffer to execute
2938608c861SLee Jones  * @flags: unused
294bb0db70fSLeo Liu  *
295bb0db70fSLeo Liu  * Write ring commands to execute the indirect buffer.
296bb0db70fSLeo Liu  */
jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring * ring,struct amdgpu_job * job,struct amdgpu_ib * ib,uint32_t flags)297bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring *ring,
298bb0db70fSLeo Liu 					struct amdgpu_job *job,
299bb0db70fSLeo Liu 					struct amdgpu_ib *ib,
300bb0db70fSLeo Liu 					uint32_t flags)
301bb0db70fSLeo Liu {
302bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
303bb0db70fSLeo Liu 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
304bb0db70fSLeo Liu 
305bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
306bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0));
307*ff65ae25SDavid (Ming Qiang) Wu 	if (ring->funcs->parse_cs)
308*ff65ae25SDavid (Ming Qiang) Wu 		amdgpu_ring_write(ring, 0);
309*ff65ae25SDavid (Ming Qiang) Wu 	else
310bb0db70fSLeo Liu 		amdgpu_ring_write(ring, (vmid | (vmid << 4)));
311bb0db70fSLeo Liu 
312bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
313bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0));
314bb0db70fSLeo Liu 	amdgpu_ring_write(ring, (vmid | (vmid << 4)));
315bb0db70fSLeo Liu 
316bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
317bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
318bb0db70fSLeo Liu 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
319bb0db70fSLeo Liu 
320bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
321bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
322bb0db70fSLeo Liu 	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
323bb0db70fSLeo Liu 
324bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
325bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_IB_SIZE), 0, 0, PACKETJ_TYPE0));
326bb0db70fSLeo Liu 	amdgpu_ring_write(ring, ib->length_dw);
327bb0db70fSLeo Liu 
328bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
329bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
330bb0db70fSLeo Liu 	amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
331bb0db70fSLeo Liu 
332bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
333bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
334bb0db70fSLeo Liu 	amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
335bb0db70fSLeo Liu 
336bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
337bb0db70fSLeo Liu 		PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
338bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0);
339bb0db70fSLeo Liu 
340bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
341bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
342bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x01400200);
343bb0db70fSLeo Liu 
344bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
345bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
346bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x2);
347bb0db70fSLeo Liu 
348bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
349bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_STATUS), 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
350bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x2);
351bb0db70fSLeo Liu }
352bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_emit_reg_wait(struct amdgpu_ring * ring,uint32_t reg,uint32_t val,uint32_t mask)353bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_emit_reg_wait(struct amdgpu_ring *ring,
354bb0db70fSLeo Liu 					    uint32_t reg, uint32_t val,
355bb0db70fSLeo Liu 					    uint32_t mask)
356bb0db70fSLeo Liu {
357bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
358bb0db70fSLeo Liu 	uint32_t reg_offset = (reg << 2);
359bb0db70fSLeo Liu 
360bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
361bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
362bb0db70fSLeo Liu 	amdgpu_ring_write(ring, 0x01400200);
363bb0db70fSLeo Liu 
364bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
365bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
366bb0db70fSLeo Liu 	amdgpu_ring_write(ring, val);
367bb0db70fSLeo Liu 
368bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
369bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
370bb0db70fSLeo Liu 	if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
371bb0db70fSLeo Liu 		((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
372bb0db70fSLeo Liu 		amdgpu_ring_write(ring, 0);
373bb0db70fSLeo Liu 		amdgpu_ring_write(ring,
374bb0db70fSLeo Liu 			PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
375bb0db70fSLeo Liu 	} else {
376bb0db70fSLeo Liu 		amdgpu_ring_write(ring, reg_offset);
377bb0db70fSLeo Liu 		amdgpu_ring_write(ring,
378bb0db70fSLeo Liu 			PACKETJ(0, 0, 0, PACKETJ_TYPE3));
379bb0db70fSLeo Liu 	}
380bb0db70fSLeo Liu 	amdgpu_ring_write(ring, mask);
381bb0db70fSLeo Liu }
382bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_emit_vm_flush(struct amdgpu_ring * ring,unsigned vmid,uint64_t pd_addr)383bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_emit_vm_flush(struct amdgpu_ring *ring,
384bb0db70fSLeo Liu 		unsigned vmid, uint64_t pd_addr)
385bb0db70fSLeo Liu {
3860530553bSLe Ma 	struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
387bb0db70fSLeo Liu 	uint32_t data0, data1, mask;
388bb0db70fSLeo Liu 
389bb0db70fSLeo Liu 	pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
390bb0db70fSLeo Liu 
391bb0db70fSLeo Liu 	/* wait for register write */
392228ea7b0SHuang Rui 	data0 = hub->ctx0_ptb_addr_lo32 + vmid * hub->ctx_addr_distance;
393bb0db70fSLeo Liu 	data1 = lower_32_bits(pd_addr);
394bb0db70fSLeo Liu 	mask = 0xffffffff;
395bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_emit_reg_wait(ring, data0, data1, mask);
396bb0db70fSLeo Liu }
397bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_emit_wreg(struct amdgpu_ring * ring,uint32_t reg,uint32_t val)398bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_emit_wreg(struct amdgpu_ring *ring,
399bb0db70fSLeo Liu 					uint32_t reg, uint32_t val)
400bb0db70fSLeo Liu {
401bb0db70fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
402bb0db70fSLeo Liu 	uint32_t reg_offset = (reg << 2);
403bb0db70fSLeo Liu 
404bb0db70fSLeo Liu 	amdgpu_ring_write(ring,
405bb0db70fSLeo Liu 		PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
406bb0db70fSLeo Liu 	if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
407bb0db70fSLeo Liu 			((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
408bb0db70fSLeo Liu 		amdgpu_ring_write(ring, 0);
409bb0db70fSLeo Liu 		amdgpu_ring_write(ring,
410bb0db70fSLeo Liu 			PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
411bb0db70fSLeo Liu 	} else {
412bb0db70fSLeo Liu 		amdgpu_ring_write(ring, reg_offset);
413bb0db70fSLeo Liu 		amdgpu_ring_write(ring,
414bb0db70fSLeo Liu 			PACKETJ(0, 0, 0, PACKETJ_TYPE0));
415bb0db70fSLeo Liu 	}
416bb0db70fSLeo Liu 	amdgpu_ring_write(ring, val);
417bb0db70fSLeo Liu }
418bb0db70fSLeo Liu 
jpeg_v1_0_decode_ring_nop(struct amdgpu_ring * ring,uint32_t count)419bb0db70fSLeo Liu static void jpeg_v1_0_decode_ring_nop(struct amdgpu_ring *ring, uint32_t count)
420bb0db70fSLeo Liu {
421bb0db70fSLeo Liu 	int i;
422bb0db70fSLeo Liu 
423bb0db70fSLeo Liu 	WARN_ON(ring->wptr % 2 || count % 2);
424bb0db70fSLeo Liu 
425bb0db70fSLeo Liu 	for (i = 0; i < count / 2; i++) {
426bb0db70fSLeo Liu 		amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
427bb0db70fSLeo Liu 		amdgpu_ring_write(ring, 0);
428bb0db70fSLeo Liu 	}
429bb0db70fSLeo Liu }
430bb0db70fSLeo Liu 
jpeg_v1_0_set_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)431bb0db70fSLeo Liu static int jpeg_v1_0_set_interrupt_state(struct amdgpu_device *adev,
432bb0db70fSLeo Liu 					struct amdgpu_irq_src *source,
433bb0db70fSLeo Liu 					unsigned type,
434bb0db70fSLeo Liu 					enum amdgpu_interrupt_state state)
435bb0db70fSLeo Liu {
436bb0db70fSLeo Liu 	return 0;
437bb0db70fSLeo Liu }
438bb0db70fSLeo Liu 
jpeg_v1_0_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)439bb0db70fSLeo Liu static int jpeg_v1_0_process_interrupt(struct amdgpu_device *adev,
440bb0db70fSLeo Liu 				      struct amdgpu_irq_src *source,
441bb0db70fSLeo Liu 				      struct amdgpu_iv_entry *entry)
442bb0db70fSLeo Liu {
443bb0db70fSLeo Liu 	DRM_DEBUG("IH: JPEG decode TRAP\n");
444bb0db70fSLeo Liu 
445bb0db70fSLeo Liu 	switch (entry->src_id) {
446bb0db70fSLeo Liu 	case 126:
447bc224553SJames Zhu 		amdgpu_fence_process(adev->jpeg.inst->ring_dec);
448bb0db70fSLeo Liu 		break;
449bb0db70fSLeo Liu 	default:
450bb0db70fSLeo Liu 		DRM_ERROR("Unhandled interrupt: %d %d\n",
451bb0db70fSLeo Liu 			  entry->src_id, entry->src_data[0]);
452bb0db70fSLeo Liu 		break;
453bb0db70fSLeo Liu 	}
454bb0db70fSLeo Liu 
455bb0db70fSLeo Liu 	return 0;
456bb0db70fSLeo Liu }
457bb0db70fSLeo Liu 
458bb0db70fSLeo Liu /**
459bb0db70fSLeo Liu  * jpeg_v1_0_early_init - set function pointers
460bb0db70fSLeo Liu  *
461bb0db70fSLeo Liu  * @handle: amdgpu_device pointer
462bb0db70fSLeo Liu  *
463bb0db70fSLeo Liu  * Set ring and irq function pointers
464bb0db70fSLeo Liu  */
jpeg_v1_0_early_init(void * handle)465bb0db70fSLeo Liu int jpeg_v1_0_early_init(void *handle)
466bb0db70fSLeo Liu {
467bb0db70fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
468bb0db70fSLeo Liu 
469bb0db70fSLeo Liu 	adev->jpeg.num_jpeg_inst = 1;
47028bb7f13SJames Zhu 	adev->jpeg.num_jpeg_rings = 1;
471bb0db70fSLeo Liu 
472bb0db70fSLeo Liu 	jpeg_v1_0_set_dec_ring_funcs(adev);
473bb0db70fSLeo Liu 	jpeg_v1_0_set_irq_funcs(adev);
474bb0db70fSLeo Liu 
475bb0db70fSLeo Liu 	return 0;
476bb0db70fSLeo Liu }
477bb0db70fSLeo Liu 
478bb0db70fSLeo Liu /**
479bb0db70fSLeo Liu  * jpeg_v1_0_sw_init - sw init for JPEG block
480bb0db70fSLeo Liu  *
481bb0db70fSLeo Liu  * @handle: amdgpu_device pointer
482bb0db70fSLeo Liu  *
483bb0db70fSLeo Liu  */
jpeg_v1_0_sw_init(void * handle)484bb0db70fSLeo Liu int jpeg_v1_0_sw_init(void *handle)
485bb0db70fSLeo Liu {
486bb0db70fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
487bb0db70fSLeo Liu 	struct amdgpu_ring *ring;
488bb0db70fSLeo Liu 	int r;
489bb0db70fSLeo Liu 
490bb0db70fSLeo Liu 	/* JPEG TRAP */
491bb0db70fSLeo Liu 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 126, &adev->jpeg.inst->irq);
492bb0db70fSLeo Liu 	if (r)
493bb0db70fSLeo Liu 		return r;
494bb0db70fSLeo Liu 
495bc224553SJames Zhu 	ring = adev->jpeg.inst->ring_dec;
496f4caf584SHawking Zhang 	ring->vm_hub = AMDGPU_MMHUB0(0);
497bb0db70fSLeo Liu 	sprintf(ring->name, "jpeg_dec");
4981c6d567bSNirmoy Das 	r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,
499c107171bSChristian König 			     0, AMDGPU_RING_PRIO_DEFAULT, NULL);
500bb0db70fSLeo Liu 	if (r)
501bb0db70fSLeo Liu 		return r;
502bb0db70fSLeo Liu 
503bc224553SJames Zhu 	adev->jpeg.internal.jpeg_pitch[0] = adev->jpeg.inst->external.jpeg_pitch[0] =
504bb0db70fSLeo Liu 		SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
505bb0db70fSLeo Liu 
506bb0db70fSLeo Liu 	return 0;
507bb0db70fSLeo Liu }
508bb0db70fSLeo Liu 
509bb0db70fSLeo Liu /**
510bb0db70fSLeo Liu  * jpeg_v1_0_sw_fini - sw fini for JPEG block
511bb0db70fSLeo Liu  *
512bb0db70fSLeo Liu  * @handle: amdgpu_device pointer
513bb0db70fSLeo Liu  *
514bb0db70fSLeo Liu  * JPEG free up sw allocation
515bb0db70fSLeo Liu  */
jpeg_v1_0_sw_fini(void * handle)516bb0db70fSLeo Liu void jpeg_v1_0_sw_fini(void *handle)
517bb0db70fSLeo Liu {
518bb0db70fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
519bb0db70fSLeo Liu 
520bc224553SJames Zhu 	amdgpu_ring_fini(adev->jpeg.inst->ring_dec);
521bb0db70fSLeo Liu }
522bb0db70fSLeo Liu 
523bb0db70fSLeo Liu /**
524bb0db70fSLeo Liu  * jpeg_v1_0_start - start JPEG block
525bb0db70fSLeo Liu  *
526bb0db70fSLeo Liu  * @adev: amdgpu_device pointer
5278608c861SLee Jones  * @mode: SPG or DPG mode
528bb0db70fSLeo Liu  *
529bb0db70fSLeo Liu  * Setup and start the JPEG block
530bb0db70fSLeo Liu  */
jpeg_v1_0_start(struct amdgpu_device * adev,int mode)531bb0db70fSLeo Liu void jpeg_v1_0_start(struct amdgpu_device *adev, int mode)
532bb0db70fSLeo Liu {
533bc224553SJames Zhu 	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
534bb0db70fSLeo Liu 
535bb0db70fSLeo Liu 	if (mode == 0) {
536bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
537bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
538bb0db70fSLeo Liu 				UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
539bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr));
540bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr));
541bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0);
542bb0db70fSLeo Liu 		WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0);
543f4618fe9SDan Carpenter 		WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
544f4618fe9SDan Carpenter 	}
545bb0db70fSLeo Liu 
546bb0db70fSLeo Liu 	/* initialize wptr */
547bb0db70fSLeo Liu 	ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
548bb0db70fSLeo Liu 
549bb0db70fSLeo Liu 	/* copy patch commands to the jpeg ring */
550bb0db70fSLeo Liu 	jpeg_v1_0_decode_ring_set_patch_ring(ring,
551bb0db70fSLeo Liu 		(ring->wptr + ring->max_dw * amdgpu_sched_hw_submission));
552bb0db70fSLeo Liu }
553bb0db70fSLeo Liu 
554bb0db70fSLeo Liu static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
555bb0db70fSLeo Liu 	.type = AMDGPU_RING_TYPE_VCN_JPEG,
556bb0db70fSLeo Liu 	.align_mask = 0xf,
557bb0db70fSLeo Liu 	.nop = PACKET0(0x81ff, 0),
558bb0db70fSLeo Liu 	.support_64bit_ptrs = false,
559bb0db70fSLeo Liu 	.no_user_fence = true,
560bb0db70fSLeo Liu 	.extra_dw = 64,
561bb0db70fSLeo Liu 	.get_rptr = jpeg_v1_0_decode_ring_get_rptr,
562bb0db70fSLeo Liu 	.get_wptr = jpeg_v1_0_decode_ring_get_wptr,
563bb0db70fSLeo Liu 	.set_wptr = jpeg_v1_0_decode_ring_set_wptr,
564*ff65ae25SDavid (Ming Qiang) Wu 	.parse_cs = jpeg_v1_dec_ring_parse_cs,
565bb0db70fSLeo Liu 	.emit_frame_size =
566bb0db70fSLeo Liu 		6 + 6 + /* hdp invalidate / flush */
567bb0db70fSLeo Liu 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
568bb0db70fSLeo Liu 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
569bb0db70fSLeo Liu 		8 + /* jpeg_v1_0_decode_ring_emit_vm_flush */
570bb0db70fSLeo Liu 		26 + 26 + /* jpeg_v1_0_decode_ring_emit_fence x2 vm fence */
571bb0db70fSLeo Liu 		6,
572bb0db70fSLeo Liu 	.emit_ib_size = 22, /* jpeg_v1_0_decode_ring_emit_ib */
573bb0db70fSLeo Liu 	.emit_ib = jpeg_v1_0_decode_ring_emit_ib,
574bb0db70fSLeo Liu 	.emit_fence = jpeg_v1_0_decode_ring_emit_fence,
575bb0db70fSLeo Liu 	.emit_vm_flush = jpeg_v1_0_decode_ring_emit_vm_flush,
576bb0db70fSLeo Liu 	.test_ring = amdgpu_jpeg_dec_ring_test_ring,
577bb0db70fSLeo Liu 	.test_ib = amdgpu_jpeg_dec_ring_test_ib,
578bb0db70fSLeo Liu 	.insert_nop = jpeg_v1_0_decode_ring_nop,
579bb0db70fSLeo Liu 	.insert_start = jpeg_v1_0_decode_ring_insert_start,
580bb0db70fSLeo Liu 	.insert_end = jpeg_v1_0_decode_ring_insert_end,
581bb0db70fSLeo Liu 	.pad_ib = amdgpu_ring_generic_pad_ib,
582187561ddSVeerabadhran G 	.begin_use = jpeg_v1_0_ring_begin_use,
583187561ddSVeerabadhran G 	.end_use = vcn_v1_0_ring_end_use,
584bb0db70fSLeo Liu 	.emit_wreg = jpeg_v1_0_decode_ring_emit_wreg,
585bb0db70fSLeo Liu 	.emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,
586bb0db70fSLeo Liu 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
587bb0db70fSLeo Liu };
588bb0db70fSLeo Liu 
jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device * adev)589bb0db70fSLeo Liu static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
590bb0db70fSLeo Liu {
591bc224553SJames Zhu 	adev->jpeg.inst->ring_dec->funcs = &jpeg_v1_0_decode_ring_vm_funcs;
592bb0db70fSLeo Liu 	DRM_INFO("JPEG decode is enabled in VM mode\n");
593bb0db70fSLeo Liu }
594bb0db70fSLeo Liu 
595bb0db70fSLeo Liu static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = {
596bb0db70fSLeo Liu 	.set = jpeg_v1_0_set_interrupt_state,
597bb0db70fSLeo Liu 	.process = jpeg_v1_0_process_interrupt,
598bb0db70fSLeo Liu };
599bb0db70fSLeo Liu 
jpeg_v1_0_set_irq_funcs(struct amdgpu_device * adev)600bb0db70fSLeo Liu static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
601bb0db70fSLeo Liu {
602bb0db70fSLeo Liu 	adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs;
603bb0db70fSLeo Liu }
604187561ddSVeerabadhran G 
jpeg_v1_0_ring_begin_use(struct amdgpu_ring * ring)605187561ddSVeerabadhran G static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
606187561ddSVeerabadhran G {
607187561ddSVeerabadhran G 	struct	amdgpu_device *adev = ring->adev;
608187561ddSVeerabadhran G 	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
609187561ddSVeerabadhran G 	int		cnt = 0;
610187561ddSVeerabadhran G 
611187561ddSVeerabadhran G 	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
612187561ddSVeerabadhran G 
613187561ddSVeerabadhran G 	if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
614187561ddSVeerabadhran G 		DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
615187561ddSVeerabadhran G 
616187561ddSVeerabadhran G 	for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
617187561ddSVeerabadhran G 		if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
618187561ddSVeerabadhran G 			DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
619187561ddSVeerabadhran G 	}
620187561ddSVeerabadhran G 
621187561ddSVeerabadhran G 	vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
622187561ddSVeerabadhran G }
623*ff65ae25SDavid (Ming Qiang) Wu 
624*ff65ae25SDavid (Ming Qiang) Wu /**
625*ff65ae25SDavid (Ming Qiang) Wu  * jpeg_v1_dec_ring_parse_cs - command submission parser
626*ff65ae25SDavid (Ming Qiang) Wu  *
627*ff65ae25SDavid (Ming Qiang) Wu  * @parser: Command submission parser context
628*ff65ae25SDavid (Ming Qiang) Wu  * @job: the job to parse
629*ff65ae25SDavid (Ming Qiang) Wu  * @ib: the IB to parse
630*ff65ae25SDavid (Ming Qiang) Wu  *
631*ff65ae25SDavid (Ming Qiang) Wu  * Parse the command stream, return -EINVAL for invalid packet,
632*ff65ae25SDavid (Ming Qiang) Wu  * 0 otherwise
633*ff65ae25SDavid (Ming Qiang) Wu  */
jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser * parser,struct amdgpu_job * job,struct amdgpu_ib * ib)634*ff65ae25SDavid (Ming Qiang) Wu static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,
635*ff65ae25SDavid (Ming Qiang) Wu 				     struct amdgpu_job *job,
636*ff65ae25SDavid (Ming Qiang) Wu 				     struct amdgpu_ib *ib)
637*ff65ae25SDavid (Ming Qiang) Wu {
638*ff65ae25SDavid (Ming Qiang) Wu 	u32 i, reg, res, cond, type;
639*ff65ae25SDavid (Ming Qiang) Wu 	int ret = 0;
640*ff65ae25SDavid (Ming Qiang) Wu 	struct amdgpu_device *adev = parser->adev;
641*ff65ae25SDavid (Ming Qiang) Wu 
642*ff65ae25SDavid (Ming Qiang) Wu 	for (i = 0; i < ib->length_dw ; i += 2) {
643*ff65ae25SDavid (Ming Qiang) Wu 		reg  = CP_PACKETJ_GET_REG(ib->ptr[i]);
644*ff65ae25SDavid (Ming Qiang) Wu 		res  = CP_PACKETJ_GET_RES(ib->ptr[i]);
645*ff65ae25SDavid (Ming Qiang) Wu 		cond = CP_PACKETJ_GET_COND(ib->ptr[i]);
646*ff65ae25SDavid (Ming Qiang) Wu 		type = CP_PACKETJ_GET_TYPE(ib->ptr[i]);
647*ff65ae25SDavid (Ming Qiang) Wu 
648*ff65ae25SDavid (Ming Qiang) Wu 		if (res || cond != PACKETJ_CONDITION_CHECK0) /* only allow 0 for now */
649*ff65ae25SDavid (Ming Qiang) Wu 			return -EINVAL;
650*ff65ae25SDavid (Ming Qiang) Wu 
651*ff65ae25SDavid (Ming Qiang) Wu 		if (reg >= JPEG_V1_REG_RANGE_START && reg <= JPEG_V1_REG_RANGE_END)
652*ff65ae25SDavid (Ming Qiang) Wu 			continue;
653*ff65ae25SDavid (Ming Qiang) Wu 
654*ff65ae25SDavid (Ming Qiang) Wu 		switch (type) {
655*ff65ae25SDavid (Ming Qiang) Wu 		case PACKETJ_TYPE0:
656*ff65ae25SDavid (Ming Qiang) Wu 			if (reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_HIGH &&
657*ff65ae25SDavid (Ming Qiang) Wu 			    reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_LOW &&
658*ff65ae25SDavid (Ming Qiang) Wu 			    reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_HIGH &&
659*ff65ae25SDavid (Ming Qiang) Wu 			    reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_LOW &&
660*ff65ae25SDavid (Ming Qiang) Wu 			    reg != JPEG_V1_REG_CTX_INDEX &&
661*ff65ae25SDavid (Ming Qiang) Wu 			    reg != JPEG_V1_REG_CTX_DATA) {
662*ff65ae25SDavid (Ming Qiang) Wu 				ret = -EINVAL;
663*ff65ae25SDavid (Ming Qiang) Wu 			}
664*ff65ae25SDavid (Ming Qiang) Wu 			break;
665*ff65ae25SDavid (Ming Qiang) Wu 		case PACKETJ_TYPE1:
666*ff65ae25SDavid (Ming Qiang) Wu 			if (reg != JPEG_V1_REG_CTX_DATA)
667*ff65ae25SDavid (Ming Qiang) Wu 				ret = -EINVAL;
668*ff65ae25SDavid (Ming Qiang) Wu 			break;
669*ff65ae25SDavid (Ming Qiang) Wu 		case PACKETJ_TYPE3:
670*ff65ae25SDavid (Ming Qiang) Wu 			if (reg != JPEG_V1_REG_SOFT_RESET)
671*ff65ae25SDavid (Ming Qiang) Wu 				ret = -EINVAL;
672*ff65ae25SDavid (Ming Qiang) Wu 			break;
673*ff65ae25SDavid (Ming Qiang) Wu 		case PACKETJ_TYPE6:
674*ff65ae25SDavid (Ming Qiang) Wu 			if (ib->ptr[i] != CP_PACKETJ_NOP)
675*ff65ae25SDavid (Ming Qiang) Wu 				ret = -EINVAL;
676*ff65ae25SDavid (Ming Qiang) Wu 			break;
677*ff65ae25SDavid (Ming Qiang) Wu 		default:
678*ff65ae25SDavid (Ming Qiang) Wu 			ret = -EINVAL;
679*ff65ae25SDavid (Ming Qiang) Wu 		}
680*ff65ae25SDavid (Ming Qiang) Wu 
681*ff65ae25SDavid (Ming Qiang) Wu 		if (ret) {
682*ff65ae25SDavid (Ming Qiang) Wu 			dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]);
683*ff65ae25SDavid (Ming Qiang) Wu 			break;
684*ff65ae25SDavid (Ming Qiang) Wu 		}
685*ff65ae25SDavid (Ming Qiang) Wu 	}
686*ff65ae25SDavid (Ming Qiang) Wu 
687*ff65ae25SDavid (Ming Qiang) Wu 	return ret;
688*ff65ae25SDavid (Ming Qiang) Wu }
689