From: Christian K?nig <christian.koe...@amd.com>

Our different hardware blocks are actually completely
separated, so it doesn't make much sense any more to
structure the code by pure chipset generations.

Signed-off-by: Christian K?nig <christian.koenig at amd.com>
---
 drivers/gpu/drm/radeon/Makefile      |   12 +-
 drivers/gpu/drm/radeon/cik.c         |    6 +-
 drivers/gpu/drm/radeon/evergreen.c   |    6 +-
 drivers/gpu/drm/radeon/ni.c          |   23 +-
 drivers/gpu/drm/radeon/r600.c        |  322 ---------------------------
 drivers/gpu/drm/radeon/radeon_asic.c |   32 +--
 drivers/gpu/drm/radeon/radeon_asic.h |   54 +++--
 drivers/gpu/drm/radeon/rv770.c       |  102 +--------
 drivers/gpu/drm/radeon/rv770d.h      |   16 ++
 drivers/gpu/drm/radeon/si.c          |    6 +-
 drivers/gpu/drm/radeon/uvd_v1_0.c    |  401 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/uvd_v2_2.c    |  165 ++++++++++++++
 drivers/gpu/drm/radeon/uvd_v3_1.c    |   55 +++++
 drivers/gpu/drm/radeon/uvd_v4_2.c    |   73 +++++++
 14 files changed, 783 insertions(+), 490 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/uvd_v1_0.c
 create mode 100644 drivers/gpu/drm/radeon/uvd_v2_2.c
 create mode 100644 drivers/gpu/drm/radeon/uvd_v3_1.c
 create mode 100644 drivers/gpu/drm/radeon/uvd_v4_2.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index c3df52c..a3134ec 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -76,11 +76,19 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
        evergreen.o evergreen_cs.o evergreen_blit_shaders.o 
evergreen_blit_kms.o \
        evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
        atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
-       si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
-       r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
+       si_blit_shaders.o radeon_prime.o cik.o cik_blit_shaders.o r600_dpm.o \
+       rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
        rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o 
\
        trinity_smc.o ni_dpm.o si_smc.o si_dpm.o

+# add UVD block
+radeon-y += \
+       radeon_uvd.o \
+       uvd_v1_0.o \
+       uvd_v2_2.o \
+       uvd_v3_1.o \
+       uvd_v4_2.o
+
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
 radeon-$(CONFIG_ACPI) += radeon_acpi.o
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index d3d3940..945608f 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -6019,7 +6019,7 @@ static int cik_startup(struct radeon_device *rdev)
                return r;
        }

-       r = cik_uvd_resume(rdev);
+       r = uvd_v4_2_resume(rdev);
        if (!r) {
                r = radeon_fence_driver_start_ring(rdev,
                                                   R600_RING_TYPE_UVD_INDEX);
@@ -6107,7 +6107,7 @@ static int cik_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = uvd_v1_0_init(rdev);
                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
        }
@@ -6172,7 +6172,7 @@ int cik_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        cik_cp_enable(rdev, false);
        cik_sdma_enable(rdev, false);
-       r600_uvd_rbc_stop(rdev);
+       uvd_v1_0_rbc_stop(rdev);
        radeon_uvd_suspend(rdev);
        cik_irq_suspend(rdev);
        radeon_wb_disable(rdev);
diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index f02bb9f..52e037c 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -5173,7 +5173,7 @@ static int evergreen_startup(struct radeon_device *rdev)
                return r;
        }

-       r = rv770_uvd_resume(rdev);
+       r = uvd_v2_2_resume(rdev);
        if (!r) {
                r = radeon_fence_driver_start_ring(rdev,
                                                   R600_RING_TYPE_UVD_INDEX);
@@ -5229,7 +5229,7 @@ static int evergreen_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = uvd_v1_0_init(rdev);

                if (r)
                        DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
@@ -5287,7 +5287,7 @@ int evergreen_suspend(struct radeon_device *rdev)
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
        r600_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
+       uvd_v1_0_rbc_stop(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
        evergreen_pcie_gart_disable(rdev);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 6274723..73302dc 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1381,23 +1381,6 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, 
struct radeon_ib *ib)
        radeon_ring_write(ring, 10); /* poll interval */
 }

-void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
-                              struct radeon_ring *ring,
-                              struct radeon_semaphore *semaphore,
-                              bool emit_wait)
-{
-       uint64_t addr = semaphore->gpu_addr;
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
-       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
-       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
-       radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
-}
-
 static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
 {
        if (enable)
@@ -2154,7 +2137,7 @@ static int cayman_startup(struct radeon_device *rdev)
                return r;
        }

-       r = rv770_uvd_resume(rdev);
+       r = uvd_v2_2_resume(rdev);
        if (!r) {
                r = radeon_fence_driver_start_ring(rdev,
                                                   R600_RING_TYPE_UVD_INDEX);
@@ -2242,7 +2225,7 @@ static int cayman_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = uvd_v1_0_init(rdev);
                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
        }
@@ -2296,7 +2279,7 @@ int cayman_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        cayman_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
+       uvd_v1_0_rbc_stop(rdev);
        radeon_uvd_suspend(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index e1f4382..ce7b05c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2671,208 +2671,6 @@ void r600_dma_fini(struct radeon_device *rdev)
 }

 /*
- * UVD
- */
-
-uint32_t r600_uvd_get_rptr(struct radeon_device *rdev,
-                          struct radeon_ring *ring)
-{
-       return RREG32(UVD_RBC_RB_RPTR);
-}
-
-uint32_t r600_uvd_get_wptr(struct radeon_device *rdev,
-                          struct radeon_ring *ring)
-{
-       return RREG32(UVD_RBC_RB_WPTR);
-}
-
-void r600_uvd_set_wptr(struct radeon_device *rdev,
-                      struct radeon_ring *ring)
-{
-       WREG32(UVD_RBC_RB_WPTR, ring->wptr);
-}
-
-int r600_uvd_rbc_start(struct radeon_device *rdev)
-{
-       struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-       uint32_t rb_bufsz, tmp;
-       int r;
-
-       /* force RBC into idle state */
-       WREG32(UVD_RBC_RB_CNTL, 0x11010101);
-
-       /* Set the write pointer delay */
-       WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
-
-       /* programm the 4GB memory segment for rptr and ring buffer */
-       WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
-                                  (0x7 << 16) | (0x1 << 31));
-
-       /* Initialize the ring buffer's read and write pointers */
-       WREG32(UVD_RBC_RB_RPTR, 0x0);
-
-       ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR);
-       WREG32(UVD_RBC_RB_WPTR, ring->wptr);
-
-       /* set the ring address */
-       WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
-
-       /* Set ring buffer size */
-       rb_bufsz = drm_order(ring->ring_size);
-       rb_bufsz = (0x1 << 8) | rb_bufsz;
-       WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
-
-       ring->ready = true;
-       r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
-       if (r) {
-               ring->ready = false;
-               return r;
-       }
-
-       r = radeon_ring_lock(rdev, ring, 10);
-       if (r) {
-               DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
-               return r;
-       }
-
-       tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
-       radeon_ring_write(ring, tmp);
-       radeon_ring_write(ring, 0xFFFFF);
-
-       tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
-       radeon_ring_write(ring, tmp);
-       radeon_ring_write(ring, 0xFFFFF);
-
-       tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
-       radeon_ring_write(ring, tmp);
-       radeon_ring_write(ring, 0xFFFFF);
-
-       /* Clear timeout status bits */
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
-       radeon_ring_write(ring, 0x8);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
-       radeon_ring_write(ring, 3);
-
-       radeon_ring_unlock_commit(rdev, ring);
-
-       return 0;
-}
-
-void r600_uvd_rbc_stop(struct radeon_device *rdev)
-{
-       struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-
-       /* force RBC into idle state */
-       WREG32(UVD_RBC_RB_CNTL, 0x11010101);
-       ring->ready = false;
-}
-
-int r600_uvd_init(struct radeon_device *rdev)
-{
-       int i, j, r;
-       /* disable byte swapping */
-       u32 lmi_swap_cntl = 0;
-       u32 mp_swap_cntl = 0;
-
-       /* raise clocks while booting up the VCPU */
-       radeon_set_uvd_clocks(rdev, 53300, 40000);
-
-       /* disable clock gating */
-       WREG32(UVD_CGC_GATE, 0);
-
-       /* disable interupt */
-       WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
-
-       /* put LMI, VCPU, RBC etc... into reset */
-       WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
-              LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
-              CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
-       mdelay(5);
-
-       /* take UVD block out of reset */
-       WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
-       mdelay(5);
-
-       /* initialize UVD memory controller */
-       WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
-                            (1 << 21) | (1 << 9) | (1 << 20));
-
-#ifdef __BIG_ENDIAN
-       /* swap (8 in 32) RB and IB */
-       lmi_swap_cntl = 0xa;
-       mp_swap_cntl = 0;
-#endif
-       WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl);
-       WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl);
-
-       WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
-       WREG32(UVD_MPC_SET_MUXA1, 0x0);
-       WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
-       WREG32(UVD_MPC_SET_MUXB1, 0x0);
-       WREG32(UVD_MPC_SET_ALU, 0);
-       WREG32(UVD_MPC_SET_MUX, 0x88);
-
-       /* Stall UMC */
-       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
-       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
-
-       /* take all subblocks out of reset, except VCPU */
-       WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
-       mdelay(5);
-
-       /* enable VCPU clock */
-       WREG32(UVD_VCPU_CNTL,  1 << 9);
-
-       /* enable UMC */
-       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
-
-       /* boot up the VCPU */
-       WREG32(UVD_SOFT_RESET, 0);
-       mdelay(10);
-
-       WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
-
-       for (i = 0; i < 10; ++i) {
-               uint32_t status;
-               for (j = 0; j < 100; ++j) {
-                       status = RREG32(UVD_STATUS);
-                       if (status & 2)
-                               break;
-                       mdelay(10);
-               }
-               r = 0;
-               if (status & 2)
-                       break;
-
-               DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
-               WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
-               mdelay(10);
-               WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
-               mdelay(10);
-               r = -1;
-       }
-
-       if (r) {
-               DRM_ERROR("UVD not responding, giving up!!!\n");
-               radeon_set_uvd_clocks(rdev, 0, 0);
-               return r;
-       }
-
-       /* enable interupt */
-       WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
-
-       r = r600_uvd_rbc_start(rdev);
-       if (!r)
-               DRM_INFO("UVD initialized successfully.\n");
-
-       /* lower clocks again */
-       radeon_set_uvd_clocks(rdev, 0, 0);
-
-       return r;
-}
-
-/*
  * GPU scratch registers helpers function.
  */
 void r600_scratch_init(struct radeon_device *rdev)
@@ -2981,40 +2779,6 @@ int r600_dma_ring_test(struct radeon_device *rdev,
        return r;
 }

-int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-       uint32_t tmp = 0;
-       unsigned i;
-       int r;
-
-       WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
-       r = radeon_ring_lock(rdev, ring, 3);
-       if (r) {
-               DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
-                         ring->idx, r);
-               return r;
-       }
-       radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
-       radeon_ring_write(ring, 0xDEADBEEF);
-       radeon_ring_unlock_commit(rdev, ring);
-       for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = RREG32(UVD_CONTEXT_ID);
-               if (tmp == 0xDEADBEEF)
-                       break;
-               DRM_UDELAY(1);
-       }
-
-       if (i < rdev->usec_timeout) {
-               DRM_INFO("ring test on %d succeeded in %d usecs\n",
-                        ring->idx, i);
-       } else {
-               DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
-                         ring->idx, tmp);
-               r = -EINVAL;
-       }
-       return r;
-}
-
 /*
  * CP fences/semaphores
  */
@@ -3066,30 +2830,6 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        }
 }

-void r600_uvd_fence_emit(struct radeon_device *rdev,
-                        struct radeon_fence *fence)
-{
-       struct radeon_ring *ring = &rdev->ring[fence->ring];
-       uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
-
-       radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
-       radeon_ring_write(ring, fence->seq);
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
-       radeon_ring_write(ring, addr & 0xffffffff);
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
-       radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
-       radeon_ring_write(ring, 0);
-
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
-       radeon_ring_write(ring, 2);
-       return;
-}
-
 void r600_semaphore_ring_emit(struct radeon_device *rdev,
                              struct radeon_ring *ring,
                              struct radeon_semaphore *semaphore,
@@ -3159,23 +2899,6 @@ void r600_dma_semaphore_ring_emit(struct radeon_device 
*rdev,
        radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
 }

-void r600_uvd_semaphore_emit(struct radeon_device *rdev,
-                            struct radeon_ring *ring,
-                            struct radeon_semaphore *semaphore,
-                            bool emit_wait)
-{
-       uint64_t addr = semaphore->gpu_addr;
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
-       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
-       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
-       radeon_ring_write(ring, emit_wait ? 1 : 0);
-}
-
 int r600_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset,
                   uint64_t dst_offset,
@@ -3581,16 +3304,6 @@ void r600_ring_ib_execute(struct radeon_device *rdev, 
struct radeon_ib *ib)
        radeon_ring_write(ring, ib->length_dw);
 }

-void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
-{
-       struct radeon_ring *ring = &rdev->ring[ib->ring];
-
-       radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
-       radeon_ring_write(ring, ib->gpu_addr);
-       radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
-       radeon_ring_write(ring, ib->length_dw);
-}
-
 int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        struct radeon_ib ib;
@@ -3708,41 +3421,6 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct 
radeon_ring *ring)
        return r;
 }

-int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-       struct radeon_fence *fence = NULL;
-       int r;
-
-       r = radeon_set_uvd_clocks(rdev, 53300, 40000);
-       if (r) {
-               DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
-               return r;
-       }
-
-       r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
-       if (r) {
-               DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
-               goto error;
-       }
-
-       r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
-       if (r) {
-               DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
-               goto error;
-       }
-
-       r = radeon_fence_wait(fence, false);
-       if (r) {
-               DRM_ERROR("radeon: fence wait failed (%d).\n", r);
-               goto error;
-       }
-       DRM_INFO("ib test on ring %d succeeded\n",  ring->idx);
-error:
-       radeon_fence_unref(&fence);
-       radeon_set_uvd_clocks(rdev, 0, 0);
-       return r;
-}
-
 /**
  * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine
  *
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index 300a502..566fb2a 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1148,16 +1148,16 @@ static struct radeon_asic rs780_asic = {
 };

 static struct radeon_asic_ring rv770_uvd_ring = {
-       .ib_execute = &r600_uvd_ib_execute,
-       .emit_fence = &r600_uvd_fence_emit,
-       .emit_semaphore = &r600_uvd_semaphore_emit,
+       .ib_execute = &uvd_v1_0_ib_execute,
+       .emit_fence = &uvd_v2_2_fence_emit,
+       .emit_semaphore = &uvd_v1_0_semaphore_emit,
        .cs_parse = &radeon_uvd_cs_parse,
-       .ring_test = &r600_uvd_ring_test,
-       .ib_test = &r600_uvd_ib_test,
+       .ring_test = &uvd_v1_0_ring_test,
+       .ib_test = &uvd_v1_0_ib_test,
        .is_lockup = &radeon_ring_test_lockup,
-       .get_rptr = &r600_uvd_get_rptr,
-       .get_wptr = &r600_uvd_get_wptr,
-       .set_wptr = &r600_uvd_set_wptr,
+       .get_rptr = &uvd_v1_0_get_rptr,
+       .get_wptr = &uvd_v1_0_get_wptr,
+       .set_wptr = &uvd_v1_0_set_wptr,
 };

 static struct radeon_asic rv770_asic = {
@@ -1577,16 +1577,16 @@ static struct radeon_asic_ring cayman_dma_ring = {
 };

 static struct radeon_asic_ring cayman_uvd_ring = {
-       .ib_execute = &r600_uvd_ib_execute,
-       .emit_fence = &r600_uvd_fence_emit,
-       .emit_semaphore = &cayman_uvd_semaphore_emit,
+       .ib_execute = &uvd_v1_0_ib_execute,
+       .emit_fence = &uvd_v2_2_fence_emit,
+       .emit_semaphore = &uvd_v3_1_semaphore_emit,
        .cs_parse = &radeon_uvd_cs_parse,
-       .ring_test = &r600_uvd_ring_test,
-       .ib_test = &r600_uvd_ib_test,
+       .ring_test = &uvd_v1_0_ring_test,
+       .ib_test = &uvd_v1_0_ib_test,
        .is_lockup = &radeon_ring_test_lockup,
-       .get_rptr = &r600_uvd_get_rptr,
-       .get_wptr = &r600_uvd_get_wptr,
-       .set_wptr = &r600_uvd_set_wptr,
+       .get_rptr = &uvd_v1_0_get_rptr,
+       .get_wptr = &uvd_v1_0_get_wptr,
+       .set_wptr = &uvd_v1_0_set_wptr,
 };

 static struct radeon_asic cayman_asic = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index 8ae539ae..9c85e85 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -336,7 +336,6 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct 
radeon_ring *ring);
 void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
 int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
-int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
 int r600_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset, uint64_t dst_offset,
                   unsigned num_gpu_pages, struct radeon_fence **fence);
@@ -438,25 +437,6 @@ u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool 
low);
 void rs780_dpm_print_power_state(struct radeon_device *rdev,
                                 struct radeon_ps *ps);

-/* uvd */
-int r600_uvd_init(struct radeon_device *rdev);
-uint32_t r600_uvd_get_rptr(struct radeon_device *rdev,
-                           struct radeon_ring *ring);
-uint32_t r600_uvd_get_wptr(struct radeon_device *rdev,
-                           struct radeon_ring *ring);
-void r600_uvd_set_wptr(struct radeon_device *rdev,
-                       struct radeon_ring *ring);
-int r600_uvd_rbc_start(struct radeon_device *rdev);
-void r600_uvd_rbc_stop(struct radeon_device *rdev);
-int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
-void r600_uvd_fence_emit(struct radeon_device *rdev,
-                        struct radeon_fence *fence);
-void r600_uvd_semaphore_emit(struct radeon_device *rdev,
-                            struct radeon_ring *ring,
-                            struct radeon_semaphore *semaphore,
-                            bool emit_wait);
-void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-
 /*
  * rv770,rv730,rv710,rv740
  */
@@ -474,7 +454,6 @@ int rv770_copy_dma(struct radeon_device *rdev,
                  unsigned num_gpu_pages,
                   struct radeon_fence **fence);
 u32 rv770_get_xclk(struct radeon_device *rdev);
-int rv770_uvd_resume(struct radeon_device *rdev);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_get_temp(struct radeon_device *rdev);
 /* rv7xx pm */
@@ -704,7 +683,6 @@ u32 cik_get_xclk(struct radeon_device *rdev);
 uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
 void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
-int cik_uvd_resume(struct radeon_device *rdev);
 void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
                              struct radeon_fence *fence);
 void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
@@ -756,4 +734,36 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
 void cik_compute_ring_set_wptr(struct radeon_device *rdev,
                               struct radeon_ring *ring);

+/* uvd v1.0 */
+uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
+                           struct radeon_ring *ring);
+uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
+                           struct radeon_ring *ring);
+void uvd_v1_0_set_wptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring);
+int uvd_v1_0_rbc_start(struct radeon_device *rdev);
+void uvd_v1_0_rbc_stop(struct radeon_device *rdev);
+int uvd_v1_0_init(struct radeon_device *rdev);
+int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
+int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
+void uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait);
+void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
+
+/* uvd v2.2 */
+int uvd_v2_2_resume(struct radeon_device *rdev);
+void uvd_v2_2_fence_emit(struct radeon_device *rdev,
+                        struct radeon_fence *fence);
+
+/* uvd v3.1 */
+void uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait);
+
+/* uvd v4.2 */
+int uvd_v4_2_resume(struct radeon_device *rdev);
+
 #endif
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index b4654ac..29775a7 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -801,103 +801,6 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
        return reference_clock;
 }

-int rv770_uvd_resume(struct radeon_device *rdev)
-{
-       uint64_t addr;
-       uint32_t chip_id, size;
-       int r;
-
-       r = radeon_uvd_resume(rdev);
-       if (r)
-               return r;
-
-       /* programm the VCPU memory controller bits 0-27 */
-       addr = rdev->uvd.gpu_addr >> 3;
-       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
-       WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
-       WREG32(UVD_VCPU_CACHE_SIZE0, size);
-
-       addr += size;
-       size = RADEON_UVD_STACK_SIZE >> 3;
-       WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
-       WREG32(UVD_VCPU_CACHE_SIZE1, size);
-
-       addr += size;
-       size = RADEON_UVD_HEAP_SIZE >> 3;
-       WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
-       WREG32(UVD_VCPU_CACHE_SIZE2, size);
-
-       /* bits 28-31 */
-       addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
-       WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
-
-       /* bits 32-39 */
-       addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
-       WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
-
-       /* tell firmware which hardware it is running on */
-       switch (rdev->family) {
-       default:
-               return -EINVAL;
-       case CHIP_RV710:
-               chip_id = 0x01000005;
-               break;
-       case CHIP_RV730:
-               chip_id = 0x01000006;
-               break;
-       case CHIP_RV740:
-               chip_id = 0x01000007;
-               break;
-       case CHIP_CYPRESS:
-       case CHIP_HEMLOCK:
-               chip_id = 0x01000008;
-               break;
-       case CHIP_JUNIPER:
-               chip_id = 0x01000009;
-               break;
-       case CHIP_REDWOOD:
-               chip_id = 0x0100000a;
-               break;
-       case CHIP_CEDAR:
-               chip_id = 0x0100000b;
-               break;
-       case CHIP_SUMO:
-       case CHIP_SUMO2:
-               chip_id = 0x0100000c;
-               break;
-       case CHIP_PALM:
-               chip_id = 0x0100000e;
-               break;
-       case CHIP_CAYMAN:
-               chip_id = 0x0100000f;
-               break;
-       case CHIP_BARTS:
-               chip_id = 0x01000010;
-               break;
-       case CHIP_TURKS:
-               chip_id = 0x01000011;
-               break;
-       case CHIP_CAICOS:
-               chip_id = 0x01000012;
-               break;
-       case CHIP_TAHITI:
-               chip_id = 0x01000014;
-               break;
-       case CHIP_VERDE:
-               chip_id = 0x01000015;
-               break;
-       case CHIP_PITCAIRN:
-               chip_id = 0x01000016;
-               break;
-       case CHIP_ARUBA:
-               chip_id = 0x01000017;
-               break;
-       }
-       WREG32(UVD_VCPU_CHIP_ID, chip_id);
-
-       return 0;
-}
-
 u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
@@ -1875,7 +1778,7 @@ static int rv770_startup(struct radeon_device *rdev)
                return r;
        }

-       r = rv770_uvd_resume(rdev);
+       r = uvd_v2_2_resume(rdev);
        if (!r) {
                r = radeon_fence_driver_start_ring(rdev,
                                                   R600_RING_TYPE_UVD_INDEX);
@@ -1932,7 +1835,7 @@ static int rv770_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = uvd_v1_0_init(rdev);

                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
@@ -1984,6 +1887,7 @@ int rv770_suspend(struct radeon_device *rdev)
        r600_audio_fini(rdev);
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
+       uvd_v1_0_rbc_stop(rdev);
        r600_dma_stop(rdev);
        r600_irq_suspend(rdev);
        radeon_wb_disable(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 6bef2b7..9fe60e5 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -971,7 +971,21 @@
 #       define TARGET_LINK_SPEED_MASK                     (0xf << 0)
 #       define SELECTABLE_DEEMPHASIS                      (1 << 6)

+/*
+ * PM4
+ */
+#define PACKET0(reg, n)        ((RADEON_PACKET_TYPE0 << 30) |                  
\
+                        (((reg) >> 2) & 0xFFFF) |                      \
+                        ((n) & 0x3FFF) << 16)
+#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) |                  \
+                        (((op) & 0xFF) << 8) |                         \
+                        ((n) & 0x3FFF) << 16)
+
 /* UVD */
+#define UVD_GPCOM_VCPU_CMD                             0xef0c
+#define UVD_GPCOM_VCPU_DATA0                           0xef10
+#define UVD_GPCOM_VCPU_DATA1                           0xef14
+
 #define UVD_LMI_EXT40_ADDR                             0xf498
 #define UVD_VCPU_CHIP_ID                               0xf4d4
 #define UVD_VCPU_CACHE_OFFSET0                         0xf4d8
@@ -985,4 +999,6 @@
 #define UVD_RBC_RB_RPTR                                        0xf690
 #define UVD_RBC_RB_WPTR                                        0xf694

+#define UVD_CONTEXT_ID                                 0xf6f4
+
 #endif
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 3957964..48817fd 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -6233,7 +6233,7 @@ static int si_startup(struct radeon_device *rdev)
        }

        if (rdev->has_uvd) {
-               r = rv770_uvd_resume(rdev);
+               r = uvd_v2_2_resume(rdev);
                if (!r) {
                        r = radeon_fence_driver_start_ring(rdev,
                                                           
R600_RING_TYPE_UVD_INDEX);
@@ -6314,7 +6314,7 @@ static int si_startup(struct radeon_device *rdev)
                                             UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                             RADEON_CP_PACKET2);
                        if (!r)
-                               r = r600_uvd_init(rdev);
+                               r = uvd_v1_0_init(rdev);
                        if (r)
                                DRM_ERROR("radeon: failed initializing UVD 
(%d).\n", r);
                }
@@ -6367,7 +6367,7 @@ int si_suspend(struct radeon_device *rdev)
        si_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        if (rdev->has_uvd) {
-               r600_uvd_rbc_stop(rdev);
+               uvd_v1_0_rbc_stop(rdev);
                radeon_uvd_suspend(rdev);
        }
        si_irq_suspend(rdev);
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c 
b/drivers/gpu/drm/radeon/uvd_v1_0.c
new file mode 100644
index 0000000..270f5e6
--- /dev/null
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian K?nig <christian.koenig at amd.com>
+ */
+
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "r600d.h"
+
+/**
+ * uvd_v1_0_get_rptr - get read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Returns the current hardware read pointer
+ */
+uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       return RREG32(UVD_RBC_RB_RPTR);
+}
+
+/**
+ * uvd_v1_0_get_wptr - get write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Returns the current hardware write pointer
+ */
+uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       return RREG32(UVD_RBC_RB_WPTR);
+}
+
+/**
+ * uvd_v1_0_set_wptr - set write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Commits the write pointer to the hardware
+ */
+void uvd_v1_0_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       WREG32(UVD_RBC_RB_WPTR, ring->wptr);
+}
+
+/**
+ * uvd_v1_0_rbc_start - start ring buffer controller
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Setup and start the UVD ring buffer controller
+ */
+int uvd_v1_0_rbc_start(struct radeon_device *rdev)
+{
+       struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+       uint32_t rb_bufsz, tmp;
+       int r;
+
+       /* force RBC into idle state */
+       WREG32(UVD_RBC_RB_CNTL, 0x11010101);
+
+       /* Set the write pointer delay */
+       WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
+
+       /* programm the 4GB memory segment for rptr and ring buffer */
+       WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
+                                  (0x7 << 16) | (0x1 << 31));
+
+       /* Initialize the ring buffer's read and write pointers */
+       WREG32(UVD_RBC_RB_RPTR, 0x0);
+
+       ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR);
+       WREG32(UVD_RBC_RB_WPTR, ring->wptr);
+
+       /* set the ring address */
+       WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
+
+       /* Set ring buffer size */
+       rb_bufsz = drm_order(ring->ring_size);
+       rb_bufsz = (0x1 << 8) | rb_bufsz;
+       WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
+
+       ring->ready = true;
+       r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
+       if (r) {
+               ring->ready = false;
+               return r;
+       }
+
+       r = radeon_ring_lock(rdev, ring, 10);
+       if (r) {
+               DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
+               return r;
+       }
+
+       tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
+       radeon_ring_write(ring, tmp);
+       radeon_ring_write(ring, 0xFFFFF);
+
+       tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
+       radeon_ring_write(ring, tmp);
+       radeon_ring_write(ring, 0xFFFFF);
+
+       tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
+       radeon_ring_write(ring, tmp);
+       radeon_ring_write(ring, 0xFFFFF);
+
+       /* Clear timeout status bits */
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
+       radeon_ring_write(ring, 0x8);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
+       radeon_ring_write(ring, 3);
+
+       radeon_ring_unlock_commit(rdev, ring);
+
+       return 0;
+}
+
+/**
+ * uvd_v1_0_rbc_stop - stop ring buffer controller
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Stop the RBC, so it no longer processes commands
+ */
+void uvd_v1_0_rbc_stop(struct radeon_device *rdev)
+{
+       struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+
+       /* force RBC into idle state */
+       WREG32(UVD_RBC_RB_CNTL, 0x11010101);
+       ring->ready = false;
+}
+
+/**
+ * uvd_v1_0_init - low level hardware init
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the hardware and boot up the VCPU
+ */
+int uvd_v1_0_init(struct radeon_device *rdev)
+{
+       int i, j, r;
+       /* disable byte swapping */
+       u32 lmi_swap_cntl = 0;
+       u32 mp_swap_cntl = 0;
+
+       /* raise clocks while booting up the VCPU */
+       radeon_set_uvd_clocks(rdev, 53300, 40000);
+
+       /* disable clock gating */
+       WREG32(UVD_CGC_GATE, 0);
+
+       /* disable interupt */
+       WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
+
+       /* put LMI, VCPU, RBC etc... into reset */
+       WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
+              LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
+              CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
+       mdelay(5);
+
+       /* take UVD block out of reset */
+       WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
+       mdelay(5);
+
+       /* initialize UVD memory controller */
+       WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
+                            (1 << 21) | (1 << 9) | (1 << 20));
+
+#ifdef __BIG_ENDIAN
+       /* swap (8 in 32) RB and IB */
+       lmi_swap_cntl = 0xa;
+       mp_swap_cntl = 0;
+#endif
+       WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl);
+       WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl);
+
+       WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
+       WREG32(UVD_MPC_SET_MUXA1, 0x0);
+       WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
+       WREG32(UVD_MPC_SET_MUXB1, 0x0);
+       WREG32(UVD_MPC_SET_ALU, 0);
+       WREG32(UVD_MPC_SET_MUX, 0x88);
+
+       /* Stall UMC */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
+
+       /* take all subblocks out of reset, except VCPU */
+       WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
+       mdelay(5);
+
+       /* enable VCPU clock */
+       WREG32(UVD_VCPU_CNTL,  1 << 9);
+
+       /* enable UMC */
+       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
+
+       /* boot up the VCPU */
+       WREG32(UVD_SOFT_RESET, 0);
+       mdelay(10);
+
+       WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
+
+       for (i = 0; i < 10; ++i) {
+               uint32_t status;
+               for (j = 0; j < 100; ++j) {
+                       status = RREG32(UVD_STATUS);
+                       if (status & 2)
+                               break;
+                       mdelay(10);
+               }
+               r = 0;
+               if (status & 2)
+                       break;
+
+               DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
+               WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
+               mdelay(10);
+               WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
+               mdelay(10);
+               r = -1;
+       }
+
+       if (r) {
+               DRM_ERROR("UVD not responding, giving up!!!\n");
+               radeon_set_uvd_clocks(rdev, 0, 0);
+               return r;
+       }
+
+       /* enable interupt */
+       WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
+
+       r = uvd_v1_0_rbc_start(rdev);
+       if (!r)
+               DRM_INFO("UVD initialized successfully.\n");
+
+       /* lower clocks again */
+       radeon_set_uvd_clocks(rdev, 0, 0);
+
+       return r;
+}
+
+/**
+ * uvd_v1_0_ring_test - register write test
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Test if we can successfully write to the context register
+ */
+int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       uint32_t tmp = 0;
+       unsigned i;
+       int r;
+
+       WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
+       r = radeon_ring_lock(rdev, ring, 3);
+       if (r) {
+               DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
+                         ring->idx, r);
+               return r;
+       }
+       radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
+       radeon_ring_write(ring, 0xDEADBEEF);
+       radeon_ring_unlock_commit(rdev, ring);
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               tmp = RREG32(UVD_CONTEXT_ID);
+               if (tmp == 0xDEADBEEF)
+                       break;
+               DRM_UDELAY(1);
+       }
+
+       if (i < rdev->usec_timeout) {
+               DRM_INFO("ring test on %d succeeded in %d usecs\n",
+                        ring->idx, i);
+       } else {
+               DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
+                         ring->idx, tmp);
+               r = -EINVAL;
+       }
+       return r;
+}
+
+/**
+ * uvd_v1_0_semaphore_emit - emit semaphore command
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ * @semaphore: semaphore to emit commands for
+ * @emit_wait: true if we should emit a wait command
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+void uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait)
+{
+       uint64_t addr = semaphore->gpu_addr;
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
+       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
+       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+       radeon_ring_write(ring, emit_wait ? 1 : 0);
+}
+
+/**
+ * uvd_v1_0_ib_execute - execute indirect buffer
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to execute
+ *
+ * Write ring commands to execute the indirect buffer
+ */
+void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+       struct radeon_ring *ring = &rdev->ring[ib->ring];
+
+       radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
+       radeon_ring_write(ring, ib->gpu_addr);
+       radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
+       radeon_ring_write(ring, ib->length_dw);
+}
+
+/**
+ * uvd_v1_0_ib_test - test ib execution
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ *
+ * Test if we can successfully execute an IB
+ */
+int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       struct radeon_fence *fence = NULL;
+       int r;
+
+       r = radeon_set_uvd_clocks(rdev, 53300, 40000);
+       if (r) {
+               DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
+               return r;
+       }
+
+       r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
+       if (r) {
+               DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
+               goto error;
+       }
+
+       r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
+       if (r) {
+               DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
+               goto error;
+       }
+
+       r = radeon_fence_wait(fence, false);
+       if (r) {
+               DRM_ERROR("radeon: fence wait failed (%d).\n", r);
+               goto error;
+       }
+       DRM_INFO("ib test on ring %d succeeded\n",  ring->idx);
+error:
+       radeon_fence_unref(&fence);
+       radeon_set_uvd_clocks(rdev, 0, 0);
+       return r;
+}
diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c 
b/drivers/gpu/drm/radeon/uvd_v2_2.c
new file mode 100644
index 0000000..74c93ba
--- /dev/null
+++ b/drivers/gpu/drm/radeon/uvd_v2_2.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian K?nig <christian.koenig at amd.com>
+ */
+
+#include <linux/firmware.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "rv770d.h"
+
+/**
+ * uvd_v2_2_fence_emit - emit an fence & trap command
+ *
+ * @rdev: radeon_device pointer
+ * @fence: fence to emit
+ *
+ * Write a fence and a trap command to the ring.
+ */
+void uvd_v2_2_fence_emit(struct radeon_device *rdev,
+                        struct radeon_fence *fence)
+{
+       struct radeon_ring *ring = &rdev->ring[fence->ring];
+       uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
+
+       radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
+       radeon_ring_write(ring, fence->seq);
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
+       radeon_ring_write(ring, addr & 0xffffffff);
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
+       radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
+       radeon_ring_write(ring, 0);
+
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
+       radeon_ring_write(ring, 0);
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
+       radeon_ring_write(ring, 0);
+       radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
+       radeon_ring_write(ring, 2);
+       return;
+}
+
+/**
+ * uvd_v2_2_resume - memory controller programming
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Let the UVD memory controller know it's offsets
+ */
+int uvd_v2_2_resume(struct radeon_device *rdev)
+{
+       uint64_t addr;
+       uint32_t chip_id, size;
+       int r;
+
+       r = radeon_uvd_resume(rdev);
+       if (r)
+               return r;
+
+       /* programm the VCPU memory controller bits 0-27 */
+       addr = rdev->uvd.gpu_addr >> 3;
+       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE0, size);
+
+       addr += size;
+       size = RADEON_UVD_STACK_SIZE >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE1, size);
+
+       addr += size;
+       size = RADEON_UVD_HEAP_SIZE >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE2, size);
+
+       /* bits 28-31 */
+       addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
+       WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
+
+       /* bits 32-39 */
+       addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
+       WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
+
+       /* tell firmware which hardware it is running on */
+       switch (rdev->family) {
+       default:
+               return -EINVAL;
+       case CHIP_RV710:
+               chip_id = 0x01000005;
+               break;
+       case CHIP_RV730:
+               chip_id = 0x01000006;
+               break;
+       case CHIP_RV740:
+               chip_id = 0x01000007;
+               break;
+       case CHIP_CYPRESS:
+       case CHIP_HEMLOCK:
+               chip_id = 0x01000008;
+               break;
+       case CHIP_JUNIPER:
+               chip_id = 0x01000009;
+               break;
+       case CHIP_REDWOOD:
+               chip_id = 0x0100000a;
+               break;
+       case CHIP_CEDAR:
+               chip_id = 0x0100000b;
+               break;
+       case CHIP_SUMO:
+       case CHIP_SUMO2:
+               chip_id = 0x0100000c;
+               break;
+       case CHIP_PALM:
+               chip_id = 0x0100000e;
+               break;
+       case CHIP_CAYMAN:
+               chip_id = 0x0100000f;
+               break;
+       case CHIP_BARTS:
+               chip_id = 0x01000010;
+               break;
+       case CHIP_TURKS:
+               chip_id = 0x01000011;
+               break;
+       case CHIP_CAICOS:
+               chip_id = 0x01000012;
+               break;
+       case CHIP_TAHITI:
+               chip_id = 0x01000014;
+               break;
+       case CHIP_VERDE:
+               chip_id = 0x01000015;
+               break;
+       case CHIP_PITCAIRN:
+               chip_id = 0x01000016;
+               break;
+       case CHIP_ARUBA:
+               chip_id = 0x01000017;
+               break;
+       }
+       WREG32(UVD_VCPU_CHIP_ID, chip_id);
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/radeon/uvd_v3_1.c 
b/drivers/gpu/drm/radeon/uvd_v3_1.c
new file mode 100644
index 0000000..5b6fa1f
--- /dev/null
+++ b/drivers/gpu/drm/radeon/uvd_v3_1.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian K?nig <christian.koenig at amd.com>
+ */
+
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "nid.h"
+
+/**
+ * uvd_v3_1_semaphore_emit - emit semaphore command
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ * @semaphore: semaphore to emit commands for
+ * @emit_wait: true if we should emit a wait command
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+void uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait)
+{
+       uint64_t addr = semaphore->gpu_addr;
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
+       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
+       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+       radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
+}
diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c 
b/drivers/gpu/drm/radeon/uvd_v4_2.c
new file mode 100644
index 0000000..d7e4807
--- /dev/null
+++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian K?nig <christian.koenig at amd.com>
+ */
+
+#include <linux/firmware.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "cikd.h"
+
+/**
+ * uvd_v4_2_resume - memory controller programming
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Let the UVD memory controller know it's offsets
+ */
+int uvd_v4_2_resume(struct radeon_device *rdev)
+{
+       uint64_t addr;
+       uint32_t size;
+       int r;
+
+       r = radeon_uvd_resume(rdev);
+       if (r)
+               return r;
+
+       /* programm the VCPU memory controller bits 0-27 */
+       addr = rdev->uvd.gpu_addr >> 3;
+       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE0, size);
+
+       addr += size;
+       size = RADEON_UVD_STACK_SIZE >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE1, size);
+
+       addr += size;
+       size = RADEON_UVD_HEAP_SIZE >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE2, size);
+
+       /* bits 28-31 */
+       addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
+       WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
+
+       /* bits 32-39 */
+       addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
+       WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
+
+       return 0;
+}
-- 
1.7.9.5

Reply via email to