]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright 2019 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 "soc15.h" | |
27 | #include "soc15d.h" | |
28 | #include "vcn_v1_0.h" | |
29 | ||
30 | #include "vcn/vcn_1_0_offset.h" | |
31 | #include "vcn/vcn_1_0_sh_mask.h" | |
32 | ||
33 | static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); | |
34 | static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev); | |
35 | ||
36 | static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val) | |
37 | { | |
38 | struct amdgpu_device *adev = ring->adev; | |
39 | ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0); | |
40 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | |
41 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | |
42 | ring->ring[(*ptr)++] = 0; | |
43 | ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0); | |
44 | } else { | |
45 | ring->ring[(*ptr)++] = reg_offset; | |
46 | ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0); | |
47 | } | |
48 | ring->ring[(*ptr)++] = val; | |
49 | } | |
50 | ||
51 | static void jpeg_v1_0_decode_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr) | |
52 | { | |
53 | struct amdgpu_device *adev = ring->adev; | |
54 | ||
55 | uint32_t reg, reg_offset, val, mask, i; | |
56 | ||
57 | // 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW | |
58 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW); | |
59 | reg_offset = (reg << 2); | |
60 | val = lower_32_bits(ring->gpu_addr); | |
61 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
62 | ||
63 | // 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH | |
64 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH); | |
65 | reg_offset = (reg << 2); | |
66 | val = upper_32_bits(ring->gpu_addr); | |
67 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
68 | ||
69 | // 3rd to 5th: issue MEM_READ commands | |
70 | for (i = 0; i <= 2; i++) { | |
71 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2); | |
72 | ring->ring[ptr++] = 0; | |
73 | } | |
74 | ||
75 | // 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability | |
76 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL); | |
77 | reg_offset = (reg << 2); | |
78 | val = 0x13; | |
79 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
80 | ||
81 | // 7th: program mmUVD_JRBC_RB_REF_DATA | |
82 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA); | |
83 | reg_offset = (reg << 2); | |
84 | val = 0x1; | |
85 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
86 | ||
87 | // 8th: issue conditional register read mmUVD_JRBC_RB_CNTL | |
88 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL); | |
89 | reg_offset = (reg << 2); | |
90 | val = 0x1; | |
91 | mask = 0x1; | |
92 | ||
93 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0); | |
94 | ring->ring[ptr++] = 0x01400200; | |
95 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0); | |
96 | ring->ring[ptr++] = val; | |
97 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0); | |
98 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | |
99 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | |
100 | ring->ring[ptr++] = 0; | |
101 | ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3); | |
102 | } else { | |
103 | ring->ring[ptr++] = reg_offset; | |
104 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3); | |
105 | } | |
106 | ring->ring[ptr++] = mask; | |
107 | ||
108 | //9th to 21st: insert no-op | |
109 | for (i = 0; i <= 12; i++) { | |
110 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6); | |
111 | ring->ring[ptr++] = 0; | |
112 | } | |
113 | ||
114 | //22nd: reset mmUVD_JRBC_RB_RPTR | |
115 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_RPTR); | |
116 | reg_offset = (reg << 2); | |
117 | val = 0; | |
118 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
119 | ||
120 | //23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch | |
121 | reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL); | |
122 | reg_offset = (reg << 2); | |
123 | val = 0x12; | |
124 | jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val); | |
125 | } | |
126 | ||
127 | /** | |
128 | * jpeg_v1_0_decode_ring_get_rptr - get read pointer | |
129 | * | |
130 | * @ring: amdgpu_ring pointer | |
131 | * | |
132 | * Returns the current hardware read pointer | |
133 | */ | |
134 | static uint64_t jpeg_v1_0_decode_ring_get_rptr(struct amdgpu_ring *ring) | |
135 | { | |
136 | struct amdgpu_device *adev = ring->adev; | |
137 | ||
138 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR); | |
139 | } | |
140 | ||
141 | /** | |
142 | * jpeg_v1_0_decode_ring_get_wptr - get write pointer | |
143 | * | |
144 | * @ring: amdgpu_ring pointer | |
145 | * | |
146 | * Returns the current hardware write pointer | |
147 | */ | |
148 | static uint64_t jpeg_v1_0_decode_ring_get_wptr(struct amdgpu_ring *ring) | |
149 | { | |
150 | struct amdgpu_device *adev = ring->adev; | |
151 | ||
152 | return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); | |
153 | } | |
154 | ||
155 | /** | |
156 | * jpeg_v1_0_decode_ring_set_wptr - set write pointer | |
157 | * | |
158 | * @ring: amdgpu_ring pointer | |
159 | * | |
160 | * Commits the write pointer to the hardware | |
161 | */ | |
162 | static void jpeg_v1_0_decode_ring_set_wptr(struct amdgpu_ring *ring) | |
163 | { | |
164 | struct amdgpu_device *adev = ring->adev; | |
165 | ||
166 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr)); | |
167 | } | |
168 | ||
169 | /** | |
170 | * jpeg_v1_0_decode_ring_insert_start - insert a start command | |
171 | * | |
172 | * @ring: amdgpu_ring pointer | |
173 | * | |
174 | * Write a start command to the ring. | |
175 | */ | |
176 | static void jpeg_v1_0_decode_ring_insert_start(struct amdgpu_ring *ring) | |
177 | { | |
178 | struct amdgpu_device *adev = ring->adev; | |
179 | ||
180 | amdgpu_ring_write(ring, | |
181 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0)); | |
182 | amdgpu_ring_write(ring, 0x68e04); | |
183 | ||
184 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0)); | |
185 | amdgpu_ring_write(ring, 0x80010000); | |
186 | } | |
187 | ||
188 | /** | |
189 | * jpeg_v1_0_decode_ring_insert_end - insert a end command | |
190 | * | |
191 | * @ring: amdgpu_ring pointer | |
192 | * | |
193 | * Write a end command to the ring. | |
194 | */ | |
195 | static void jpeg_v1_0_decode_ring_insert_end(struct amdgpu_ring *ring) | |
196 | { | |
197 | struct amdgpu_device *adev = ring->adev; | |
198 | ||
199 | amdgpu_ring_write(ring, | |
200 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0)); | |
201 | amdgpu_ring_write(ring, 0x68e04); | |
202 | ||
203 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0)); | |
204 | amdgpu_ring_write(ring, 0x00010000); | |
205 | } | |
206 | ||
207 | /** | |
208 | * jpeg_v1_0_decode_ring_emit_fence - emit an fence & trap command | |
209 | * | |
210 | * @ring: amdgpu_ring pointer | |
211 | * @fence: fence to emit | |
212 | * | |
213 | * Write a fence and a trap command to the ring. | |
214 | */ | |
215 | static void jpeg_v1_0_decode_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, | |
216 | unsigned flags) | |
217 | { | |
218 | struct amdgpu_device *adev = ring->adev; | |
219 | ||
220 | WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); | |
221 | ||
222 | amdgpu_ring_write(ring, | |
223 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA0), 0, 0, PACKETJ_TYPE0)); | |
224 | amdgpu_ring_write(ring, seq); | |
225 | ||
226 | amdgpu_ring_write(ring, | |
227 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA1), 0, 0, PACKETJ_TYPE0)); | |
228 | amdgpu_ring_write(ring, seq); | |
229 | ||
230 | amdgpu_ring_write(ring, | |
231 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0)); | |
232 | amdgpu_ring_write(ring, lower_32_bits(addr)); | |
233 | ||
234 | amdgpu_ring_write(ring, | |
235 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0)); | |
236 | amdgpu_ring_write(ring, upper_32_bits(addr)); | |
237 | ||
238 | amdgpu_ring_write(ring, | |
239 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, 0, PACKETJ_TYPE0)); | |
240 | amdgpu_ring_write(ring, 0x8); | |
241 | ||
242 | amdgpu_ring_write(ring, | |
243 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4)); | |
244 | amdgpu_ring_write(ring, 0); | |
245 | ||
246 | amdgpu_ring_write(ring, | |
247 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0)); | |
248 | amdgpu_ring_write(ring, 0x01400200); | |
249 | ||
250 | amdgpu_ring_write(ring, | |
251 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0)); | |
252 | amdgpu_ring_write(ring, seq); | |
253 | ||
254 | amdgpu_ring_write(ring, | |
255 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0)); | |
256 | amdgpu_ring_write(ring, lower_32_bits(addr)); | |
257 | ||
258 | amdgpu_ring_write(ring, | |
259 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0)); | |
260 | amdgpu_ring_write(ring, upper_32_bits(addr)); | |
261 | ||
262 | amdgpu_ring_write(ring, | |
263 | PACKETJ(0, 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE2)); | |
264 | amdgpu_ring_write(ring, 0xffffffff); | |
265 | ||
266 | amdgpu_ring_write(ring, | |
267 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0)); | |
268 | amdgpu_ring_write(ring, 0x3fbc); | |
269 | ||
270 | amdgpu_ring_write(ring, | |
271 | PACKETJ(0, 0, 0, PACKETJ_TYPE0)); | |
272 | amdgpu_ring_write(ring, 0x1); | |
273 | ||
274 | /* emit trap */ | |
275 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7)); | |
276 | amdgpu_ring_write(ring, 0); | |
277 | } | |
278 | ||
279 | /** | |
280 | * jpeg_v1_0_decode_ring_emit_ib - execute indirect buffer | |
281 | * | |
282 | * @ring: amdgpu_ring pointer | |
283 | * @ib: indirect buffer to execute | |
284 | * | |
285 | * Write ring commands to execute the indirect buffer. | |
286 | */ | |
287 | static void jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring *ring, | |
288 | struct amdgpu_job *job, | |
289 | struct amdgpu_ib *ib, | |
290 | uint32_t flags) | |
291 | { | |
292 | struct amdgpu_device *adev = ring->adev; | |
293 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); | |
294 | ||
295 | amdgpu_ring_write(ring, | |
296 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0)); | |
297 | amdgpu_ring_write(ring, (vmid | (vmid << 4))); | |
298 | ||
299 | amdgpu_ring_write(ring, | |
300 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0)); | |
301 | amdgpu_ring_write(ring, (vmid | (vmid << 4))); | |
302 | ||
303 | amdgpu_ring_write(ring, | |
304 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0)); | |
305 | amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); | |
306 | ||
307 | amdgpu_ring_write(ring, | |
308 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0)); | |
309 | amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); | |
310 | ||
311 | amdgpu_ring_write(ring, | |
312 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_IB_SIZE), 0, 0, PACKETJ_TYPE0)); | |
313 | amdgpu_ring_write(ring, ib->length_dw); | |
314 | ||
315 | amdgpu_ring_write(ring, | |
316 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0)); | |
317 | amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr)); | |
318 | ||
319 | amdgpu_ring_write(ring, | |
320 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0)); | |
321 | amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr)); | |
322 | ||
323 | amdgpu_ring_write(ring, | |
324 | PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2)); | |
325 | amdgpu_ring_write(ring, 0); | |
326 | ||
327 | amdgpu_ring_write(ring, | |
328 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0)); | |
329 | amdgpu_ring_write(ring, 0x01400200); | |
330 | ||
331 | amdgpu_ring_write(ring, | |
332 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0)); | |
333 | amdgpu_ring_write(ring, 0x2); | |
334 | ||
335 | amdgpu_ring_write(ring, | |
336 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_STATUS), 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3)); | |
337 | amdgpu_ring_write(ring, 0x2); | |
338 | } | |
339 | ||
340 | static void jpeg_v1_0_decode_ring_emit_reg_wait(struct amdgpu_ring *ring, | |
341 | uint32_t reg, uint32_t val, | |
342 | uint32_t mask) | |
343 | { | |
344 | struct amdgpu_device *adev = ring->adev; | |
345 | uint32_t reg_offset = (reg << 2); | |
346 | ||
347 | amdgpu_ring_write(ring, | |
348 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0)); | |
349 | amdgpu_ring_write(ring, 0x01400200); | |
350 | ||
351 | amdgpu_ring_write(ring, | |
352 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0)); | |
353 | amdgpu_ring_write(ring, val); | |
354 | ||
355 | amdgpu_ring_write(ring, | |
356 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0)); | |
357 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | |
358 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | |
359 | amdgpu_ring_write(ring, 0); | |
360 | amdgpu_ring_write(ring, | |
361 | PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3)); | |
362 | } else { | |
363 | amdgpu_ring_write(ring, reg_offset); | |
364 | amdgpu_ring_write(ring, | |
365 | PACKETJ(0, 0, 0, PACKETJ_TYPE3)); | |
366 | } | |
367 | amdgpu_ring_write(ring, mask); | |
368 | } | |
369 | ||
370 | static void jpeg_v1_0_decode_ring_emit_vm_flush(struct amdgpu_ring *ring, | |
371 | unsigned vmid, uint64_t pd_addr) | |
372 | { | |
373 | struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; | |
374 | uint32_t data0, data1, mask; | |
375 | ||
376 | pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr); | |
377 | ||
378 | /* wait for register write */ | |
379 | data0 = hub->ctx0_ptb_addr_lo32 + vmid * 2; | |
380 | data1 = lower_32_bits(pd_addr); | |
381 | mask = 0xffffffff; | |
382 | jpeg_v1_0_decode_ring_emit_reg_wait(ring, data0, data1, mask); | |
383 | } | |
384 | ||
385 | static void jpeg_v1_0_decode_ring_emit_wreg(struct amdgpu_ring *ring, | |
386 | uint32_t reg, uint32_t val) | |
387 | { | |
388 | struct amdgpu_device *adev = ring->adev; | |
389 | uint32_t reg_offset = (reg << 2); | |
390 | ||
391 | amdgpu_ring_write(ring, | |
392 | PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0)); | |
393 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | |
394 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | |
395 | amdgpu_ring_write(ring, 0); | |
396 | amdgpu_ring_write(ring, | |
397 | PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0)); | |
398 | } else { | |
399 | amdgpu_ring_write(ring, reg_offset); | |
400 | amdgpu_ring_write(ring, | |
401 | PACKETJ(0, 0, 0, PACKETJ_TYPE0)); | |
402 | } | |
403 | amdgpu_ring_write(ring, val); | |
404 | } | |
405 | ||
406 | static void jpeg_v1_0_decode_ring_nop(struct amdgpu_ring *ring, uint32_t count) | |
407 | { | |
408 | int i; | |
409 | ||
410 | WARN_ON(ring->wptr % 2 || count % 2); | |
411 | ||
412 | for (i = 0; i < count / 2; i++) { | |
413 | amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6)); | |
414 | amdgpu_ring_write(ring, 0); | |
415 | } | |
416 | } | |
417 | ||
418 | static int jpeg_v1_0_set_interrupt_state(struct amdgpu_device *adev, | |
419 | struct amdgpu_irq_src *source, | |
420 | unsigned type, | |
421 | enum amdgpu_interrupt_state state) | |
422 | { | |
423 | return 0; | |
424 | } | |
425 | ||
426 | static int jpeg_v1_0_process_interrupt(struct amdgpu_device *adev, | |
427 | struct amdgpu_irq_src *source, | |
428 | struct amdgpu_iv_entry *entry) | |
429 | { | |
430 | DRM_DEBUG("IH: JPEG decode TRAP\n"); | |
431 | ||
432 | switch (entry->src_id) { | |
433 | case 126: | |
434 | amdgpu_fence_process(&adev->jpeg.inst->ring_dec); | |
435 | break; | |
436 | default: | |
437 | DRM_ERROR("Unhandled interrupt: %d %d\n", | |
438 | entry->src_id, entry->src_data[0]); | |
439 | break; | |
440 | } | |
441 | ||
442 | return 0; | |
443 | } | |
444 | ||
445 | /** | |
446 | * jpeg_v1_0_early_init - set function pointers | |
447 | * | |
448 | * @handle: amdgpu_device pointer | |
449 | * | |
450 | * Set ring and irq function pointers | |
451 | */ | |
452 | int jpeg_v1_0_early_init(void *handle) | |
453 | { | |
454 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
455 | ||
456 | adev->jpeg.num_jpeg_inst = 1; | |
457 | ||
458 | jpeg_v1_0_set_dec_ring_funcs(adev); | |
459 | jpeg_v1_0_set_irq_funcs(adev); | |
460 | ||
461 | return 0; | |
462 | } | |
463 | ||
464 | /** | |
465 | * jpeg_v1_0_sw_init - sw init for JPEG block | |
466 | * | |
467 | * @handle: amdgpu_device pointer | |
468 | * | |
469 | */ | |
470 | int jpeg_v1_0_sw_init(void *handle) | |
471 | { | |
472 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
473 | struct amdgpu_ring *ring; | |
474 | int r; | |
475 | ||
476 | /* JPEG TRAP */ | |
477 | r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 126, &adev->jpeg.inst->irq); | |
478 | if (r) | |
479 | return r; | |
480 | ||
481 | ring = &adev->jpeg.inst->ring_dec; | |
482 | sprintf(ring->name, "jpeg_dec"); | |
483 | r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, | |
484 | 0, AMDGPU_RING_PRIO_DEFAULT); | |
485 | if (r) | |
486 | return r; | |
487 | ||
488 | adev->jpeg.internal.jpeg_pitch = adev->jpeg.inst->external.jpeg_pitch = | |
489 | SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH); | |
490 | ||
491 | return 0; | |
492 | } | |
493 | ||
494 | /** | |
495 | * jpeg_v1_0_sw_fini - sw fini for JPEG block | |
496 | * | |
497 | * @handle: amdgpu_device pointer | |
498 | * | |
499 | * JPEG free up sw allocation | |
500 | */ | |
501 | void jpeg_v1_0_sw_fini(void *handle) | |
502 | { | |
503 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
504 | ||
505 | amdgpu_ring_fini(&adev->jpeg.inst[0].ring_dec); | |
506 | } | |
507 | ||
508 | /** | |
509 | * jpeg_v1_0_start - start JPEG block | |
510 | * | |
511 | * @adev: amdgpu_device pointer | |
512 | * | |
513 | * Setup and start the JPEG block | |
514 | */ | |
515 | void jpeg_v1_0_start(struct amdgpu_device *adev, int mode) | |
516 | { | |
517 | struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec; | |
518 | ||
519 | if (mode == 0) { | |
520 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0); | |
521 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK | | |
522 | UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK); | |
523 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); | |
524 | WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr)); | |
525 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0); | |
526 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0); | |
527 | WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK); | |
528 | } | |
529 | ||
530 | /* initialize wptr */ | |
531 | ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR); | |
532 | ||
533 | /* copy patch commands to the jpeg ring */ | |
534 | jpeg_v1_0_decode_ring_set_patch_ring(ring, | |
535 | (ring->wptr + ring->max_dw * amdgpu_sched_hw_submission)); | |
536 | } | |
537 | ||
538 | static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = { | |
539 | .type = AMDGPU_RING_TYPE_VCN_JPEG, | |
540 | .align_mask = 0xf, | |
541 | .nop = PACKET0(0x81ff, 0), | |
542 | .support_64bit_ptrs = false, | |
543 | .no_user_fence = true, | |
544 | .vmhub = AMDGPU_MMHUB_0, | |
545 | .extra_dw = 64, | |
546 | .get_rptr = jpeg_v1_0_decode_ring_get_rptr, | |
547 | .get_wptr = jpeg_v1_0_decode_ring_get_wptr, | |
548 | .set_wptr = jpeg_v1_0_decode_ring_set_wptr, | |
549 | .emit_frame_size = | |
550 | 6 + 6 + /* hdp invalidate / flush */ | |
551 | SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + | |
552 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + | |
553 | 8 + /* jpeg_v1_0_decode_ring_emit_vm_flush */ | |
554 | 26 + 26 + /* jpeg_v1_0_decode_ring_emit_fence x2 vm fence */ | |
555 | 6, | |
556 | .emit_ib_size = 22, /* jpeg_v1_0_decode_ring_emit_ib */ | |
557 | .emit_ib = jpeg_v1_0_decode_ring_emit_ib, | |
558 | .emit_fence = jpeg_v1_0_decode_ring_emit_fence, | |
559 | .emit_vm_flush = jpeg_v1_0_decode_ring_emit_vm_flush, | |
560 | .test_ring = amdgpu_jpeg_dec_ring_test_ring, | |
561 | .test_ib = amdgpu_jpeg_dec_ring_test_ib, | |
562 | .insert_nop = jpeg_v1_0_decode_ring_nop, | |
563 | .insert_start = jpeg_v1_0_decode_ring_insert_start, | |
564 | .insert_end = jpeg_v1_0_decode_ring_insert_end, | |
565 | .pad_ib = amdgpu_ring_generic_pad_ib, | |
566 | .begin_use = vcn_v1_0_ring_begin_use, | |
567 | .end_use = amdgpu_vcn_ring_end_use, | |
568 | .emit_wreg = jpeg_v1_0_decode_ring_emit_wreg, | |
569 | .emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait, | |
570 | .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, | |
571 | }; | |
572 | ||
573 | static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev) | |
574 | { | |
575 | adev->jpeg.inst->ring_dec.funcs = &jpeg_v1_0_decode_ring_vm_funcs; | |
576 | DRM_INFO("JPEG decode is enabled in VM mode\n"); | |
577 | } | |
578 | ||
579 | static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = { | |
580 | .set = jpeg_v1_0_set_interrupt_state, | |
581 | .process = jpeg_v1_0_process_interrupt, | |
582 | }; | |
583 | ||
584 | static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev) | |
585 | { | |
586 | adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs; | |
587 | } |