aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600.c
diff options
context:
space:
mode:
authorChristian König <deathsimple@vodafone.de>2013-04-08 06:41:29 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-04-09 10:31:33 -0400
commitf2ba57b5eab8817d86d0f108fdf1878e51dc0a37 (patch)
treee784f0573069f6341768968fe3d49df6d2c9a534 /drivers/gpu/drm/radeon/r600.c
parent4474f3a91f95e3fcc62d97e36f1e8e3392c96ee0 (diff)
drm/radeon: UVD bringup v8
Just everything needed to decode videos using UVD. v6: just all the bugfixes and support for R7xx-SI merged in one patch v7: UVD_CGC_GATE is a write only register, lockup detection fix v8: split out VRAM fallback changes, remove support for RV770, add support for HEMLOCK, add buffer sizes checks Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r--drivers/gpu/drm/radeon/r600.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 1c5308778948..7ce7b83c76f5 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2552,6 +2552,185 @@ void r600_dma_fini(struct radeon_device *rdev)
2552} 2552}
2553 2553
2554/* 2554/*
2555 * UVD
2556 */
2557int r600_uvd_rbc_start(struct radeon_device *rdev)
2558{
2559 struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2560 uint64_t rptr_addr;
2561 uint32_t rb_bufsz, tmp;
2562 int r;
2563
2564 rptr_addr = rdev->wb.gpu_addr + R600_WB_UVD_RPTR_OFFSET;
2565
2566 if (upper_32_bits(rptr_addr) != upper_32_bits(ring->gpu_addr)) {
2567 DRM_ERROR("UVD ring and rptr not in the same 4GB segment!\n");
2568 return -EINVAL;
2569 }
2570
2571 /* force RBC into idle state */
2572 WREG32(UVD_RBC_RB_CNTL, 0x11010101);
2573
2574 /* Set the write pointer delay */
2575 WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
2576
2577 /* set the wb address */
2578 WREG32(UVD_RBC_RB_RPTR_ADDR, rptr_addr >> 2);
2579
2580 /* programm the 4GB memory segment for rptr and ring buffer */
2581 WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(rptr_addr) |
2582 (0x7 << 16) | (0x1 << 31));
2583
2584 /* Initialize the ring buffer's read and write pointers */
2585 WREG32(UVD_RBC_RB_RPTR, 0x0);
2586
2587 ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR);
2588 WREG32(UVD_RBC_RB_WPTR, ring->wptr);
2589
2590 /* set the ring address */
2591 WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
2592
2593 /* Set ring buffer size */
2594 rb_bufsz = drm_order(ring->ring_size);
2595 rb_bufsz = (0x1 << 8) | rb_bufsz;
2596 WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
2597
2598 ring->ready = true;
2599 r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
2600 if (r) {
2601 ring->ready = false;
2602 return r;
2603 }
2604
2605 r = radeon_ring_lock(rdev, ring, 10);
2606 if (r) {
2607 DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
2608 return r;
2609 }
2610
2611 tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
2612 radeon_ring_write(ring, tmp);
2613 radeon_ring_write(ring, 0xFFFFF);
2614
2615 tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
2616 radeon_ring_write(ring, tmp);
2617 radeon_ring_write(ring, 0xFFFFF);
2618
2619 tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
2620 radeon_ring_write(ring, tmp);
2621 radeon_ring_write(ring, 0xFFFFF);
2622
2623 /* Clear timeout status bits */
2624 radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
2625 radeon_ring_write(ring, 0x8);
2626
2627 radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
2628 radeon_ring_write(ring, 1);
2629
2630 radeon_ring_unlock_commit(rdev, ring);
2631
2632 return 0;
2633}
2634
2635void r600_uvd_rbc_stop(struct radeon_device *rdev)
2636{
2637 struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2638
2639 /* force RBC into idle state */
2640 WREG32(UVD_RBC_RB_CNTL, 0x11010101);
2641 ring->ready = false;
2642}
2643
2644int r600_uvd_init(struct radeon_device *rdev)
2645{
2646 int i, j, r;
2647
2648 /* disable clock gating */
2649 WREG32(UVD_CGC_GATE, 0);
2650
2651 /* disable interupt */
2652 WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
2653
2654 /* put LMI, VCPU, RBC etc... into reset */
2655 WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
2656 LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
2657 CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
2658 mdelay(5);
2659
2660 /* take UVD block out of reset */
2661 WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
2662 mdelay(5);
2663
2664 /* initialize UVD memory controller */
2665 WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
2666 (1 << 21) | (1 << 9) | (1 << 20));
2667
2668 /* disable byte swapping */
2669 WREG32(UVD_LMI_SWAP_CNTL, 0);
2670 WREG32(UVD_MP_SWAP_CNTL, 0);
2671
2672 WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
2673 WREG32(UVD_MPC_SET_MUXA1, 0x0);
2674 WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
2675 WREG32(UVD_MPC_SET_MUXB1, 0x0);
2676 WREG32(UVD_MPC_SET_ALU, 0);
2677 WREG32(UVD_MPC_SET_MUX, 0x88);
2678
2679 /* Stall UMC */
2680 WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
2681 WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
2682
2683 /* take all subblocks out of reset, except VCPU */
2684 WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
2685 mdelay(5);
2686
2687 /* enable VCPU clock */
2688 WREG32(UVD_VCPU_CNTL, 1 << 9);
2689
2690 /* enable UMC */
2691 WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
2692
2693 /* boot up the VCPU */
2694 WREG32(UVD_SOFT_RESET, 0);
2695 mdelay(10);
2696
2697 WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
2698
2699 for (i = 0; i < 10; ++i) {
2700 uint32_t status;
2701 for (j = 0; j < 100; ++j) {
2702 status = RREG32(UVD_STATUS);
2703 if (status & 2)
2704 break;
2705 mdelay(10);
2706 }
2707 r = 0;
2708 if (status & 2)
2709 break;
2710
2711 DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
2712 WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
2713 mdelay(10);
2714 WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
2715 mdelay(10);
2716 r = -1;
2717 }
2718 if (r) {
2719 DRM_ERROR("UVD not responding, giving up!!!\n");
2720 return r;
2721 }
2722 /* enable interupt */
2723 WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
2724
2725 r = r600_uvd_rbc_start(rdev);
2726 if (r)
2727 return r;
2728
2729 DRM_INFO("UVD initialized successfully.\n");
2730 return 0;
2731}
2732
2733/*
2555 * GPU scratch registers helpers function. 2734 * GPU scratch registers helpers function.
2556 */ 2735 */
2557void r600_scratch_init(struct radeon_device *rdev) 2736void r600_scratch_init(struct radeon_device *rdev)
@@ -2660,6 +2839,40 @@ int r600_dma_ring_test(struct radeon_device *rdev,
2660 return r; 2839 return r;
2661} 2840}
2662 2841
2842int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
2843{
2844 uint32_t tmp = 0;
2845 unsigned i;
2846 int r;
2847
2848 WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
2849 r = radeon_ring_lock(rdev, ring, 3);
2850 if (r) {
2851 DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
2852 ring->idx, r);
2853 return r;
2854 }
2855 radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
2856 radeon_ring_write(ring, 0xDEADBEEF);
2857 radeon_ring_unlock_commit(rdev, ring);
2858 for (i = 0; i < rdev->usec_timeout; i++) {
2859 tmp = RREG32(UVD_CONTEXT_ID);
2860 if (tmp == 0xDEADBEEF)
2861 break;
2862 DRM_UDELAY(1);
2863 }
2864
2865 if (i < rdev->usec_timeout) {
2866 DRM_INFO("ring test on %d succeeded in %d usecs\n",
2867 ring->idx, i);
2868 } else {
2869 DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
2870 ring->idx, tmp);
2871 r = -EINVAL;
2872 }
2873 return r;
2874}
2875
2663/* 2876/*
2664 * CP fences/semaphores 2877 * CP fences/semaphores
2665 */ 2878 */
@@ -2711,6 +2924,30 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
2711 } 2924 }
2712} 2925}
2713 2926
2927void r600_uvd_fence_emit(struct radeon_device *rdev,
2928 struct radeon_fence *fence)
2929{
2930 struct radeon_ring *ring = &rdev->ring[fence->ring];
2931 uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
2932
2933 radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
2934 radeon_ring_write(ring, fence->seq);
2935 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
2936 radeon_ring_write(ring, addr & 0xffffffff);
2937 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
2938 radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
2939 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
2940 radeon_ring_write(ring, 0);
2941
2942 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
2943 radeon_ring_write(ring, 0);
2944 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
2945 radeon_ring_write(ring, 0);
2946 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
2947 radeon_ring_write(ring, 2);
2948 return;
2949}
2950
2714void r600_semaphore_ring_emit(struct radeon_device *rdev, 2951void r600_semaphore_ring_emit(struct radeon_device *rdev,
2715 struct radeon_ring *ring, 2952 struct radeon_ring *ring,
2716 struct radeon_semaphore *semaphore, 2953 struct radeon_semaphore *semaphore,
@@ -2780,6 +3017,23 @@ void r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
2780 radeon_ring_write(ring, upper_32_bits(addr) & 0xff); 3017 radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
2781} 3018}
2782 3019
3020void r600_uvd_semaphore_emit(struct radeon_device *rdev,
3021 struct radeon_ring *ring,
3022 struct radeon_semaphore *semaphore,
3023 bool emit_wait)
3024{
3025 uint64_t addr = semaphore->gpu_addr;
3026
3027 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
3028 radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
3029
3030 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
3031 radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
3032
3033 radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
3034 radeon_ring_write(ring, emit_wait ? 1 : 0);
3035}
3036
2783int r600_copy_blit(struct radeon_device *rdev, 3037int r600_copy_blit(struct radeon_device *rdev,
2784 uint64_t src_offset, 3038 uint64_t src_offset,
2785 uint64_t dst_offset, 3039 uint64_t dst_offset,
@@ -3183,6 +3437,16 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
3183 radeon_ring_write(ring, ib->length_dw); 3437 radeon_ring_write(ring, ib->length_dw);
3184} 3438}
3185 3439
3440void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
3441{
3442 struct radeon_ring *ring = &rdev->ring[ib->ring];
3443
3444 radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
3445 radeon_ring_write(ring, ib->gpu_addr);
3446 radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
3447 radeon_ring_write(ring, ib->length_dw);
3448}
3449
3186int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 3450int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
3187{ 3451{
3188 struct radeon_ib ib; 3452 struct radeon_ib ib;
@@ -3300,6 +3564,33 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
3300 return r; 3564 return r;
3301} 3565}
3302 3566
3567int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
3568{
3569 struct radeon_fence *fence;
3570 int r;
3571
3572 r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
3573 if (r) {
3574 DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
3575 return r;
3576 }
3577
3578 r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
3579 if (r) {
3580 DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
3581 return r;
3582 }
3583
3584 r = radeon_fence_wait(fence, false);
3585 if (r) {
3586 DRM_ERROR("radeon: fence wait failed (%d).\n", r);
3587 return r;
3588 }
3589 DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
3590 radeon_fence_unref(&fence);
3591 return r;
3592}
3593
3303/** 3594/**
3304 * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine 3595 * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine
3305 * 3596 *