xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/amdgpu_vcn.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  *
25  */
26 
27 #include <linux/firmware.h>
28 #include <linux/module.h>
29 #include <drm/drmP.h>
30 #include <drm/drm.h>
31 
32 #include "amdgpu.h"
33 #include "amdgpu_pm.h"
34 #include "amdgpu_vcn.h"
35 #include "soc15d.h"
36 #include "soc15_common.h"
37 
38 #include "vcn/vcn_1_0_offset.h"
39 
40 /* 1 second timeout */
41 #define VCN_IDLE_TIMEOUT	msecs_to_jiffies(1000)
42 
43 /* Firmware Names */
44 #define FIRMWARE_RAVEN		"amdgpu/raven_vcn.bin"
45 #define FIRMWARE_PICASSO	"amdgpu/picasso_vcn.bin"
46 
47 MODULE_FIRMWARE(FIRMWARE_RAVEN);
48 MODULE_FIRMWARE(FIRMWARE_PICASSO);
49 
50 static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
51 
52 int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
53 {
54 	unsigned long bo_size;
55 	const char *fw_name;
56 	const struct common_firmware_header *hdr;
57 	unsigned char fw_check;
58 	int r;
59 
60 	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
61 
62 	switch (adev->asic_type) {
63 	case CHIP_RAVEN:
64 		if (adev->pdev->device == 0x15d8)
65 			fw_name = FIRMWARE_PICASSO;
66 		else
67 			fw_name = FIRMWARE_RAVEN;
68 		break;
69 	default:
70 		return -EINVAL;
71 	}
72 
73 	r = request_firmware(&adev->vcn.fw, fw_name, adev->dev);
74 	if (r) {
75 		dev_err(adev->dev, "amdgpu_vcn: Can't load firmware \"%s\"\n",
76 			fw_name);
77 		return r;
78 	}
79 
80 	r = amdgpu_ucode_validate(adev->vcn.fw);
81 	if (r) {
82 		dev_err(adev->dev, "amdgpu_vcn: Can't validate firmware \"%s\"\n",
83 			fw_name);
84 		release_firmware(adev->vcn.fw);
85 		adev->vcn.fw = NULL;
86 		return r;
87 	}
88 
89 	hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
90 	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
91 
92 	/* Bit 20-23, it is encode major and non-zero for new naming convention.
93 	 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
94 	 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
95 	 * is zero in old naming convention, this field is always zero so far.
96 	 * These four bits are used to tell which naming convention is present.
97 	 */
98 	fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
99 	if (fw_check) {
100 		unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
101 
102 		fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
103 		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
104 		enc_major = fw_check;
105 		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
106 		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
107 		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
108 			enc_major, enc_minor, dec_ver, vep, fw_rev);
109 	} else {
110 		unsigned int version_major, version_minor, family_id;
111 
112 		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
113 		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
114 		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
115 		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
116 			version_major, version_minor, family_id);
117 	}
118 
119 	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_HEAP_SIZE
120 		  +  AMDGPU_VCN_SESSION_SIZE * 40;
121 	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
122 		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
123 	r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
124 				    AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.vcpu_bo,
125 				    &adev->vcn.gpu_addr, &adev->vcn.cpu_addr);
126 	if (r) {
127 		dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
128 		return r;
129 	}
130 
131 	return 0;
132 }
133 
134 int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
135 {
136 	int i;
137 
138 	kvfree(adev->vcn.saved_bo);
139 
140 	amdgpu_bo_free_kernel(&adev->vcn.vcpu_bo,
141 			      &adev->vcn.gpu_addr,
142 			      (void **)&adev->vcn.cpu_addr);
143 
144 	amdgpu_ring_fini(&adev->vcn.ring_dec);
145 
146 	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
147 		amdgpu_ring_fini(&adev->vcn.ring_enc[i]);
148 
149 	amdgpu_ring_fini(&adev->vcn.ring_jpeg);
150 
151 	release_firmware(adev->vcn.fw);
152 
153 	return 0;
154 }
155 
156 int amdgpu_vcn_suspend(struct amdgpu_device *adev)
157 {
158 	unsigned size;
159 	void *ptr;
160 
161 	cancel_delayed_work_sync(&adev->vcn.idle_work);
162 
163 	if (adev->vcn.vcpu_bo == NULL)
164 		return 0;
165 
166 	size = amdgpu_bo_size(adev->vcn.vcpu_bo);
167 	ptr = adev->vcn.cpu_addr;
168 
169 	adev->vcn.saved_bo = kvmalloc(size, GFP_KERNEL);
170 	if (!adev->vcn.saved_bo)
171 		return -ENOMEM;
172 
173 	memcpy_fromio(adev->vcn.saved_bo, ptr, size);
174 
175 	return 0;
176 }
177 
178 int amdgpu_vcn_resume(struct amdgpu_device *adev)
179 {
180 	unsigned size;
181 	void *ptr;
182 
183 	if (adev->vcn.vcpu_bo == NULL)
184 		return -EINVAL;
185 
186 	size = amdgpu_bo_size(adev->vcn.vcpu_bo);
187 	ptr = adev->vcn.cpu_addr;
188 
189 	if (adev->vcn.saved_bo != NULL) {
190 		memcpy_toio(ptr, adev->vcn.saved_bo, size);
191 		kvfree(adev->vcn.saved_bo);
192 		adev->vcn.saved_bo = NULL;
193 	} else {
194 		const struct common_firmware_header *hdr;
195 		unsigned offset;
196 
197 		hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
198 		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
199 			offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
200 			memcpy_toio(adev->vcn.cpu_addr, adev->vcn.fw->data + offset,
201 				    le32_to_cpu(hdr->ucode_size_bytes));
202 			size -= le32_to_cpu(hdr->ucode_size_bytes);
203 			ptr += le32_to_cpu(hdr->ucode_size_bytes);
204 		}
205 		memset_io(ptr, 0, size);
206 	}
207 
208 	return 0;
209 }
210 
211 static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
212 {
213 	struct amdgpu_device *adev =
214 		container_of(work, struct amdgpu_device, vcn.idle_work.work);
215 	unsigned fences = amdgpu_fence_count_emitted(&adev->vcn.ring_dec);
216 	unsigned i;
217 
218 	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
219 		fences += amdgpu_fence_count_emitted(&adev->vcn.ring_enc[i]);
220 	}
221 
222 	fences += amdgpu_fence_count_emitted(&adev->vcn.ring_jpeg);
223 
224 	if (fences == 0) {
225 		if (adev->pm.dpm_enabled)
226 			amdgpu_dpm_enable_uvd(adev, false);
227 		else
228 			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
229 							       AMD_PG_STATE_GATE);
230 	} else {
231 		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
232 	}
233 }
234 
235 void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
236 {
237 	struct amdgpu_device *adev = ring->adev;
238 	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
239 
240 	if (set_clocks) {
241 		if (adev->pm.dpm_enabled)
242 			amdgpu_dpm_enable_uvd(adev, true);
243 		else
244 			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
245 							       AMD_PG_STATE_UNGATE);
246 	}
247 }
248 
249 void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
250 {
251 	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
252 }
253 
254 int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
255 {
256 	struct amdgpu_device *adev = ring->adev;
257 	uint32_t tmp = 0;
258 	unsigned i;
259 	int r;
260 
261 	WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID), 0xCAFEDEAD);
262 	r = amdgpu_ring_alloc(ring, 3);
263 	if (r) {
264 		DRM_ERROR("amdgpu: cp failed to lock ring %d (%d).\n",
265 			  ring->idx, r);
266 		return r;
267 	}
268 	amdgpu_ring_write(ring,
269 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID), 0));
270 	amdgpu_ring_write(ring, 0xDEADBEEF);
271 	amdgpu_ring_commit(ring);
272 	for (i = 0; i < adev->usec_timeout; i++) {
273 		tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID));
274 		if (tmp == 0xDEADBEEF)
275 			break;
276 		DRM_UDELAY(1);
277 	}
278 
279 	if (i < adev->usec_timeout) {
280 		DRM_DEBUG("ring test on %d succeeded in %d usecs\n",
281 			 ring->idx, i);
282 	} else {
283 		DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n",
284 			  ring->idx, tmp);
285 		r = -EINVAL;
286 	}
287 	return r;
288 }
289 
290 static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
291 				   struct amdgpu_bo *bo,
292 				   struct dma_fence **fence)
293 {
294 	struct amdgpu_device *adev = ring->adev;
295 	struct dma_fence *f = NULL;
296 	struct amdgpu_job *job;
297 	struct amdgpu_ib *ib;
298 	uint64_t addr;
299 	int i, r;
300 
301 	r = amdgpu_job_alloc_with_ib(adev, 64, &job);
302 	if (r)
303 		goto err;
304 
305 	ib = &job->ibs[0];
306 	addr = amdgpu_bo_gpu_offset(bo);
307 	ib->ptr[0] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0);
308 	ib->ptr[1] = addr;
309 	ib->ptr[2] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0);
310 	ib->ptr[3] = addr >> 32;
311 	ib->ptr[4] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0);
312 	ib->ptr[5] = 0;
313 	for (i = 6; i < 16; i += 2) {
314 		ib->ptr[i] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP), 0);
315 		ib->ptr[i+1] = 0;
316 	}
317 	ib->length_dw = 16;
318 
319 	r = amdgpu_job_submit_direct(job, ring, &f);
320 	if (r)
321 		goto err_free;
322 
323 	amdgpu_bo_fence(bo, f, false);
324 	amdgpu_bo_unreserve(bo);
325 	amdgpu_bo_unref(&bo);
326 
327 	if (fence)
328 		*fence = dma_fence_get(f);
329 	dma_fence_put(f);
330 
331 	return 0;
332 
333 err_free:
334 	amdgpu_job_free(job);
335 
336 err:
337 	amdgpu_bo_unreserve(bo);
338 	amdgpu_bo_unref(&bo);
339 	return r;
340 }
341 
342 static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
343 			      struct dma_fence **fence)
344 {
345 	struct amdgpu_device *adev = ring->adev;
346 	struct amdgpu_bo *bo = NULL;
347 	uint32_t *msg;
348 	int r, i;
349 
350 	r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
351 				      AMDGPU_GEM_DOMAIN_VRAM,
352 				      &bo, NULL, (void **)&msg);
353 	if (r)
354 		return r;
355 
356 	msg[0] = cpu_to_le32(0x00000028);
357 	msg[1] = cpu_to_le32(0x00000038);
358 	msg[2] = cpu_to_le32(0x00000001);
359 	msg[3] = cpu_to_le32(0x00000000);
360 	msg[4] = cpu_to_le32(handle);
361 	msg[5] = cpu_to_le32(0x00000000);
362 	msg[6] = cpu_to_le32(0x00000001);
363 	msg[7] = cpu_to_le32(0x00000028);
364 	msg[8] = cpu_to_le32(0x00000010);
365 	msg[9] = cpu_to_le32(0x00000000);
366 	msg[10] = cpu_to_le32(0x00000007);
367 	msg[11] = cpu_to_le32(0x00000000);
368 	msg[12] = cpu_to_le32(0x00000780);
369 	msg[13] = cpu_to_le32(0x00000440);
370 	for (i = 14; i < 1024; ++i)
371 		msg[i] = cpu_to_le32(0x0);
372 
373 	return amdgpu_vcn_dec_send_msg(ring, bo, fence);
374 }
375 
376 static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
377 			       struct dma_fence **fence)
378 {
379 	struct amdgpu_device *adev = ring->adev;
380 	struct amdgpu_bo *bo = NULL;
381 	uint32_t *msg;
382 	int r, i;
383 
384 	r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
385 				      AMDGPU_GEM_DOMAIN_VRAM,
386 				      &bo, NULL, (void **)&msg);
387 	if (r)
388 		return r;
389 
390 	msg[0] = cpu_to_le32(0x00000028);
391 	msg[1] = cpu_to_le32(0x00000018);
392 	msg[2] = cpu_to_le32(0x00000000);
393 	msg[3] = cpu_to_le32(0x00000002);
394 	msg[4] = cpu_to_le32(handle);
395 	msg[5] = cpu_to_le32(0x00000000);
396 	for (i = 6; i < 1024; ++i)
397 		msg[i] = cpu_to_le32(0x0);
398 
399 	return amdgpu_vcn_dec_send_msg(ring, bo, fence);
400 }
401 
402 int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
403 {
404 	struct dma_fence *fence;
405 	long r;
406 
407 	r = amdgpu_vcn_dec_get_create_msg(ring, 1, NULL);
408 	if (r) {
409 		DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r);
410 		goto error;
411 	}
412 
413 	r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence);
414 	if (r) {
415 		DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r);
416 		goto error;
417 	}
418 
419 	r = dma_fence_wait_timeout(fence, false, timeout);
420 	if (r == 0) {
421 		DRM_ERROR("amdgpu: IB test timed out.\n");
422 		r = -ETIMEDOUT;
423 	} else if (r < 0) {
424 		DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
425 	} else {
426 		DRM_DEBUG("ib test on ring %d succeeded\n",  ring->idx);
427 		r = 0;
428 	}
429 
430 	dma_fence_put(fence);
431 
432 error:
433 	return r;
434 }
435 
436 int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
437 {
438 	struct amdgpu_device *adev = ring->adev;
439 	uint32_t rptr;
440 	unsigned i;
441 	int r;
442 
443 	r = amdgpu_ring_alloc(ring, 16);
444 	if (r) {
445 		DRM_ERROR("amdgpu: vcn enc failed to lock ring %d (%d).\n",
446 			  ring->idx, r);
447 		return r;
448 	}
449 
450 	rptr = amdgpu_ring_get_rptr(ring);
451 
452 	amdgpu_ring_write(ring, VCN_ENC_CMD_END);
453 	amdgpu_ring_commit(ring);
454 
455 	for (i = 0; i < adev->usec_timeout; i++) {
456 		if (amdgpu_ring_get_rptr(ring) != rptr)
457 			break;
458 		DRM_UDELAY(1);
459 	}
460 
461 	if (i < adev->usec_timeout) {
462 		DRM_DEBUG("ring test on %d succeeded in %d usecs\n",
463 			 ring->idx, i);
464 	} else {
465 		DRM_ERROR("amdgpu: ring %d test failed\n",
466 			  ring->idx);
467 		r = -ETIMEDOUT;
468 	}
469 
470 	return r;
471 }
472 
473 static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
474 			      struct dma_fence **fence)
475 {
476 	const unsigned ib_size_dw = 16;
477 	struct amdgpu_job *job;
478 	struct amdgpu_ib *ib;
479 	struct dma_fence *f = NULL;
480 	uint64_t dummy;
481 	int i, r;
482 
483 	r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
484 	if (r)
485 		return r;
486 
487 	ib = &job->ibs[0];
488 	dummy = ib->gpu_addr + 1024;
489 
490 	ib->length_dw = 0;
491 	ib->ptr[ib->length_dw++] = 0x00000018;
492 	ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
493 	ib->ptr[ib->length_dw++] = handle;
494 	ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
495 	ib->ptr[ib->length_dw++] = dummy;
496 	ib->ptr[ib->length_dw++] = 0x0000000b;
497 
498 	ib->ptr[ib->length_dw++] = 0x00000014;
499 	ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
500 	ib->ptr[ib->length_dw++] = 0x0000001c;
501 	ib->ptr[ib->length_dw++] = 0x00000000;
502 	ib->ptr[ib->length_dw++] = 0x00000000;
503 
504 	ib->ptr[ib->length_dw++] = 0x00000008;
505 	ib->ptr[ib->length_dw++] = 0x08000001; /* op initialize */
506 
507 	for (i = ib->length_dw; i < ib_size_dw; ++i)
508 		ib->ptr[i] = 0x0;
509 
510 	r = amdgpu_job_submit_direct(job, ring, &f);
511 	if (r)
512 		goto err;
513 
514 	if (fence)
515 		*fence = dma_fence_get(f);
516 	dma_fence_put(f);
517 
518 	return 0;
519 
520 err:
521 	amdgpu_job_free(job);
522 	return r;
523 }
524 
525 static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
526 				struct dma_fence **fence)
527 {
528 	const unsigned ib_size_dw = 16;
529 	struct amdgpu_job *job;
530 	struct amdgpu_ib *ib;
531 	struct dma_fence *f = NULL;
532 	uint64_t dummy;
533 	int i, r;
534 
535 	r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
536 	if (r)
537 		return r;
538 
539 	ib = &job->ibs[0];
540 	dummy = ib->gpu_addr + 1024;
541 
542 	ib->length_dw = 0;
543 	ib->ptr[ib->length_dw++] = 0x00000018;
544 	ib->ptr[ib->length_dw++] = 0x00000001;
545 	ib->ptr[ib->length_dw++] = handle;
546 	ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
547 	ib->ptr[ib->length_dw++] = dummy;
548 	ib->ptr[ib->length_dw++] = 0x0000000b;
549 
550 	ib->ptr[ib->length_dw++] = 0x00000014;
551 	ib->ptr[ib->length_dw++] = 0x00000002;
552 	ib->ptr[ib->length_dw++] = 0x0000001c;
553 	ib->ptr[ib->length_dw++] = 0x00000000;
554 	ib->ptr[ib->length_dw++] = 0x00000000;
555 
556 	ib->ptr[ib->length_dw++] = 0x00000008;
557 	ib->ptr[ib->length_dw++] = 0x08000002; /* op close session */
558 
559 	for (i = ib->length_dw; i < ib_size_dw; ++i)
560 		ib->ptr[i] = 0x0;
561 
562 	r = amdgpu_job_submit_direct(job, ring, &f);
563 	if (r)
564 		goto err;
565 
566 	if (fence)
567 		*fence = dma_fence_get(f);
568 	dma_fence_put(f);
569 
570 	return 0;
571 
572 err:
573 	amdgpu_job_free(job);
574 	return r;
575 }
576 
577 int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
578 {
579 	struct dma_fence *fence = NULL;
580 	long r;
581 
582 	r = amdgpu_vcn_enc_get_create_msg(ring, 1, NULL);
583 	if (r) {
584 		DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r);
585 		goto error;
586 	}
587 
588 	r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &fence);
589 	if (r) {
590 		DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r);
591 		goto error;
592 	}
593 
594 	r = dma_fence_wait_timeout(fence, false, timeout);
595 	if (r == 0) {
596 		DRM_ERROR("amdgpu: IB test timed out.\n");
597 		r = -ETIMEDOUT;
598 	} else if (r < 0) {
599 		DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
600 	} else {
601 		DRM_DEBUG("ib test on ring %d succeeded\n", ring->idx);
602 		r = 0;
603 	}
604 error:
605 	dma_fence_put(fence);
606 	return r;
607 }
608 
609 int amdgpu_vcn_jpeg_ring_test_ring(struct amdgpu_ring *ring)
610 {
611 	struct amdgpu_device *adev = ring->adev;
612 	uint32_t tmp = 0;
613 	unsigned i;
614 	int r;
615 
616 	WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID), 0xCAFEDEAD);
617 	r = amdgpu_ring_alloc(ring, 3);
618 
619 	if (r) {
620 		DRM_ERROR("amdgpu: cp failed to lock ring %d (%d).\n",
621 				  ring->idx, r);
622 		return r;
623 	}
624 
625 	amdgpu_ring_write(ring,
626 		PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID), 0, 0, 0));
627 	amdgpu_ring_write(ring, 0xDEADBEEF);
628 	amdgpu_ring_commit(ring);
629 
630 	for (i = 0; i < adev->usec_timeout; i++) {
631 		tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID));
632 		if (tmp == 0xDEADBEEF)
633 			break;
634 		DRM_UDELAY(1);
635 	}
636 
637 	if (i < adev->usec_timeout) {
638 		DRM_DEBUG("ring test on %d succeeded in %d usecs\n",
639 				  ring->idx, i);
640 	} else {
641 		DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n",
642 				  ring->idx, tmp);
643 		r = -EINVAL;
644 	}
645 
646 	return r;
647 }
648 
649 static int amdgpu_vcn_jpeg_set_reg(struct amdgpu_ring *ring, uint32_t handle,
650 		struct dma_fence **fence)
651 {
652 	struct amdgpu_device *adev = ring->adev;
653 	struct amdgpu_job *job;
654 	struct amdgpu_ib *ib;
655 	struct dma_fence *f = NULL;
656 	const unsigned ib_size_dw = 16;
657 	int i, r;
658 
659 	r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
660 	if (r)
661 		return r;
662 
663 	ib = &job->ibs[0];
664 
665 	ib->ptr[0] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_PITCH), 0, 0, PACKETJ_TYPE0);
666 	ib->ptr[1] = 0xDEADBEEF;
667 	for (i = 2; i < 16; i += 2) {
668 		ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
669 		ib->ptr[i+1] = 0;
670 	}
671 	ib->length_dw = 16;
672 
673 	r = amdgpu_job_submit_direct(job, ring, &f);
674 	if (r)
675 		goto err;
676 
677 	if (fence)
678 		*fence = dma_fence_get(f);
679 	dma_fence_put(f);
680 
681 	return 0;
682 
683 err:
684 	amdgpu_job_free(job);
685 	return r;
686 }
687 
688 int amdgpu_vcn_jpeg_ring_test_ib(struct amdgpu_ring *ring, long timeout)
689 {
690 	struct amdgpu_device *adev = ring->adev;
691 	uint32_t tmp = 0;
692 	unsigned i;
693 	struct dma_fence *fence = NULL;
694 	long r = 0;
695 
696 	r = amdgpu_vcn_jpeg_set_reg(ring, 1, &fence);
697 	if (r) {
698 		DRM_ERROR("amdgpu: failed to set jpeg register (%ld).\n", r);
699 		goto error;
700 	}
701 
702 	r = dma_fence_wait_timeout(fence, false, timeout);
703 	if (r == 0) {
704 		DRM_ERROR("amdgpu: IB test timed out.\n");
705 		r = -ETIMEDOUT;
706 		goto error;
707 	} else if (r < 0) {
708 		DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
709 		goto error;
710 	} else
711 		r = 0;
712 
713 	for (i = 0; i < adev->usec_timeout; i++) {
714 		tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_PITCH));
715 		if (tmp == 0xDEADBEEF)
716 			break;
717 		DRM_UDELAY(1);
718 	}
719 
720 	if (i < adev->usec_timeout)
721 		DRM_DEBUG("ib test on ring %d succeeded\n", ring->idx);
722 	else {
723 		DRM_ERROR("ib test failed (0x%08X)\n", tmp);
724 		r = -EINVAL;
725 	}
726 
727 	dma_fence_put(fence);
728 
729 error:
730 	return r;
731 }
732