drm/radeon: restructure UVD code to handle UVD PG (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 6 Aug 2013 15:39:38 +0000 (11:39 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 30 Aug 2013 20:30:34 +0000 (16:30 -0400)
When we PG (powergate) UVD, we need to re-initialize it
before we can use it again.

v2: rebase on UVD stop fixes

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/si.c

index 736a416b51a7f4c2992810fef689ca99cbe9ae6f..59b866aa08d9b3029672493bb7cb30cdd4560b1e 100644 (file)
@@ -69,6 +69,7 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev);
 static void cik_program_aspm(struct radeon_device *rdev);
 static void cik_init_pg(struct radeon_device *rdev);
 static void cik_init_cg(struct radeon_device *rdev);
+static void cik_uvd_resume(struct radeon_device *rdev);
 
 /* get temperature in millidegrees */
 int ci_get_temp(struct radeon_device *rdev)
@@ -7619,8 +7620,9 @@ static int cik_startup(struct radeon_device *rdev)
                return r;
        }
 
-       r = cik_uvd_resume(rdev);
+       r = radeon_uvd_resume(rdev);
        if (!r) {
+               cik_uvd_resume(rdev);
                r = radeon_fence_driver_start_ring(rdev,
                                                   R600_RING_TYPE_UVD_INDEX);
                if (r)
@@ -7708,7 +7710,7 @@ static int cik_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     0, 0xfffff, RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = r600_uvd_init(rdev, true);
                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
        }
@@ -8598,15 +8600,10 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
        return r;
 }
 
-int cik_uvd_resume(struct radeon_device *rdev)
+static void cik_uvd_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;
@@ -8632,7 +8629,6 @@ int cik_uvd_resume(struct radeon_device *rdev)
        addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
        WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
 
-       return 0;
 }
 
 static void cik_pcie_gen3_enable(struct radeon_device *rdev)
index 2ce12ee3e67f4cc64eb9594a09408a63858b38be..710c1d4ae5db7911d8ca34edb977aae2ff3580ee 100644 (file)
@@ -5296,7 +5296,7 @@ static int evergreen_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     0, 0xfffff, RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = r600_uvd_init(rdev, true);
 
                if (r)
                        DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
index 21f2eceff2c672df33e4054b9d2a0f87a7e95b05..bc298a3500a42f239a504f535127443f83757525 100644 (file)
@@ -2230,7 +2230,7 @@ static int cayman_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     0, 0xfffff, RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = r600_uvd_init(rdev, true);
                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
        }
index 3db2e4ddb2d6b1c1fa586324929896af9dc67833..8a600153ef6cf221004c69dafa22cce1710e85f0 100644 (file)
@@ -2623,7 +2623,7 @@ void r600_dma_fini(struct radeon_device *rdev)
 /*
  * UVD
  */
-int r600_uvd_rbc_start(struct radeon_device *rdev)
+static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test)
 {
        struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        uint64_t rptr_addr;
@@ -2664,47 +2664,47 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
        rb_bufsz = (0x1 << 8) | rb_bufsz;
        WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
 
-       ring->ready = true;
-       r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
-       if (r) {
-               ring->ready = false;
-               return r;
-       }
+       if (ring_test) {
+               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;
-       }
+               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_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_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);
+               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);
+               /* 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_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
+               radeon_ring_write(ring, 3);
 
-       radeon_ring_unlock_commit(rdev, ring);
+               radeon_ring_unlock_commit(rdev, ring);
+       }
 
        return 0;
 }
 
-void r600_uvd_stop(struct radeon_device *rdev)
+void r600_do_uvd_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);
 
@@ -2723,11 +2723,17 @@ void r600_uvd_stop(struct radeon_device *rdev)
        /* Unstall UMC and register bus */
        WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
        WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
+}
 
+void r600_uvd_stop(struct radeon_device *rdev)
+{
+       struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+
+       r600_do_uvd_stop(rdev);
        ring->ready = false;
 }
 
-int r600_uvd_init(struct radeon_device *rdev)
+int r600_uvd_init(struct radeon_device *rdev, bool ring_test)
 {
        int i, j, r;
        /* disable byte swapping */
@@ -2815,17 +2821,17 @@ int r600_uvd_init(struct radeon_device *rdev)
 
        if (r) {
                DRM_ERROR("UVD not responding, giving up!!!\n");
-               radeon_set_uvd_clocks(rdev, 0, 0);
-               return r;
+               goto done;
        }
 
        /* enable interupt */
        WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
 
-       r = r600_uvd_rbc_start(rdev);
+       r = r600_uvd_rbc_start(rdev, ring_test);
        if (!r)
                DRM_INFO("UVD initialized successfully.\n");
 
+done:
        /* lower clocks again */
        radeon_set_uvd_clocks(rdev, 0, 0);
 
index 1e386c48ae2d9d9114fb6cfa34e9f01942329ced..3570817a5847c0a1297f14c5f61a6acc41a7b67f 100644 (file)
@@ -424,8 +424,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
                                                       struct seq_file *m);
 
 /* uvd */
-int r600_uvd_init(struct radeon_device *rdev);
-int r600_uvd_rbc_start(struct radeon_device *rdev);
+int r600_uvd_init(struct radeon_device *rdev, bool ring_test);
 void r600_uvd_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,
@@ -696,7 +695,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,
index 95590bd07afbf018d32454f1990042c84f1b0c46..52253b2ab0d5a0f24534011021f8d3a9fa77d67c 100644 (file)
@@ -1928,7 +1928,7 @@ static int rv770_startup(struct radeon_device *rdev)
                                     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     0, 0xfffff, RADEON_CP_PACKET2);
                if (!r)
-                       r = r600_uvd_init(rdev);
+                       r = r600_uvd_init(rdev, true);
 
                if (r)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
index 4f91e1f4d8147c7aee573ccf45de8efd02f47e74..da23ce8f4388d33caf3a648f7b0c162b84c7b152 100644 (file)
@@ -6421,7 +6421,7 @@ static int si_startup(struct radeon_device *rdev)
                                             UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                             0, 0xfffff, RADEON_CP_PACKET2);
                        if (!r)
-                               r = r600_uvd_init(rdev);
+                               r = r600_uvd_init(rdev, true);
                        if (r)
                                DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
                }