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