aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/gpu/drm/radeon/Makefile2
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c40
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h7
-rw-r--r--drivers/gpu/drm/radeon/ni.c49
-rw-r--r--drivers/gpu/drm/radeon/nid.h9
-rw-r--r--drivers/gpu/drm/radeon/r600.c291
-rw-r--r--drivers/gpu/drm/radeon/r600d.h61
-rw-r--r--drivers/gpu/drm/radeon/radeon.h41
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c63
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h19
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c30
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c23
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c24
-rw-r--r--drivers/gpu/drm/radeon/radeon_test.c72
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c664
-rw-r--r--drivers/gpu/drm/radeon/rv770.c132
-rw-r--r--drivers/gpu/drm/radeon/rv770d.h14
-rw-r--r--drivers/gpu/drm/radeon/si.c32
-rw-r--r--drivers/gpu/drm/radeon/sid.h6
22 files changed, 1533 insertions, 53 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index bf172522ea68..86c5e3611892 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -76,7 +76,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
76 evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ 76 evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
77 evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ 77 evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ 78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
79 si_blit_shaders.o radeon_prime.o 79 si_blit_shaders.o radeon_prime.o radeon_uvd.o
80 80
81radeon-$(CONFIG_COMPAT) += radeon_ioc32.o 81radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
82radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o 82radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 305a657bf215..18b66ff59dcf 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3360,6 +3360,9 @@ restart_ih:
3360 DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); 3360 DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
3361 break; 3361 break;
3362 } 3362 }
3363 case 124: /* UVD */
3364 DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
3365 radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
3363 break; 3366 break;
3364 case 146: 3367 case 146:
3365 case 147: 3368 case 147:
@@ -3571,7 +3574,7 @@ int evergreen_copy_dma(struct radeon_device *rdev,
3571 3574
3572static int evergreen_startup(struct radeon_device *rdev) 3575static int evergreen_startup(struct radeon_device *rdev)
3573{ 3576{
3574 struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 3577 struct radeon_ring *ring;
3575 int r; 3578 int r;
3576 3579
3577 /* enable pcie gen2 link */ 3580 /* enable pcie gen2 link */
@@ -3638,6 +3641,17 @@ static int evergreen_startup(struct radeon_device *rdev)
3638 return r; 3641 return r;
3639 } 3642 }
3640 3643
3644 r = rv770_uvd_resume(rdev);
3645 if (!r) {
3646 r = radeon_fence_driver_start_ring(rdev,
3647 R600_RING_TYPE_UVD_INDEX);
3648 if (r)
3649 dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
3650 }
3651
3652 if (r)
3653 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
3654
3641 /* Enable IRQ */ 3655 /* Enable IRQ */
3642 r = r600_irq_init(rdev); 3656 r = r600_irq_init(rdev);
3643 if (r) { 3657 if (r) {
@@ -3647,6 +3661,7 @@ static int evergreen_startup(struct radeon_device *rdev)
3647 } 3661 }
3648 evergreen_irq_set(rdev); 3662 evergreen_irq_set(rdev);
3649 3663
3664 ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
3650 r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, 3665 r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
3651 R600_CP_RB_RPTR, R600_CP_RB_WPTR, 3666 R600_CP_RB_RPTR, R600_CP_RB_WPTR,
3652 0, 0xfffff, RADEON_CP_PACKET2); 3667 0, 0xfffff, RADEON_CP_PACKET2);
@@ -3670,6 +3685,19 @@ static int evergreen_startup(struct radeon_device *rdev)
3670 if (r) 3685 if (r)
3671 return r; 3686 return r;
3672 3687
3688 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
3689 if (ring->ring_size) {
3690 r = radeon_ring_init(rdev, ring, ring->ring_size,
3691 R600_WB_UVD_RPTR_OFFSET,
3692 UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
3693 0, 0xfffff, RADEON_CP_PACKET2);
3694 if (!r)
3695 r = r600_uvd_init(rdev);
3696
3697 if (r)
3698 DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
3699 }
3700
3673 r = radeon_ib_pool_init(rdev); 3701 r = radeon_ib_pool_init(rdev);
3674 if (r) { 3702 if (r) {
3675 dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 3703 dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -3716,8 +3744,10 @@ int evergreen_resume(struct radeon_device *rdev)
3716int evergreen_suspend(struct radeon_device *rdev) 3744int evergreen_suspend(struct radeon_device *rdev)
3717{ 3745{
3718 r600_audio_fini(rdev); 3746 r600_audio_fini(rdev);
3747 radeon_uvd_suspend(rdev);
3719 r700_cp_stop(rdev); 3748 r700_cp_stop(rdev);
3720 r600_dma_stop(rdev); 3749 r600_dma_stop(rdev);
3750 r600_uvd_rbc_stop(rdev);
3721 evergreen_irq_suspend(rdev); 3751 evergreen_irq_suspend(rdev);
3722 radeon_wb_disable(rdev); 3752 radeon_wb_disable(rdev);
3723 evergreen_pcie_gart_disable(rdev); 3753 evergreen_pcie_gart_disable(rdev);
@@ -3797,6 +3827,13 @@ int evergreen_init(struct radeon_device *rdev)
3797 rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; 3827 rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
3798 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); 3828 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
3799 3829
3830 r = radeon_uvd_init(rdev);
3831 if (!r) {
3832 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
3833 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
3834 4096);
3835 }
3836
3800 rdev->ih.ring_obj = NULL; 3837 rdev->ih.ring_obj = NULL;
3801 r600_ih_ring_init(rdev, 64 * 1024); 3838 r600_ih_ring_init(rdev, 64 * 1024);
3802 3839
@@ -3843,6 +3880,7 @@ void evergreen_fini(struct radeon_device *rdev)
3843 radeon_ib_pool_fini(rdev); 3880 radeon_ib_pool_fini(rdev);
3844 radeon_irq_kms_fini(rdev); 3881 radeon_irq_kms_fini(rdev);
3845 evergreen_pcie_gart_fini(rdev); 3882 evergreen_pcie_gart_fini(rdev);
3883 radeon_uvd_fini(rdev);
3846 r600_vram_scratch_fini(rdev); 3884 r600_vram_scratch_fini(rdev);
3847 radeon_gem_fini(rdev); 3885 radeon_gem_fini(rdev);
3848 radeon_fence_driver_fini(rdev); 3886 radeon_fence_driver_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 982d25ad9af3..c5d873e525c9 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -992,6 +992,13 @@
992# define TARGET_LINK_SPEED_MASK (0xf << 0) 992# define TARGET_LINK_SPEED_MASK (0xf << 0)
993# define SELECTABLE_DEEMPHASIS (1 << 6) 993# define SELECTABLE_DEEMPHASIS (1 << 6)
994 994
995
996/*
997 * UVD
998 */
999#define UVD_RBC_RB_RPTR 0xf690
1000#define UVD_RBC_RB_WPTR 0xf694
1001
995/* 1002/*
996 * PM4 1003 * PM4
997 */ 1004 */
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 02e958063682..35d7caa60c48 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -933,6 +933,23 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
933 radeon_ring_write(ring, 10); /* poll interval */ 933 radeon_ring_write(ring, 10); /* poll interval */
934} 934}
935 935
936void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
937 struct radeon_ring *ring,
938 struct radeon_semaphore *semaphore,
939 bool emit_wait)
940{
941 uint64_t addr = semaphore->gpu_addr;
942
943 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
944 radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
945
946 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
947 radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
948
949 radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
950 radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
951}
952
936static void cayman_cp_enable(struct radeon_device *rdev, bool enable) 953static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
937{ 954{
938 if (enable) 955 if (enable)
@@ -1684,6 +1701,16 @@ static int cayman_startup(struct radeon_device *rdev)
1684 return r; 1701 return r;
1685 } 1702 }
1686 1703
1704 r = rv770_uvd_resume(rdev);
1705 if (!r) {
1706 r = radeon_fence_driver_start_ring(rdev,
1707 R600_RING_TYPE_UVD_INDEX);
1708 if (r)
1709 dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
1710 }
1711 if (r)
1712 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
1713
1687 r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); 1714 r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
1688 if (r) { 1715 if (r) {
1689 dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 1716 dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
@@ -1750,6 +1777,18 @@ static int cayman_startup(struct radeon_device *rdev)
1750 if (r) 1777 if (r)
1751 return r; 1778 return r;
1752 1779
1780 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
1781 if (ring->ring_size) {
1782 r = radeon_ring_init(rdev, ring, ring->ring_size,
1783 R600_WB_UVD_RPTR_OFFSET,
1784 UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
1785 0, 0xfffff, RADEON_CP_PACKET2);
1786 if (!r)
1787 r = r600_uvd_init(rdev);
1788 if (r)
1789 DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
1790 }
1791
1753 r = radeon_ib_pool_init(rdev); 1792 r = radeon_ib_pool_init(rdev);
1754 if (r) { 1793 if (r) {
1755 dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 1794 dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -1796,6 +1835,8 @@ int cayman_suspend(struct radeon_device *rdev)
1796 radeon_vm_manager_fini(rdev); 1835 radeon_vm_manager_fini(rdev);
1797 cayman_cp_enable(rdev, false); 1836 cayman_cp_enable(rdev, false);
1798 cayman_dma_stop(rdev); 1837 cayman_dma_stop(rdev);
1838 r600_uvd_rbc_stop(rdev);
1839 radeon_uvd_suspend(rdev);
1799 evergreen_irq_suspend(rdev); 1840 evergreen_irq_suspend(rdev);
1800 radeon_wb_disable(rdev); 1841 radeon_wb_disable(rdev);
1801 cayman_pcie_gart_disable(rdev); 1842 cayman_pcie_gart_disable(rdev);
@@ -1870,6 +1911,13 @@ int cayman_init(struct radeon_device *rdev)
1870 ring->ring_obj = NULL; 1911 ring->ring_obj = NULL;
1871 r600_ring_init(rdev, ring, 64 * 1024); 1912 r600_ring_init(rdev, ring, 64 * 1024);
1872 1913
1914 r = radeon_uvd_init(rdev);
1915 if (!r) {
1916 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
1917 ring->ring_obj = NULL;
1918 r600_ring_init(rdev, ring, 4096);
1919 }
1920
1873 rdev->ih.ring_obj = NULL; 1921 rdev->ih.ring_obj = NULL;
1874 r600_ih_ring_init(rdev, 64 * 1024); 1922 r600_ih_ring_init(rdev, 64 * 1024);
1875 1923
@@ -1921,6 +1969,7 @@ void cayman_fini(struct radeon_device *rdev)
1921 radeon_vm_manager_fini(rdev); 1969 radeon_vm_manager_fini(rdev);
1922 radeon_ib_pool_fini(rdev); 1970 radeon_ib_pool_fini(rdev);
1923 radeon_irq_kms_fini(rdev); 1971 radeon_irq_kms_fini(rdev);
1972 radeon_uvd_fini(rdev);
1924 cayman_pcie_gart_fini(rdev); 1973 cayman_pcie_gart_fini(rdev);
1925 r600_vram_scratch_fini(rdev); 1974 r600_vram_scratch_fini(rdev);
1926 radeon_gem_fini(rdev); 1975 radeon_gem_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
index 445b235c4323..f2555bc44ada 100644
--- a/drivers/gpu/drm/radeon/nid.h
+++ b/drivers/gpu/drm/radeon/nid.h
@@ -490,6 +490,15 @@
490# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) 490# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0)
491 491
492/* 492/*
493 * UVD
494 */
495#define UVD_SEMA_ADDR_LOW 0xEF00
496#define UVD_SEMA_ADDR_HIGH 0xEF04
497#define UVD_SEMA_CMD 0xEF08
498#define UVD_RBC_RB_RPTR 0xF690
499#define UVD_RBC_RB_WPTR 0xF694
500
501/*
493 * PM4 502 * PM4
494 */ 503 */
495#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \ 504#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \
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 *
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index a42ba11a3bed..441bdb809a0b 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -691,6 +691,7 @@
691#define SRBM_SOFT_RESET 0xe60 691#define SRBM_SOFT_RESET 0xe60
692# define SOFT_RESET_DMA (1 << 12) 692# define SOFT_RESET_DMA (1 << 12)
693# define SOFT_RESET_RLC (1 << 13) 693# define SOFT_RESET_RLC (1 << 13)
694# define SOFT_RESET_UVD (1 << 18)
694# define RV770_SOFT_RESET_DMA (1 << 20) 695# define RV770_SOFT_RESET_DMA (1 << 20)
695 696
696#define CP_INT_CNTL 0xc124 697#define CP_INT_CNTL 0xc124
@@ -1143,6 +1144,66 @@
1143# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) 1144# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30)
1144 1145
1145/* 1146/*
1147 * UVD
1148 */
1149#define UVD_SEMA_ADDR_LOW 0xef00
1150#define UVD_SEMA_ADDR_HIGH 0xef04
1151#define UVD_SEMA_CMD 0xef08
1152
1153#define UVD_GPCOM_VCPU_CMD 0xef0c
1154#define UVD_GPCOM_VCPU_DATA0 0xef10
1155#define UVD_GPCOM_VCPU_DATA1 0xef14
1156#define UVD_ENGINE_CNTL 0xef18
1157
1158#define UVD_SEMA_CNTL 0xf400
1159#define UVD_RB_ARB_CTRL 0xf480
1160
1161#define UVD_LMI_EXT40_ADDR 0xf498
1162#define UVD_CGC_GATE 0xf4a8
1163#define UVD_LMI_CTRL2 0xf4f4
1164#define UVD_MASTINT_EN 0xf500
1165#define UVD_LMI_ADDR_EXT 0xf594
1166#define UVD_LMI_CTRL 0xf598
1167#define UVD_LMI_SWAP_CNTL 0xf5b4
1168#define UVD_MP_SWAP_CNTL 0xf5bC
1169#define UVD_MPC_CNTL 0xf5dC
1170#define UVD_MPC_SET_MUXA0 0xf5e4
1171#define UVD_MPC_SET_MUXA1 0xf5e8
1172#define UVD_MPC_SET_MUXB0 0xf5eC
1173#define UVD_MPC_SET_MUXB1 0xf5f0
1174#define UVD_MPC_SET_MUX 0xf5f4
1175#define UVD_MPC_SET_ALU 0xf5f8
1176
1177#define UVD_VCPU_CNTL 0xf660
1178#define UVD_SOFT_RESET 0xf680
1179#define RBC_SOFT_RESET (1<<0)
1180#define LBSI_SOFT_RESET (1<<1)
1181#define LMI_SOFT_RESET (1<<2)
1182#define VCPU_SOFT_RESET (1<<3)
1183#define CSM_SOFT_RESET (1<<5)
1184#define CXW_SOFT_RESET (1<<6)
1185#define TAP_SOFT_RESET (1<<7)
1186#define LMI_UMC_SOFT_RESET (1<<13)
1187#define UVD_RBC_IB_BASE 0xf684
1188#define UVD_RBC_IB_SIZE 0xf688
1189#define UVD_RBC_RB_BASE 0xf68c
1190#define UVD_RBC_RB_RPTR 0xf690
1191#define UVD_RBC_RB_WPTR 0xf694
1192#define UVD_RBC_RB_WPTR_CNTL 0xf698
1193
1194#define UVD_STATUS 0xf6bc
1195
1196#define UVD_SEMA_TIMEOUT_STATUS 0xf6c0
1197#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL 0xf6c4
1198#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL 0xf6c8
1199#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL 0xf6cc
1200
1201#define UVD_RBC_RB_CNTL 0xf6a4
1202#define UVD_RBC_RB_RPTR_ADDR 0xf6a8
1203
1204#define UVD_CONTEXT_ID 0xf6f4
1205
1206/*
1146 * PM4 1207 * PM4
1147 */ 1208 */
1148#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \ 1209#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3db6b02c4263..66e68c1a578f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -110,24 +110,27 @@ extern int radeon_fastfb;
110#define RADEON_BIOS_NUM_SCRATCH 8 110#define RADEON_BIOS_NUM_SCRATCH 8
111 111
112/* max number of rings */ 112/* max number of rings */
113#define RADEON_NUM_RINGS 5 113#define RADEON_NUM_RINGS 6
114 114
115/* fence seq are set to this number when signaled */ 115/* fence seq are set to this number when signaled */
116#define RADEON_FENCE_SIGNALED_SEQ 0LL 116#define RADEON_FENCE_SIGNALED_SEQ 0LL
117 117
118/* internal ring indices */ 118/* internal ring indices */
119/* r1xx+ has gfx CP ring */ 119/* r1xx+ has gfx CP ring */
120#define RADEON_RING_TYPE_GFX_INDEX 0 120#define RADEON_RING_TYPE_GFX_INDEX 0
121 121
122/* cayman has 2 compute CP rings */ 122/* cayman has 2 compute CP rings */
123#define CAYMAN_RING_TYPE_CP1_INDEX 1 123#define CAYMAN_RING_TYPE_CP1_INDEX 1
124#define CAYMAN_RING_TYPE_CP2_INDEX 2 124#define CAYMAN_RING_TYPE_CP2_INDEX 2
125 125
126/* R600+ has an async dma ring */ 126/* R600+ has an async dma ring */
127#define R600_RING_TYPE_DMA_INDEX 3 127#define R600_RING_TYPE_DMA_INDEX 3
128/* cayman add a second async dma ring */ 128/* cayman add a second async dma ring */
129#define CAYMAN_RING_TYPE_DMA1_INDEX 4 129#define CAYMAN_RING_TYPE_DMA1_INDEX 4
130 130
131/* R600+ */
132#define R600_RING_TYPE_UVD_INDEX 5
133
131/* hardcode those limit for now */ 134/* hardcode those limit for now */
132#define RADEON_VA_IB_OFFSET (1 << 20) 135#define RADEON_VA_IB_OFFSET (1 << 20)
133#define RADEON_VA_RESERVED_SIZE (8 << 20) 136#define RADEON_VA_RESERVED_SIZE (8 << 20)
@@ -921,6 +924,7 @@ struct radeon_wb {
921#define R600_WB_DMA_RPTR_OFFSET 1792 924#define R600_WB_DMA_RPTR_OFFSET 1792
922#define R600_WB_IH_WPTR_OFFSET 2048 925#define R600_WB_IH_WPTR_OFFSET 2048
923#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304 926#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304
927#define R600_WB_UVD_RPTR_OFFSET 2560
924#define R600_WB_EVENT_OFFSET 3072 928#define R600_WB_EVENT_OFFSET 3072
925 929
926/** 930/**
@@ -1121,6 +1125,33 @@ struct radeon_pm {
1121int radeon_pm_get_type_index(struct radeon_device *rdev, 1125int radeon_pm_get_type_index(struct radeon_device *rdev,
1122 enum radeon_pm_state_type ps_type, 1126 enum radeon_pm_state_type ps_type,
1123 int instance); 1127 int instance);
1128/*
1129 * UVD
1130 */
1131#define RADEON_MAX_UVD_HANDLES 10
1132#define RADEON_UVD_STACK_SIZE (1024*1024)
1133#define RADEON_UVD_HEAP_SIZE (1024*1024)
1134
1135struct radeon_uvd {
1136 struct radeon_bo *vcpu_bo;
1137 void *cpu_addr;
1138 uint64_t gpu_addr;
1139 atomic_t handles[RADEON_MAX_UVD_HANDLES];
1140 struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
1141};
1142
1143int radeon_uvd_init(struct radeon_device *rdev);
1144void radeon_uvd_fini(struct radeon_device *rdev);
1145int radeon_uvd_suspend(struct radeon_device *rdev);
1146int radeon_uvd_resume(struct radeon_device *rdev);
1147int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring,
1148 uint32_t handle, struct radeon_fence **fence);
1149int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
1150 uint32_t handle, struct radeon_fence **fence);
1151void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo);
1152void radeon_uvd_free_handles(struct radeon_device *rdev,
1153 struct drm_file *filp);
1154int radeon_uvd_cs_parse(struct radeon_cs_parser *parser);
1124 1155
1125struct r600_audio { 1156struct r600_audio {
1126 int channels; 1157 int channels;
@@ -1611,6 +1642,7 @@ struct radeon_device {
1611 struct radeon_asic *asic; 1642 struct radeon_asic *asic;
1612 struct radeon_gem gem; 1643 struct radeon_gem gem;
1613 struct radeon_pm pm; 1644 struct radeon_pm pm;
1645 struct radeon_uvd uvd;
1614 uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; 1646 uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH];
1615 struct radeon_wb wb; 1647 struct radeon_wb wb;
1616 struct radeon_dummy_page dummy_page; 1648 struct radeon_dummy_page dummy_page;
@@ -1625,6 +1657,7 @@ struct radeon_device {
1625 const struct firmware *rlc_fw; /* r6/700 RLC firmware */ 1657 const struct firmware *rlc_fw; /* r6/700 RLC firmware */
1626 const struct firmware *mc_fw; /* NI MC firmware */ 1658 const struct firmware *mc_fw; /* NI MC firmware */
1627 const struct firmware *ce_fw; /* SI CE firmware */ 1659 const struct firmware *ce_fw; /* SI CE firmware */
1660 const struct firmware *uvd_fw; /* UVD firmware */
1628 struct r600_blit r600_blit; 1661 struct r600_blit r600_blit;
1629 struct r600_vram_scratch vram_scratch; 1662 struct r600_vram_scratch vram_scratch;
1630 int msi_enabled; /* msi enabled */ 1663 int msi_enabled; /* msi enabled */
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index aba0a893ea98..a7a7b2bc4204 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1130,6 +1130,15 @@ static struct radeon_asic rv770_asic = {
1130 .ring_test = &r600_dma_ring_test, 1130 .ring_test = &r600_dma_ring_test,
1131 .ib_test = &r600_dma_ib_test, 1131 .ib_test = &r600_dma_ib_test,
1132 .is_lockup = &r600_dma_is_lockup, 1132 .is_lockup = &r600_dma_is_lockup,
1133 },
1134 [R600_RING_TYPE_UVD_INDEX] = {
1135 .ib_execute = &r600_uvd_ib_execute,
1136 .emit_fence = &r600_uvd_fence_emit,
1137 .emit_semaphore = &r600_uvd_semaphore_emit,
1138 .cs_parse = &radeon_uvd_cs_parse,
1139 .ring_test = &r600_uvd_ring_test,
1140 .ib_test = &r600_uvd_ib_test,
1141 .is_lockup = &radeon_ring_test_lockup,
1133 } 1142 }
1134 }, 1143 },
1135 .irq = { 1144 .irq = {
@@ -1216,6 +1225,15 @@ static struct radeon_asic evergreen_asic = {
1216 .ring_test = &r600_dma_ring_test, 1225 .ring_test = &r600_dma_ring_test,
1217 .ib_test = &r600_dma_ib_test, 1226 .ib_test = &r600_dma_ib_test,
1218 .is_lockup = &evergreen_dma_is_lockup, 1227 .is_lockup = &evergreen_dma_is_lockup,
1228 },
1229 [R600_RING_TYPE_UVD_INDEX] = {
1230 .ib_execute = &r600_uvd_ib_execute,
1231 .emit_fence = &r600_uvd_fence_emit,
1232 .emit_semaphore = &r600_uvd_semaphore_emit,
1233 .cs_parse = &radeon_uvd_cs_parse,
1234 .ring_test = &r600_uvd_ring_test,
1235 .ib_test = &r600_uvd_ib_test,
1236 .is_lockup = &radeon_ring_test_lockup,
1219 } 1237 }
1220 }, 1238 },
1221 .irq = { 1239 .irq = {
@@ -1302,6 +1320,15 @@ static struct radeon_asic sumo_asic = {
1302 .ring_test = &r600_dma_ring_test, 1320 .ring_test = &r600_dma_ring_test,
1303 .ib_test = &r600_dma_ib_test, 1321 .ib_test = &r600_dma_ib_test,
1304 .is_lockup = &evergreen_dma_is_lockup, 1322 .is_lockup = &evergreen_dma_is_lockup,
1323 },
1324 [R600_RING_TYPE_UVD_INDEX] = {
1325 .ib_execute = &r600_uvd_ib_execute,
1326 .emit_fence = &r600_uvd_fence_emit,
1327 .emit_semaphore = &r600_uvd_semaphore_emit,
1328 .cs_parse = &radeon_uvd_cs_parse,
1329 .ring_test = &r600_uvd_ring_test,
1330 .ib_test = &r600_uvd_ib_test,
1331 .is_lockup = &radeon_ring_test_lockup,
1305 } 1332 }
1306 }, 1333 },
1307 .irq = { 1334 .irq = {
@@ -1388,6 +1415,15 @@ static struct radeon_asic btc_asic = {
1388 .ring_test = &r600_dma_ring_test, 1415 .ring_test = &r600_dma_ring_test,
1389 .ib_test = &r600_dma_ib_test, 1416 .ib_test = &r600_dma_ib_test,
1390 .is_lockup = &evergreen_dma_is_lockup, 1417 .is_lockup = &evergreen_dma_is_lockup,
1418 },
1419 [R600_RING_TYPE_UVD_INDEX] = {
1420 .ib_execute = &r600_uvd_ib_execute,
1421 .emit_fence = &r600_uvd_fence_emit,
1422 .emit_semaphore = &r600_uvd_semaphore_emit,
1423 .cs_parse = &radeon_uvd_cs_parse,
1424 .ring_test = &r600_uvd_ring_test,
1425 .ib_test = &r600_uvd_ib_test,
1426 .is_lockup = &radeon_ring_test_lockup,
1391 } 1427 }
1392 }, 1428 },
1393 .irq = { 1429 .irq = {
@@ -1517,6 +1553,15 @@ static struct radeon_asic cayman_asic = {
1517 .ib_test = &r600_dma_ib_test, 1553 .ib_test = &r600_dma_ib_test,
1518 .is_lockup = &cayman_dma_is_lockup, 1554 .is_lockup = &cayman_dma_is_lockup,
1519 .vm_flush = &cayman_dma_vm_flush, 1555 .vm_flush = &cayman_dma_vm_flush,
1556 },
1557 [R600_RING_TYPE_UVD_INDEX] = {
1558 .ib_execute = &r600_uvd_ib_execute,
1559 .emit_fence = &r600_uvd_fence_emit,
1560 .emit_semaphore = &cayman_uvd_semaphore_emit,
1561 .cs_parse = &radeon_uvd_cs_parse,
1562 .ring_test = &r600_uvd_ring_test,
1563 .ib_test = &r600_uvd_ib_test,
1564 .is_lockup = &radeon_ring_test_lockup,
1520 } 1565 }
1521 }, 1566 },
1522 .irq = { 1567 .irq = {
@@ -1646,6 +1691,15 @@ static struct radeon_asic trinity_asic = {
1646 .ib_test = &r600_dma_ib_test, 1691 .ib_test = &r600_dma_ib_test,
1647 .is_lockup = &cayman_dma_is_lockup, 1692 .is_lockup = &cayman_dma_is_lockup,
1648 .vm_flush = &cayman_dma_vm_flush, 1693 .vm_flush = &cayman_dma_vm_flush,
1694 },
1695 [R600_RING_TYPE_UVD_INDEX] = {
1696 .ib_execute = &r600_uvd_ib_execute,
1697 .emit_fence = &r600_uvd_fence_emit,
1698 .emit_semaphore = &cayman_uvd_semaphore_emit,
1699 .cs_parse = &radeon_uvd_cs_parse,
1700 .ring_test = &r600_uvd_ring_test,
1701 .ib_test = &r600_uvd_ib_test,
1702 .is_lockup = &radeon_ring_test_lockup,
1649 } 1703 }
1650 }, 1704 },
1651 .irq = { 1705 .irq = {
@@ -1775,6 +1829,15 @@ static struct radeon_asic si_asic = {
1775 .ib_test = &r600_dma_ib_test, 1829 .ib_test = &r600_dma_ib_test,
1776 .is_lockup = &si_dma_is_lockup, 1830 .is_lockup = &si_dma_is_lockup,
1777 .vm_flush = &si_dma_vm_flush, 1831 .vm_flush = &si_dma_vm_flush,
1832 },
1833 [R600_RING_TYPE_UVD_INDEX] = {
1834 .ib_execute = &r600_uvd_ib_execute,
1835 .emit_fence = &r600_uvd_fence_emit,
1836 .emit_semaphore = &cayman_uvd_semaphore_emit,
1837 .cs_parse = &radeon_uvd_cs_parse,
1838 .ring_test = &r600_uvd_ring_test,
1839 .ib_test = &r600_uvd_ib_test,
1840 .is_lockup = &radeon_ring_test_lockup,
1778 } 1841 }
1779 }, 1842 },
1780 .irq = { 1843 .irq = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 3535f73ad3e2..515db96e3e2c 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -330,6 +330,7 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
330void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); 330void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
331int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); 331int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
332int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); 332int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
333int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
333int r600_copy_blit(struct radeon_device *rdev, 334int r600_copy_blit(struct radeon_device *rdev,
334 uint64_t src_offset, uint64_t dst_offset, 335 uint64_t src_offset, uint64_t dst_offset,
335 unsigned num_gpu_pages, struct radeon_fence **fence); 336 unsigned num_gpu_pages, struct radeon_fence **fence);
@@ -392,6 +393,19 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
392u32 r600_get_xclk(struct radeon_device *rdev); 393u32 r600_get_xclk(struct radeon_device *rdev);
393uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); 394uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
394 395
396/* uvd */
397int r600_uvd_init(struct radeon_device *rdev);
398int r600_uvd_rbc_start(struct radeon_device *rdev);
399void r600_uvd_rbc_stop(struct radeon_device *rdev);
400int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
401void r600_uvd_fence_emit(struct radeon_device *rdev,
402 struct radeon_fence *fence);
403void r600_uvd_semaphore_emit(struct radeon_device *rdev,
404 struct radeon_ring *ring,
405 struct radeon_semaphore *semaphore,
406 bool emit_wait);
407void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
408
395/* 409/*
396 * rv770,rv730,rv710,rv740 410 * rv770,rv730,rv710,rv740
397 */ 411 */
@@ -409,6 +423,7 @@ int rv770_copy_dma(struct radeon_device *rdev,
409 unsigned num_gpu_pages, 423 unsigned num_gpu_pages,
410 struct radeon_fence **fence); 424 struct radeon_fence **fence);
411u32 rv770_get_xclk(struct radeon_device *rdev); 425u32 rv770_get_xclk(struct radeon_device *rdev);
426int rv770_uvd_resume(struct radeon_device *rdev);
412 427
413/* 428/*
414 * evergreen 429 * evergreen
@@ -465,6 +480,10 @@ int evergreen_copy_dma(struct radeon_device *rdev,
465 */ 480 */
466void cayman_fence_ring_emit(struct radeon_device *rdev, 481void cayman_fence_ring_emit(struct radeon_device *rdev,
467 struct radeon_fence *fence); 482 struct radeon_fence *fence);
483void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
484 struct radeon_ring *ring,
485 struct radeon_semaphore *semaphore,
486 bool emit_wait);
468void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); 487void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev);
469int cayman_init(struct radeon_device *rdev); 488int cayman_init(struct radeon_device *rdev);
470void cayman_fini(struct radeon_device *rdev); 489void cayman_fini(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index c9ee4c02522a..c7407074c09b 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -53,7 +53,6 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
53 } 53 }
54 for (i = 0; i < p->nrelocs; i++) { 54 for (i = 0; i < p->nrelocs; i++) {
55 struct drm_radeon_cs_reloc *r; 55 struct drm_radeon_cs_reloc *r;
56 uint32_t domain;
57 56
58 duplicate = false; 57 duplicate = false;
59 r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4]; 58 r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
@@ -81,11 +80,25 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
81 p->relocs[i].lobj.bo = p->relocs[i].robj; 80 p->relocs[i].lobj.bo = p->relocs[i].robj;
82 p->relocs[i].lobj.written = !!r->write_domain; 81 p->relocs[i].lobj.written = !!r->write_domain;
83 82
84 domain = r->write_domain ? r->write_domain : r->read_domains; 83 /* the first reloc of an UVD job is the
85 p->relocs[i].lobj.domain = domain; 84 msg and that must be in VRAM */
86 if (domain == RADEON_GEM_DOMAIN_VRAM) 85 if (p->ring == R600_RING_TYPE_UVD_INDEX && i == 0) {
87 domain |= RADEON_GEM_DOMAIN_GTT; 86 /* TODO: is this still needed for NI+ ? */
88 p->relocs[i].lobj.alt_domain = domain; 87 p->relocs[i].lobj.domain =
88 RADEON_GEM_DOMAIN_VRAM;
89
90 p->relocs[i].lobj.alt_domain =
91 RADEON_GEM_DOMAIN_VRAM;
92
93 } else {
94 uint32_t domain = r->write_domain ?
95 r->write_domain : r->read_domains;
96
97 p->relocs[i].lobj.domain = domain;
98 if (domain == RADEON_GEM_DOMAIN_VRAM)
99 domain |= RADEON_GEM_DOMAIN_GTT;
100 p->relocs[i].lobj.alt_domain = domain;
101 }
89 102
90 p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; 103 p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo;
91 p->relocs[i].handle = r->handle; 104 p->relocs[i].handle = r->handle;
@@ -93,7 +106,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
93 radeon_bo_list_add_object(&p->relocs[i].lobj, 106 radeon_bo_list_add_object(&p->relocs[i].lobj,
94 &p->validated); 107 &p->validated);
95 } 108 }
96 return radeon_bo_list_validate(&p->validated); 109 return radeon_bo_list_validate(&p->validated, p->ring);
97} 110}
98 111
99static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) 112static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
@@ -128,6 +141,9 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
128 return -EINVAL; 141 return -EINVAL;
129 } 142 }
130 break; 143 break;
144 case RADEON_CS_RING_UVD:
145 p->ring = R600_RING_TYPE_UVD_INDEX;
146 break;
131 } 147 }
132 return 0; 148 return 0;
133} 149}
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 34356252567a..82fe1835ff8c 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -31,9 +31,9 @@
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/atomic.h> 32#include <linux/atomic.h>
33#include <linux/wait.h> 33#include <linux/wait.h>
34#include <linux/list.h>
35#include <linux/kref.h> 34#include <linux/kref.h>
36#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/firmware.h>
37#include <drm/drmP.h> 37#include <drm/drmP.h>
38#include "radeon_reg.h" 38#include "radeon_reg.h"
39#include "radeon.h" 39#include "radeon.h"
@@ -767,8 +767,21 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
767 767
768 radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); 768 radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
769 if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) { 769 if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) {
770 rdev->fence_drv[ring].scratch_reg = 0; 770 if (ring != R600_RING_TYPE_UVD_INDEX) {
771 index = R600_WB_EVENT_OFFSET + ring * 4; 771 rdev->fence_drv[ring].scratch_reg = 0;
772 index = R600_WB_EVENT_OFFSET + ring * 4;
773 rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
774 rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr +
775 index;
776
777 } else {
778 /* put fence directly behind firmware */
779 rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr +
780 rdev->uvd_fw->size;
781 rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr +
782 rdev->uvd_fw->size;
783 }
784
772 } else { 785 } else {
773 r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg); 786 r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg);
774 if (r) { 787 if (r) {
@@ -778,9 +791,9 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
778 index = RADEON_WB_SCRATCH_OFFSET + 791 index = RADEON_WB_SCRATCH_OFFSET +
779 rdev->fence_drv[ring].scratch_reg - 792 rdev->fence_drv[ring].scratch_reg -
780 rdev->scratch.reg_base; 793 rdev->scratch.reg_base;
794 rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
795 rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
781 } 796 }
782 rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
783 rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
784 radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); 797 radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring);
785 rdev->fence_drv[ring].initialized = true; 798 rdev->fence_drv[ring].initialized = true;
786 dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", 799 dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n",
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index f5464482dee8..8365c75b31b6 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -516,6 +516,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
516 rdev->hyperz_filp = NULL; 516 rdev->hyperz_filp = NULL;
517 if (rdev->cmask_filp == file_priv) 517 if (rdev->cmask_filp == file_priv)
518 rdev->cmask_filp = NULL; 518 rdev->cmask_filp = NULL;
519 radeon_uvd_free_handles(rdev, file_priv);
519} 520}
520 521
521/* 522/*
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 4466477f1e7b..1424ccde2377 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -348,7 +348,7 @@ void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
348 } 348 }
349} 349}
350 350
351int radeon_bo_list_validate(struct list_head *head) 351int radeon_bo_list_validate(struct list_head *head, int ring)
352{ 352{
353 struct radeon_bo_list *lobj; 353 struct radeon_bo_list *lobj;
354 struct radeon_bo *bo; 354 struct radeon_bo *bo;
@@ -366,6 +366,8 @@ int radeon_bo_list_validate(struct list_head *head)
366 366
367 retry: 367 retry:
368 radeon_ttm_placement_from_domain(bo, domain); 368 radeon_ttm_placement_from_domain(bo, domain);
369 if (ring == R600_RING_TYPE_UVD_INDEX)
370 radeon_uvd_force_into_uvd_segment(bo);
369 r = ttm_bo_validate(&bo->tbo, &bo->placement, 371 r = ttm_bo_validate(&bo->tbo, &bo->placement,
370 true, false); 372 true, false);
371 if (unlikely(r)) { 373 if (unlikely(r)) {
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 5fc86b03043b..e2cb80a96b51 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -128,7 +128,7 @@ extern int radeon_bo_init(struct radeon_device *rdev);
128extern void radeon_bo_fini(struct radeon_device *rdev); 128extern void radeon_bo_fini(struct radeon_device *rdev);
129extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, 129extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
130 struct list_head *head); 130 struct list_head *head);
131extern int radeon_bo_list_validate(struct list_head *head); 131extern int radeon_bo_list_validate(struct list_head *head, int ring);
132extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, 132extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
133 struct vm_area_struct *vma); 133 struct vm_area_struct *vma);
134extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, 134extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 8d58e268ff6d..31e47d898c46 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -368,7 +368,7 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
368{ 368{
369 u32 rptr; 369 u32 rptr;
370 370
371 if (rdev->wb.enabled) 371 if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX])
372 rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); 372 rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
373 else 373 else
374 rptr = RREG32(ring->rptr_reg); 374 rptr = RREG32(ring->rptr_reg);
@@ -821,18 +821,20 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
821 return 0; 821 return 0;
822} 822}
823 823
824static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX; 824static int radeon_gfx_index = RADEON_RING_TYPE_GFX_INDEX;
825static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX; 825static int cayman_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX;
826static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; 826static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX;
827static int radeon_ring_type_dma1_index = R600_RING_TYPE_DMA_INDEX; 827static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX;
828static int radeon_ring_type_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; 828static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX;
829static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX;
829 830
830static struct drm_info_list radeon_debugfs_ring_info_list[] = { 831static struct drm_info_list radeon_debugfs_ring_info_list[] = {
831 {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index}, 832 {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index},
832 {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index}, 833 {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_cp1_index},
833 {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index}, 834 {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_cp2_index},
834 {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma1_index}, 835 {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index},
835 {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma2_index}, 836 {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index},
837 {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index},
836}; 838};
837 839
838static int radeon_debugfs_sa_info(struct seq_file *m, void *data) 840static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index fda09c9ea689..bbed4af8d0bc 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -252,6 +252,36 @@ void radeon_test_moves(struct radeon_device *rdev)
252 radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); 252 radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT);
253} 253}
254 254
255static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
256 struct radeon_ring *ring,
257 struct radeon_fence **fence)
258{
259 int r;
260
261 if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
262 r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
263 if (r) {
264 DRM_ERROR("Failed to get dummy create msg\n");
265 return r;
266 }
267
268 r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence);
269 if (r) {
270 DRM_ERROR("Failed to get dummy destroy msg\n");
271 return r;
272 }
273 } else {
274 r = radeon_ring_lock(rdev, ring, 64);
275 if (r) {
276 DRM_ERROR("Failed to lock ring A %d\n", ring->idx);
277 return r;
278 }
279 radeon_fence_emit(rdev, fence, ring->idx);
280 radeon_ring_unlock_commit(rdev, ring);
281 }
282 return 0;
283}
284
255void radeon_test_ring_sync(struct radeon_device *rdev, 285void radeon_test_ring_sync(struct radeon_device *rdev,
256 struct radeon_ring *ringA, 286 struct radeon_ring *ringA,
257 struct radeon_ring *ringB) 287 struct radeon_ring *ringB)
@@ -272,21 +302,24 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
272 goto out_cleanup; 302 goto out_cleanup;
273 } 303 }
274 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 304 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
275 r = radeon_fence_emit(rdev, &fence1, ringA->idx); 305 radeon_ring_unlock_commit(rdev, ringA);
276 if (r) { 306
277 DRM_ERROR("Failed to emit fence 1\n"); 307 r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1);
278 radeon_ring_unlock_undo(rdev, ringA); 308 if (r)
279 goto out_cleanup; 309 goto out_cleanup;
280 } 310
281 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 311 r = radeon_ring_lock(rdev, ringA, 64);
282 r = radeon_fence_emit(rdev, &fence2, ringA->idx);
283 if (r) { 312 if (r) {
284 DRM_ERROR("Failed to emit fence 2\n"); 313 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
285 radeon_ring_unlock_undo(rdev, ringA);
286 goto out_cleanup; 314 goto out_cleanup;
287 } 315 }
316 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
288 radeon_ring_unlock_commit(rdev, ringA); 317 radeon_ring_unlock_commit(rdev, ringA);
289 318
319 r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2);
320 if (r)
321 goto out_cleanup;
322
290 mdelay(1000); 323 mdelay(1000);
291 324
292 if (radeon_fence_signaled(fence1)) { 325 if (radeon_fence_signaled(fence1)) {
@@ -364,27 +397,22 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
364 goto out_cleanup; 397 goto out_cleanup;
365 } 398 }
366 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 399 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
367 r = radeon_fence_emit(rdev, &fenceA, ringA->idx);
368 if (r) {
369 DRM_ERROR("Failed to emit sync fence 1\n");
370 radeon_ring_unlock_undo(rdev, ringA);
371 goto out_cleanup;
372 }
373 radeon_ring_unlock_commit(rdev, ringA); 400 radeon_ring_unlock_commit(rdev, ringA);
374 401
402 r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA);
403 if (r)
404 goto out_cleanup;
405
375 r = radeon_ring_lock(rdev, ringB, 64); 406 r = radeon_ring_lock(rdev, ringB, 64);
376 if (r) { 407 if (r) {
377 DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); 408 DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
378 goto out_cleanup; 409 goto out_cleanup;
379 } 410 }
380 radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); 411 radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
381 r = radeon_fence_emit(rdev, &fenceB, ringB->idx);
382 if (r) {
383 DRM_ERROR("Failed to create sync fence 2\n");
384 radeon_ring_unlock_undo(rdev, ringB);
385 goto out_cleanup;
386 }
387 radeon_ring_unlock_commit(rdev, ringB); 412 radeon_ring_unlock_commit(rdev, ringB);
413 r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB);
414 if (r)
415 goto out_cleanup;
388 416
389 mdelay(1000); 417 mdelay(1000);
390 418
@@ -393,7 +421,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
393 goto out_cleanup; 421 goto out_cleanup;
394 } 422 }
395 if (radeon_fence_signaled(fenceB)) { 423 if (radeon_fence_signaled(fenceB)) {
396 DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 424 DRM_ERROR("Fence B signaled without waiting for semaphore.\n");
397 goto out_cleanup; 425 goto out_cleanup;
398 } 426 }
399 427
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
new file mode 100644
index 000000000000..05a192e95e5d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -0,0 +1,664 @@
1/*
2 * Copyright 2011 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 * Authors:
28 * Christian König <deathsimple@vodafone.de>
29 */
30
31#include <linux/firmware.h>
32#include <linux/module.h>
33#include <drm/drmP.h>
34#include <drm/drm.h>
35
36#include "radeon.h"
37#include "r600d.h"
38
39/* Firmware Names */
40#define FIRMWARE_RV710 "radeon/RV710_uvd.bin"
41#define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin"
42#define FIRMWARE_SUMO "radeon/SUMO_uvd.bin"
43#define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin"
44
45MODULE_FIRMWARE(FIRMWARE_RV710);
46MODULE_FIRMWARE(FIRMWARE_CYPRESS);
47MODULE_FIRMWARE(FIRMWARE_SUMO);
48MODULE_FIRMWARE(FIRMWARE_TAHITI);
49
50int radeon_uvd_init(struct radeon_device *rdev)
51{
52 struct platform_device *pdev;
53 unsigned long bo_size;
54 const char *fw_name;
55 int i, r;
56
57 pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0);
58 r = IS_ERR(pdev);
59 if (r) {
60 dev_err(rdev->dev, "radeon_uvd: Failed to register firmware\n");
61 return -EINVAL;
62 }
63
64 switch (rdev->family) {
65 case CHIP_RV710:
66 case CHIP_RV730:
67 case CHIP_RV740:
68 fw_name = FIRMWARE_RV710;
69 break;
70
71 case CHIP_CYPRESS:
72 case CHIP_HEMLOCK:
73 case CHIP_JUNIPER:
74 case CHIP_REDWOOD:
75 case CHIP_CEDAR:
76 fw_name = FIRMWARE_CYPRESS;
77 break;
78
79 case CHIP_SUMO:
80 case CHIP_SUMO2:
81 case CHIP_PALM:
82 case CHIP_CAYMAN:
83 case CHIP_BARTS:
84 case CHIP_TURKS:
85 case CHIP_CAICOS:
86 fw_name = FIRMWARE_SUMO;
87 break;
88
89 case CHIP_TAHITI:
90 case CHIP_VERDE:
91 case CHIP_PITCAIRN:
92 case CHIP_ARUBA:
93 fw_name = FIRMWARE_TAHITI;
94 break;
95
96 default:
97 return -EINVAL;
98 }
99
100 r = request_firmware(&rdev->uvd_fw, fw_name, &pdev->dev);
101 if (r) {
102 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
103 fw_name);
104 platform_device_unregister(pdev);
105 return r;
106 }
107
108 platform_device_unregister(pdev);
109
110 bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) +
111 RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
112 r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
113 RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
114 if (r) {
115 dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r);
116 return r;
117 }
118
119 r = radeon_uvd_resume(rdev);
120 if (r)
121 return r;
122
123 memset(rdev->uvd.cpu_addr, 0, bo_size);
124 memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
125
126 r = radeon_uvd_suspend(rdev);
127 if (r)
128 return r;
129
130 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
131 atomic_set(&rdev->uvd.handles[i], 0);
132 rdev->uvd.filp[i] = NULL;
133 }
134
135 return 0;
136}
137
138void radeon_uvd_fini(struct radeon_device *rdev)
139{
140 radeon_uvd_suspend(rdev);
141 radeon_bo_unref(&rdev->uvd.vcpu_bo);
142}
143
144int radeon_uvd_suspend(struct radeon_device *rdev)
145{
146 int r;
147
148 if (rdev->uvd.vcpu_bo == NULL)
149 return 0;
150
151 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
152 if (!r) {
153 radeon_bo_kunmap(rdev->uvd.vcpu_bo);
154 radeon_bo_unpin(rdev->uvd.vcpu_bo);
155 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
156 }
157 return r;
158}
159
160int radeon_uvd_resume(struct radeon_device *rdev)
161{
162 int r;
163
164 if (rdev->uvd.vcpu_bo == NULL)
165 return -EINVAL;
166
167 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
168 if (r) {
169 radeon_bo_unref(&rdev->uvd.vcpu_bo);
170 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
171 return r;
172 }
173
174 r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
175 &rdev->uvd.gpu_addr);
176 if (r) {
177 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
178 radeon_bo_unref(&rdev->uvd.vcpu_bo);
179 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
180 return r;
181 }
182
183 r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
184 if (r) {
185 dev_err(rdev->dev, "(%d) UVD map failed\n", r);
186 return r;
187 }
188
189 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
190
191 return 0;
192}
193
194void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo)
195{
196 rbo->placement.fpfn = 0 >> PAGE_SHIFT;
197 rbo->placement.lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
198}
199
200void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
201{
202 int i, r;
203 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
204 if (rdev->uvd.filp[i] == filp) {
205 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
206 struct radeon_fence *fence;
207
208 r = radeon_uvd_get_destroy_msg(rdev,
209 R600_RING_TYPE_UVD_INDEX, handle, &fence);
210 if (r) {
211 DRM_ERROR("Error destroying UVD (%d)!\n", r);
212 continue;
213 }
214
215 radeon_fence_wait(fence, false);
216 radeon_fence_unref(&fence);
217
218 rdev->uvd.filp[i] = NULL;
219 atomic_set(&rdev->uvd.handles[i], 0);
220 }
221 }
222}
223
224static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
225{
226 unsigned stream_type = msg[4];
227 unsigned width = msg[6];
228 unsigned height = msg[7];
229 unsigned dpb_size = msg[9];
230 unsigned pitch = msg[28];
231
232 unsigned width_in_mb = width / 16;
233 unsigned height_in_mb = ALIGN(height / 16, 2);
234
235 unsigned image_size, tmp, min_dpb_size;
236
237 image_size = width * height;
238 image_size += image_size / 2;
239 image_size = ALIGN(image_size, 1024);
240
241 switch (stream_type) {
242 case 0: /* H264 */
243
244 /* reference picture buffer */
245 min_dpb_size = image_size * 17;
246
247 /* macroblock context buffer */
248 min_dpb_size += width_in_mb * height_in_mb * 17 * 192;
249
250 /* IT surface buffer */
251 min_dpb_size += width_in_mb * height_in_mb * 32;
252 break;
253
254 case 1: /* VC1 */
255
256 /* reference picture buffer */
257 min_dpb_size = image_size * 3;
258
259 /* CONTEXT_BUFFER */
260 min_dpb_size += width_in_mb * height_in_mb * 128;
261
262 /* IT surface buffer */
263 min_dpb_size += width_in_mb * 64;
264
265 /* DB surface buffer */
266 min_dpb_size += width_in_mb * 128;
267
268 /* BP */
269 tmp = max(width_in_mb, height_in_mb);
270 min_dpb_size += ALIGN(tmp * 7 * 16, 64);
271 break;
272
273 case 3: /* MPEG2 */
274
275 /* reference picture buffer */
276 min_dpb_size = image_size * 3;
277 break;
278
279 case 4: /* MPEG4 */
280
281 /* reference picture buffer */
282 min_dpb_size = image_size * 3;
283
284 /* CM */
285 min_dpb_size += width_in_mb * height_in_mb * 64;
286
287 /* IT surface buffer */
288 min_dpb_size += ALIGN(width_in_mb * height_in_mb * 32, 64);
289 break;
290
291 default:
292 DRM_ERROR("UVD codec not handled %d!\n", stream_type);
293 return -EINVAL;
294 }
295
296 if (width > pitch) {
297 DRM_ERROR("Invalid UVD decoding target pitch!\n");
298 return -EINVAL;
299 }
300
301 if (dpb_size < min_dpb_size) {
302 DRM_ERROR("Invalid dpb_size in UVD message (%d / %d)!\n",
303 dpb_size, min_dpb_size);
304 return -EINVAL;
305 }
306
307 buf_sizes[0x1] = dpb_size;
308 buf_sizes[0x2] = image_size;
309 return 0;
310}
311
312static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
313 unsigned offset, unsigned buf_sizes[])
314{
315 int32_t *msg, msg_type, handle;
316 void *ptr;
317
318 int i, r;
319
320 if (offset & 0x3F) {
321 DRM_ERROR("UVD messages must be 64 byte aligned!\n");
322 return -EINVAL;
323 }
324
325 r = radeon_bo_kmap(bo, &ptr);
326 if (r)
327 return r;
328
329 msg = ptr + offset;
330
331 msg_type = msg[1];
332 handle = msg[2];
333
334 if (handle == 0) {
335 DRM_ERROR("Invalid UVD handle!\n");
336 return -EINVAL;
337 }
338
339 if (msg_type == 1) {
340 /* it's a decode msg, calc buffer sizes */
341 r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
342 radeon_bo_kunmap(bo);
343 if (r)
344 return r;
345
346 } else if (msg_type == 2) {
347 /* it's a destroy msg, free the handle */
348 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
349 atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
350 radeon_bo_kunmap(bo);
351 return 0;
352 } else {
353 /* it's a create msg, no special handling needed */
354 radeon_bo_kunmap(bo);
355 }
356
357 /* create or decode, validate the handle */
358 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
359 if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
360 return 0;
361 }
362
363 /* handle not found try to alloc a new one */
364 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
365 if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
366 p->rdev->uvd.filp[i] = p->filp;
367 return 0;
368 }
369 }
370
371 DRM_ERROR("No more free UVD handles!\n");
372 return -EINVAL;
373}
374
375static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
376 int data0, int data1,
377 unsigned buf_sizes[])
378{
379 struct radeon_cs_chunk *relocs_chunk;
380 struct radeon_cs_reloc *reloc;
381 unsigned idx, cmd, offset;
382 uint64_t start, end;
383 int r;
384
385 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
386 offset = radeon_get_ib_value(p, data0);
387 idx = radeon_get_ib_value(p, data1);
388 if (idx >= relocs_chunk->length_dw) {
389 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
390 idx, relocs_chunk->length_dw);
391 return -EINVAL;
392 }
393
394 reloc = p->relocs_ptr[(idx / 4)];
395 start = reloc->lobj.gpu_offset;
396 end = start + radeon_bo_size(reloc->robj);
397 start += offset;
398
399 p->ib.ptr[data0] = start & 0xFFFFFFFF;
400 p->ib.ptr[data1] = start >> 32;
401
402 cmd = radeon_get_ib_value(p, p->idx) >> 1;
403
404 if (cmd < 0x4) {
405 if ((end - start) < buf_sizes[cmd]) {
406 DRM_ERROR("buffer to small (%d / %d)!\n",
407 (unsigned)(end - start), buf_sizes[cmd]);
408 return -EINVAL;
409 }
410
411 } else if (cmd != 0x100) {
412 DRM_ERROR("invalid UVD command %X!\n", cmd);
413 return -EINVAL;
414 }
415
416 if (cmd == 0) {
417 if (end & 0xFFFFFFFFF0000000) {
418 DRM_ERROR("msg buffer %LX-%LX out of 256MB segment!\n",
419 start, end);
420 return -EINVAL;
421 }
422
423 r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes);
424 if (r)
425 return r;
426 }
427
428 if ((start & 0xFFFFFFFFF0000000) != (end & 0xFFFFFFFFF0000000)) {
429 DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
430 start, end);
431 return -EINVAL;
432 }
433
434 return 0;
435}
436
437static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
438 struct radeon_cs_packet *pkt,
439 int *data0, int *data1,
440 unsigned buf_sizes[])
441{
442 int i, r;
443
444 p->idx++;
445 for (i = 0; i <= pkt->count; ++i) {
446 switch (pkt->reg + i*4) {
447 case UVD_GPCOM_VCPU_DATA0:
448 *data0 = p->idx;
449 break;
450 case UVD_GPCOM_VCPU_DATA1:
451 *data1 = p->idx;
452 break;
453 case UVD_GPCOM_VCPU_CMD:
454 r = radeon_uvd_cs_reloc(p, *data0, *data1, buf_sizes);
455 if (r)
456 return r;
457 break;
458 case UVD_ENGINE_CNTL:
459 break;
460 default:
461 DRM_ERROR("Invalid reg 0x%X!\n",
462 pkt->reg + i*4);
463 return -EINVAL;
464 }
465 p->idx++;
466 }
467 return 0;
468}
469
470int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
471{
472 struct radeon_cs_packet pkt;
473 int r, data0 = 0, data1 = 0;
474
475 /* minimum buffer sizes */
476 unsigned buf_sizes[] = {
477 [0x00000000] = 2048,
478 [0x00000001] = 32 * 1024 * 1024,
479 [0x00000002] = 2048 * 1152 * 3,
480 [0x00000003] = 2048,
481 };
482
483 if (p->chunks[p->chunk_ib_idx].length_dw % 16) {
484 DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n",
485 p->chunks[p->chunk_ib_idx].length_dw);
486 return -EINVAL;
487 }
488
489 if (p->chunk_relocs_idx == -1) {
490 DRM_ERROR("No relocation chunk !\n");
491 return -EINVAL;
492 }
493
494
495 do {
496 r = radeon_cs_packet_parse(p, &pkt, p->idx);
497 if (r)
498 return r;
499 switch (pkt.type) {
500 case RADEON_PACKET_TYPE0:
501 r = radeon_uvd_cs_reg(p, &pkt, &data0,
502 &data1, buf_sizes);
503 if (r)
504 return r;
505 break;
506 case RADEON_PACKET_TYPE2:
507 p->idx += pkt.count + 2;
508 break;
509 default:
510 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
511 return -EINVAL;
512 }
513 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
514 return 0;
515}
516
517static int radeon_uvd_send_msg(struct radeon_device *rdev,
518 int ring, struct radeon_bo *bo,
519 struct radeon_fence **fence)
520{
521 struct ttm_validate_buffer tv;
522 struct list_head head;
523 struct radeon_ib ib;
524 uint64_t addr;
525 int i, r;
526
527 memset(&tv, 0, sizeof(tv));
528 tv.bo = &bo->tbo;
529
530 INIT_LIST_HEAD(&head);
531 list_add(&tv.head, &head);
532
533 r = ttm_eu_reserve_buffers(&head);
534 if (r)
535 return r;
536
537 radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_VRAM);
538 radeon_uvd_force_into_uvd_segment(bo);
539
540 r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
541 if (r) {
542 ttm_eu_backoff_reservation(&head);
543 return r;
544 }
545
546 r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
547 if (r) {
548 ttm_eu_backoff_reservation(&head);
549 return r;
550 }
551
552 addr = radeon_bo_gpu_offset(bo);
553 ib.ptr[0] = PACKET0(UVD_GPCOM_VCPU_DATA0, 0);
554 ib.ptr[1] = addr;
555 ib.ptr[2] = PACKET0(UVD_GPCOM_VCPU_DATA1, 0);
556 ib.ptr[3] = addr >> 32;
557 ib.ptr[4] = PACKET0(UVD_GPCOM_VCPU_CMD, 0);
558 ib.ptr[5] = 0;
559 for (i = 6; i < 16; ++i)
560 ib.ptr[i] = PACKET2(0);
561 ib.length_dw = 16;
562
563 r = radeon_ib_schedule(rdev, &ib, NULL);
564 if (r) {
565 ttm_eu_backoff_reservation(&head);
566 return r;
567 }
568 ttm_eu_fence_buffer_objects(&head, ib.fence);
569
570 if (fence)
571 *fence = radeon_fence_ref(ib.fence);
572
573 radeon_ib_free(rdev, &ib);
574 radeon_bo_unref(&bo);
575 return 0;
576}
577
578/* multiple fence commands without any stream commands in between can
579 crash the vcpu so just try to emmit a dummy create/destroy msg to
580 avoid this */
581int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring,
582 uint32_t handle, struct radeon_fence **fence)
583{
584 struct radeon_bo *bo;
585 uint32_t *msg;
586 int r, i;
587
588 r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
589 RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
590 if (r)
591 return r;
592
593 r = radeon_bo_reserve(bo, false);
594 if (r) {
595 radeon_bo_unref(&bo);
596 return r;
597 }
598
599 r = radeon_bo_kmap(bo, (void **)&msg);
600 if (r) {
601 radeon_bo_unreserve(bo);
602 radeon_bo_unref(&bo);
603 return r;
604 }
605
606 /* stitch together an UVD create msg */
607 msg[0] = 0x00000de4;
608 msg[1] = 0x00000000;
609 msg[2] = handle;
610 msg[3] = 0x00000000;
611 msg[4] = 0x00000000;
612 msg[5] = 0x00000000;
613 msg[6] = 0x00000000;
614 msg[7] = 0x00000780;
615 msg[8] = 0x00000440;
616 msg[9] = 0x00000000;
617 msg[10] = 0x01b37000;
618 for (i = 11; i < 1024; ++i)
619 msg[i] = 0x0;
620
621 radeon_bo_kunmap(bo);
622 radeon_bo_unreserve(bo);
623
624 return radeon_uvd_send_msg(rdev, ring, bo, fence);
625}
626
627int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
628 uint32_t handle, struct radeon_fence **fence)
629{
630 struct radeon_bo *bo;
631 uint32_t *msg;
632 int r, i;
633
634 r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
635 RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
636 if (r)
637 return r;
638
639 r = radeon_bo_reserve(bo, false);
640 if (r) {
641 radeon_bo_unref(&bo);
642 return r;
643 }
644
645 r = radeon_bo_kmap(bo, (void **)&msg);
646 if (r) {
647 radeon_bo_unreserve(bo);
648 radeon_bo_unref(&bo);
649 return r;
650 }
651
652 /* stitch together an UVD destroy msg */
653 msg[0] = 0x00000de4;
654 msg[1] = 0x00000002;
655 msg[2] = handle;
656 msg[3] = 0x00000000;
657 for (i = 4; i < 1024; ++i)
658 msg[i] = 0x0;
659
660 radeon_bo_kunmap(bo);
661 radeon_bo_unreserve(bo);
662
663 return radeon_uvd_send_msg(rdev, ring, bo, fence);
664}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index d4d9be17cfb9..a47e7b903cbc 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -68,6 +68,105 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
68 return reference_clock; 68 return reference_clock;
69} 69}
70 70
71int rv770_uvd_resume(struct radeon_device *rdev)
72{
73 uint64_t addr;
74 uint32_t chip_id, size;
75 int r;
76
77 r = radeon_uvd_resume(rdev);
78 if (r)
79 return r;
80
81 /* programm the VCPU memory controller bits 0-27 */
82 addr = rdev->uvd.gpu_addr >> 3;
83 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
84 WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
85 WREG32(UVD_VCPU_CACHE_SIZE0, size);
86
87 addr += size;
88 size = RADEON_UVD_STACK_SIZE >> 3;
89 WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
90 WREG32(UVD_VCPU_CACHE_SIZE1, size);
91
92 addr += size;
93 size = RADEON_UVD_HEAP_SIZE >> 3;
94 WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
95 WREG32(UVD_VCPU_CACHE_SIZE2, size);
96
97 /* bits 28-31 */
98 addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
99 WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
100
101 /* bits 32-39 */
102 addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
103 WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
104
105 /* tell firmware which hardware it is running on */
106 switch (rdev->family) {
107 default:
108 return -EINVAL;
109 case CHIP_RV710:
110 chip_id = 0x01000005;
111 break;
112 case CHIP_RV730:
113 chip_id = 0x01000006;
114 break;
115 case CHIP_RV740:
116 chip_id = 0x01000007;
117 break;
118 case CHIP_CYPRESS:
119 case CHIP_HEMLOCK:
120 chip_id = 0x01000008;
121 break;
122 case CHIP_JUNIPER:
123 chip_id = 0x01000009;
124 break;
125 case CHIP_REDWOOD:
126 chip_id = 0x0100000a;
127 break;
128 case CHIP_CEDAR:
129 chip_id = 0x0100000b;
130 break;
131 case CHIP_SUMO:
132 chip_id = 0x0100000c;
133 break;
134 case CHIP_SUMO2:
135 chip_id = 0x0100000d;
136 break;
137 case CHIP_PALM:
138 chip_id = 0x0100000e;
139 break;
140 case CHIP_CAYMAN:
141 chip_id = 0x0100000f;
142 break;
143 case CHIP_BARTS:
144 chip_id = 0x01000010;
145 break;
146 case CHIP_TURKS:
147 chip_id = 0x01000011;
148 break;
149 case CHIP_CAICOS:
150 chip_id = 0x01000012;
151 break;
152 case CHIP_TAHITI:
153 chip_id = 0x01000014;
154 break;
155 case CHIP_VERDE:
156 chip_id = 0x01000015;
157 break;
158 case CHIP_PITCAIRN:
159 chip_id = 0x01000016;
160 break;
161 case CHIP_ARUBA:
162 chip_id = 0x01000017;
163 break;
164 }
165 WREG32(UVD_VCPU_CHIP_ID, chip_id);
166
167 return 0;
168}
169
71u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 170u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
72{ 171{
73 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 172 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
@@ -1040,6 +1139,17 @@ static int rv770_startup(struct radeon_device *rdev)
1040 return r; 1139 return r;
1041 } 1140 }
1042 1141
1142 r = rv770_uvd_resume(rdev);
1143 if (!r) {
1144 r = radeon_fence_driver_start_ring(rdev,
1145 R600_RING_TYPE_UVD_INDEX);
1146 if (r)
1147 dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
1148 }
1149
1150 if (r)
1151 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
1152
1043 /* Enable IRQ */ 1153 /* Enable IRQ */
1044 r = r600_irq_init(rdev); 1154 r = r600_irq_init(rdev);
1045 if (r) { 1155 if (r) {
@@ -1074,6 +1184,19 @@ static int rv770_startup(struct radeon_device *rdev)
1074 if (r) 1184 if (r)
1075 return r; 1185 return r;
1076 1186
1187 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
1188 if (ring->ring_size) {
1189 r = radeon_ring_init(rdev, ring, ring->ring_size,
1190 R600_WB_UVD_RPTR_OFFSET,
1191 UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
1192 0, 0xfffff, RADEON_CP_PACKET2);
1193 if (!r)
1194 r = r600_uvd_init(rdev);
1195
1196 if (r)
1197 DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
1198 }
1199
1077 r = radeon_ib_pool_init(rdev); 1200 r = radeon_ib_pool_init(rdev);
1078 if (r) { 1201 if (r) {
1079 dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 1202 dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -1115,6 +1238,7 @@ int rv770_resume(struct radeon_device *rdev)
1115int rv770_suspend(struct radeon_device *rdev) 1238int rv770_suspend(struct radeon_device *rdev)
1116{ 1239{
1117 r600_audio_fini(rdev); 1240 r600_audio_fini(rdev);
1241 radeon_uvd_suspend(rdev);
1118 r700_cp_stop(rdev); 1242 r700_cp_stop(rdev);
1119 r600_dma_stop(rdev); 1243 r600_dma_stop(rdev);
1120 r600_irq_suspend(rdev); 1244 r600_irq_suspend(rdev);
@@ -1190,6 +1314,13 @@ int rv770_init(struct radeon_device *rdev)
1190 rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; 1314 rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
1191 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); 1315 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
1192 1316
1317 r = radeon_uvd_init(rdev);
1318 if (!r) {
1319 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
1320 r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
1321 4096);
1322 }
1323
1193 rdev->ih.ring_obj = NULL; 1324 rdev->ih.ring_obj = NULL;
1194 r600_ih_ring_init(rdev, 64 * 1024); 1325 r600_ih_ring_init(rdev, 64 * 1024);
1195 1326
@@ -1224,6 +1355,7 @@ void rv770_fini(struct radeon_device *rdev)
1224 radeon_ib_pool_fini(rdev); 1355 radeon_ib_pool_fini(rdev);
1225 radeon_irq_kms_fini(rdev); 1356 radeon_irq_kms_fini(rdev);
1226 rv770_pcie_gart_fini(rdev); 1357 rv770_pcie_gart_fini(rdev);
1358 radeon_uvd_fini(rdev);
1227 r600_vram_scratch_fini(rdev); 1359 r600_vram_scratch_fini(rdev);
1228 radeon_gem_fini(rdev); 1360 radeon_gem_fini(rdev);
1229 radeon_fence_driver_fini(rdev); 1361 radeon_fence_driver_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index c55f950a4af7..da158b541720 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -671,4 +671,18 @@
671# define TARGET_LINK_SPEED_MASK (0xf << 0) 671# define TARGET_LINK_SPEED_MASK (0xf << 0)
672# define SELECTABLE_DEEMPHASIS (1 << 6) 672# define SELECTABLE_DEEMPHASIS (1 << 6)
673 673
674/* UVD */
675#define UVD_LMI_EXT40_ADDR 0xf498
676#define UVD_VCPU_CHIP_ID 0xf4d4
677#define UVD_VCPU_CACHE_OFFSET0 0xf4d8
678#define UVD_VCPU_CACHE_SIZE0 0xf4dc
679#define UVD_VCPU_CACHE_OFFSET1 0xf4e0
680#define UVD_VCPU_CACHE_SIZE1 0xf4e4
681#define UVD_VCPU_CACHE_OFFSET2 0xf4e8
682#define UVD_VCPU_CACHE_SIZE2 0xf4ec
683#define UVD_LMI_ADDR_EXT 0xf594
684
685#define UVD_RBC_RB_RPTR 0xf690
686#define UVD_RBC_RB_WPTR 0xf694
687
674#endif 688#endif
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index ace45da91434..3e9782dc35bf 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -4333,6 +4333,16 @@ static int si_startup(struct radeon_device *rdev)
4333 return r; 4333 return r;
4334 } 4334 }
4335 4335
4336 r = rv770_uvd_resume(rdev);
4337 if (!r) {
4338 r = radeon_fence_driver_start_ring(rdev,
4339 R600_RING_TYPE_UVD_INDEX);
4340 if (r)
4341 dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
4342 }
4343 if (r)
4344 rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
4345
4336 /* Enable IRQ */ 4346 /* Enable IRQ */
4337 r = si_irq_init(rdev); 4347 r = si_irq_init(rdev);
4338 if (r) { 4348 if (r) {
@@ -4390,6 +4400,18 @@ static int si_startup(struct radeon_device *rdev)
4390 if (r) 4400 if (r)
4391 return r; 4401 return r;
4392 4402
4403 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
4404 if (ring->ring_size) {
4405 r = radeon_ring_init(rdev, ring, ring->ring_size,
4406 R600_WB_UVD_RPTR_OFFSET,
4407 UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
4408 0, 0xfffff, RADEON_CP_PACKET2);
4409 if (!r)
4410 r = r600_uvd_init(rdev);
4411 if (r)
4412 DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
4413 }
4414
4393 r = radeon_ib_pool_init(rdev); 4415 r = radeon_ib_pool_init(rdev);
4394 if (r) { 4416 if (r) {
4395 dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 4417 dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -4433,6 +4455,8 @@ int si_suspend(struct radeon_device *rdev)
4433 radeon_vm_manager_fini(rdev); 4455 radeon_vm_manager_fini(rdev);
4434 si_cp_enable(rdev, false); 4456 si_cp_enable(rdev, false);
4435 cayman_dma_stop(rdev); 4457 cayman_dma_stop(rdev);
4458 r600_uvd_rbc_stop(rdev);
4459 radeon_uvd_suspend(rdev);
4436 si_irq_suspend(rdev); 4460 si_irq_suspend(rdev);
4437 radeon_wb_disable(rdev); 4461 radeon_wb_disable(rdev);
4438 si_pcie_gart_disable(rdev); 4462 si_pcie_gart_disable(rdev);
@@ -4518,6 +4542,13 @@ int si_init(struct radeon_device *rdev)
4518 ring->ring_obj = NULL; 4542 ring->ring_obj = NULL;
4519 r600_ring_init(rdev, ring, 64 * 1024); 4543 r600_ring_init(rdev, ring, 64 * 1024);
4520 4544
4545 r = radeon_uvd_init(rdev);
4546 if (!r) {
4547 ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
4548 ring->ring_obj = NULL;
4549 r600_ring_init(rdev, ring, 4096);
4550 }
4551
4521 rdev->ih.ring_obj = NULL; 4552 rdev->ih.ring_obj = NULL;
4522 r600_ih_ring_init(rdev, 64 * 1024); 4553 r600_ih_ring_init(rdev, 64 * 1024);
4523 4554
@@ -4566,6 +4597,7 @@ void si_fini(struct radeon_device *rdev)
4566 radeon_vm_manager_fini(rdev); 4597 radeon_vm_manager_fini(rdev);
4567 radeon_ib_pool_fini(rdev); 4598 radeon_ib_pool_fini(rdev);
4568 radeon_irq_kms_fini(rdev); 4599 radeon_irq_kms_fini(rdev);
4600 radeon_uvd_fini(rdev);
4569 si_pcie_gart_fini(rdev); 4601 si_pcie_gart_fini(rdev);
4570 r600_vram_scratch_fini(rdev); 4602 r600_vram_scratch_fini(rdev);
4571 radeon_gem_fini(rdev); 4603 radeon_gem_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index f84cff0aafcc..1fb8ee2c45dc 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -800,6 +800,12 @@
800# define THREAD_TRACE_FINISH (55 << 0) 800# define THREAD_TRACE_FINISH (55 << 0)
801 801
802/* 802/*
803 * UVD
804 */
805#define UVD_RBC_RB_RPTR 0xF690
806#define UVD_RBC_RB_WPTR 0xF694
807
808/*
803 * PM4 809 * PM4
804 */ 810 */
805#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \ 811#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \