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