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