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