diff options
author | Leo Liu <leo.liu@amd.com> | 2016-12-21 13:56:44 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-05-24 17:41:23 -0400 |
commit | 2d531d81d0fb906ee74a5d5f8c04857849efa785 (patch) | |
tree | e0fae57a4a4730fb0759782721c5cd088534ade1 /drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | |
parent | 95d0906f8506550a7c4a59c770732e7de912cffc (diff) |
drm/amdgpu: add encode tests for vcn
Add encode ring and ib tests.
Signed-off-by: Leo Liu <leo.liu@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 97b09b63753c..9bb59cc33ace 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | |||
@@ -112,6 +112,15 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) | |||
112 | return r; | 112 | return r; |
113 | } | 113 | } |
114 | 114 | ||
115 | ring = &adev->vcn.ring_enc[0]; | ||
116 | rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL]; | ||
117 | r = amd_sched_entity_init(&ring->sched, &adev->vcn.entity_enc, | ||
118 | rq, amdgpu_sched_jobs); | ||
119 | if (r != 0) { | ||
120 | DRM_ERROR("Failed setting up VCN enc run queue.\n"); | ||
121 | return r; | ||
122 | } | ||
123 | |||
115 | return 0; | 124 | return 0; |
116 | } | 125 | } |
117 | 126 | ||
@@ -121,6 +130,8 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) | |||
121 | 130 | ||
122 | amd_sched_entity_fini(&adev->vcn.ring_dec.sched, &adev->vcn.entity_dec); | 131 | amd_sched_entity_fini(&adev->vcn.ring_dec.sched, &adev->vcn.entity_dec); |
123 | 132 | ||
133 | amd_sched_entity_fini(&adev->vcn.ring_enc[0].sched, &adev->vcn.entity_enc); | ||
134 | |||
124 | amdgpu_bo_free_kernel(&adev->vcn.vcpu_bo, | 135 | amdgpu_bo_free_kernel(&adev->vcn.vcpu_bo, |
125 | &adev->vcn.gpu_addr, | 136 | &adev->vcn.gpu_addr, |
126 | (void **)&adev->vcn.cpu_addr); | 137 | (void **)&adev->vcn.cpu_addr); |
@@ -423,3 +434,195 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) | |||
423 | error: | 434 | error: |
424 | return r; | 435 | return r; |
425 | } | 436 | } |
437 | |||
438 | static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, | ||
439 | struct dma_fence **fence) | ||
440 | { | ||
441 | const unsigned ib_size_dw = 1024; | ||
442 | struct amdgpu_job *job; | ||
443 | struct amdgpu_ib *ib; | ||
444 | struct dma_fence *f = NULL; | ||
445 | uint64_t dummy; | ||
446 | int i, r; | ||
447 | |||
448 | r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); | ||
449 | if (r) | ||
450 | return r; | ||
451 | |||
452 | ib = &job->ibs[0]; | ||
453 | |||
454 | dummy = ib->gpu_addr + 1024; | ||
455 | |||
456 | /* stitch together an VCN enc create msg */ | ||
457 | ib->length_dw = 0; | ||
458 | ib->ptr[ib->length_dw++] = 0x0000000c; /* len */ | ||
459 | ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ | ||
460 | ib->ptr[ib->length_dw++] = handle; | ||
461 | |||
462 | ib->ptr[ib->length_dw++] = 0x00000040; /* len */ | ||
463 | ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */ | ||
464 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
465 | ib->ptr[ib->length_dw++] = 0x00000042; | ||
466 | ib->ptr[ib->length_dw++] = 0x0000000a; | ||
467 | ib->ptr[ib->length_dw++] = 0x00000001; | ||
468 | ib->ptr[ib->length_dw++] = 0x00000080; | ||
469 | ib->ptr[ib->length_dw++] = 0x00000060; | ||
470 | ib->ptr[ib->length_dw++] = 0x00000100; | ||
471 | ib->ptr[ib->length_dw++] = 0x00000100; | ||
472 | ib->ptr[ib->length_dw++] = 0x0000000c; | ||
473 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
474 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
475 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
476 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
477 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
478 | |||
479 | ib->ptr[ib->length_dw++] = 0x00000014; /* len */ | ||
480 | ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ | ||
481 | ib->ptr[ib->length_dw++] = upper_32_bits(dummy); | ||
482 | ib->ptr[ib->length_dw++] = dummy; | ||
483 | ib->ptr[ib->length_dw++] = 0x00000001; | ||
484 | |||
485 | for (i = ib->length_dw; i < ib_size_dw; ++i) | ||
486 | ib->ptr[i] = 0x0; | ||
487 | |||
488 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); | ||
489 | job->fence = dma_fence_get(f); | ||
490 | if (r) | ||
491 | goto err; | ||
492 | |||
493 | amdgpu_job_free(job); | ||
494 | if (fence) | ||
495 | *fence = dma_fence_get(f); | ||
496 | dma_fence_put(f); | ||
497 | return 0; | ||
498 | |||
499 | err: | ||
500 | amdgpu_job_free(job); | ||
501 | return r; | ||
502 | } | ||
503 | |||
504 | static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | ||
505 | bool direct, struct dma_fence **fence) | ||
506 | { | ||
507 | const unsigned ib_size_dw = 1024; | ||
508 | struct amdgpu_job *job; | ||
509 | struct amdgpu_ib *ib; | ||
510 | struct dma_fence *f = NULL; | ||
511 | int i, r; | ||
512 | |||
513 | r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); | ||
514 | if (r) | ||
515 | return r; | ||
516 | |||
517 | ib = &job->ibs[0]; | ||
518 | |||
519 | /* stitch together an VCN enc destroy msg */ | ||
520 | ib->length_dw = 0; | ||
521 | ib->ptr[ib->length_dw++] = 0x0000000c; /* len */ | ||
522 | ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */ | ||
523 | ib->ptr[ib->length_dw++] = handle; | ||
524 | |||
525 | ib->ptr[ib->length_dw++] = 0x00000020; /* len */ | ||
526 | ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ | ||
527 | ib->ptr[ib->length_dw++] = 0xffffffff; /* next task info, set to 0xffffffff if no */ | ||
528 | ib->ptr[ib->length_dw++] = 0x00000001; /* destroy session */ | ||
529 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
530 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
531 | ib->ptr[ib->length_dw++] = 0xffffffff; /* feedback is not needed, set to 0xffffffff and firmware will not output feedback */ | ||
532 | ib->ptr[ib->length_dw++] = 0x00000000; | ||
533 | |||
534 | ib->ptr[ib->length_dw++] = 0x00000008; /* len */ | ||
535 | ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */ | ||
536 | |||
537 | for (i = ib->length_dw; i < ib_size_dw; ++i) | ||
538 | ib->ptr[i] = 0x0; | ||
539 | |||
540 | if (direct) { | ||
541 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); | ||
542 | job->fence = dma_fence_get(f); | ||
543 | if (r) | ||
544 | goto err; | ||
545 | |||
546 | amdgpu_job_free(job); | ||
547 | } else { | ||
548 | r = amdgpu_job_submit(job, ring, &ring->adev->vcn.entity_enc, | ||
549 | AMDGPU_FENCE_OWNER_UNDEFINED, &f); | ||
550 | if (r) | ||
551 | goto err; | ||
552 | } | ||
553 | |||
554 | if (fence) | ||
555 | *fence = dma_fence_get(f); | ||
556 | dma_fence_put(f); | ||
557 | return 0; | ||
558 | |||
559 | err: | ||
560 | amdgpu_job_free(job); | ||
561 | return r; | ||
562 | } | ||
563 | |||
564 | int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring) | ||
565 | { | ||
566 | struct amdgpu_device *adev = ring->adev; | ||
567 | uint32_t rptr = amdgpu_ring_get_rptr(ring); | ||
568 | unsigned i; | ||
569 | int r; | ||
570 | |||
571 | r = amdgpu_ring_alloc(ring, 16); | ||
572 | if (r) { | ||
573 | DRM_ERROR("amdgpu: vcn enc failed to lock ring %d (%d).\n", | ||
574 | ring->idx, r); | ||
575 | return r; | ||
576 | } | ||
577 | amdgpu_ring_write(ring, VCE_CMD_END); | ||
578 | amdgpu_ring_commit(ring); | ||
579 | |||
580 | for (i = 0; i < adev->usec_timeout; i++) { | ||
581 | if (amdgpu_ring_get_rptr(ring) != rptr) | ||
582 | break; | ||
583 | DRM_UDELAY(1); | ||
584 | } | ||
585 | |||
586 | if (i < adev->usec_timeout) { | ||
587 | DRM_INFO("ring test on %d succeeded in %d usecs\n", | ||
588 | ring->idx, i); | ||
589 | } else { | ||
590 | DRM_ERROR("amdgpu: ring %d test failed\n", | ||
591 | ring->idx); | ||
592 | r = -ETIMEDOUT; | ||
593 | } | ||
594 | |||
595 | return r; | ||
596 | } | ||
597 | |||
598 | int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) | ||
599 | { | ||
600 | struct dma_fence *fence = NULL; | ||
601 | long r; | ||
602 | |||
603 | r = amdgpu_vcn_enc_get_create_msg(ring, 1, NULL); | ||
604 | if (r) { | ||
605 | DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r); | ||
606 | goto error; | ||
607 | } | ||
608 | |||
609 | r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, true, &fence); | ||
610 | if (r) { | ||
611 | DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r); | ||
612 | goto error; | ||
613 | } | ||
614 | |||
615 | r = dma_fence_wait_timeout(fence, false, timeout); | ||
616 | if (r == 0) { | ||
617 | DRM_ERROR("amdgpu: IB test timed out.\n"); | ||
618 | r = -ETIMEDOUT; | ||
619 | } else if (r < 0) { | ||
620 | DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); | ||
621 | } else { | ||
622 | DRM_INFO("ib test on ring %d succeeded\n", ring->idx); | ||
623 | r = 0; | ||
624 | } | ||
625 | error: | ||
626 | dma_fence_put(fence); | ||
627 | return r; | ||
628 | } | ||