These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / radeon / ni.c
index 64d3a77..158872e 100644 (file)
 #include "radeon_ucode.h"
 #include "clearstate_cayman.h"
 
+/*
+ * Indirect registers accessor
+ */
+u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
+{
+       unsigned long flags;
+       u32 r;
+
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
+       WREG32(TN_SMC_IND_INDEX_0, (reg));
+       r = RREG32(TN_SMC_IND_DATA_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
+       return r;
+}
+
+void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
+       WREG32(TN_SMC_IND_INDEX_0, (reg));
+       WREG32(TN_SMC_IND_DATA_0, (v));
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
+}
+
 static const u32 tn_rlc_save_restore_register_list[] =
 {
        0x98fc,
@@ -2041,6 +2066,25 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
+       if (rdev->family == CHIP_ARUBA) {
+               r = radeon_vce_resume(rdev);
+               if (!r)
+                       r = vce_v1_0_resume(rdev);
+
+               if (!r)
+                       r = radeon_fence_driver_start_ring(rdev,
+                                                          TN_RING_TYPE_VCE1_INDEX);
+               if (!r)
+                       r = radeon_fence_driver_start_ring(rdev,
+                                                          TN_RING_TYPE_VCE2_INDEX);
+
+               if (r) {
+                       dev_err(rdev->dev, "VCE init error (%d).\n", r);
+                       rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+                       rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+               }
+       }
+
        r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
        if (r) {
                dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
@@ -2118,6 +2162,21 @@ static int cayman_startup(struct radeon_device *rdev)
                        DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
        }
 
+       if (rdev->family == CHIP_ARUBA) {
+               ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+               if (ring->ring_size)
+                       r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+
+               ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+               if (ring->ring_size)
+                       r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+
+               if (!r)
+                       r = vce_v1_0_init(rdev);
+               if (r)
+                       DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
+       }
+
        r = radeon_ib_pool_init(rdev);
        if (r) {
                dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -2273,6 +2332,19 @@ int cayman_init(struct radeon_device *rdev)
                r600_ring_init(rdev, ring, 4096);
        }
 
+       if (rdev->family == CHIP_ARUBA) {
+               r = radeon_vce_init(rdev);
+               if (!r) {
+                       ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+                       ring->ring_obj = NULL;
+                       r600_ring_init(rdev, ring, 4096);
+
+                       ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+                       ring->ring_obj = NULL;
+                       r600_ring_init(rdev, ring, 4096);
+               }
+       }
+
        rdev->ih.ring_obj = NULL;
        r600_ih_ring_init(rdev, 64 * 1024);
 
@@ -2326,6 +2398,8 @@ void cayman_fini(struct radeon_device *rdev)
        radeon_irq_kms_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_fini(rdev);
+       if (rdev->family == CHIP_ARUBA)
+               radeon_vce_fini(rdev);
        cayman_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
@@ -2554,3 +2628,34 @@ void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
        radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
        radeon_ring_write(ring, 0x0);
 }
+
+int tn_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
+{
+       struct atom_clock_dividers dividers;
+       int r, i;
+
+        r = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                          ecclk, false, &dividers);
+       if (r)
+               return r;
+
+       for (i = 0; i < 100; i++) {
+               if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
+                       break;
+               mdelay(10);
+       }
+       if (i == 100)
+               return -ETIMEDOUT;
+
+       WREG32_P(CG_ECLK_CNTL, dividers.post_div, ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK));
+
+       for (i = 0; i < 100; i++) {
+               if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
+                       break;
+               mdelay(10);
+       }
+       if (i == 100)
+               return -ETIMEDOUT;
+
+       return 0;
+}