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

v2: agd5f: fix clock dividers setup for bonaire
v3: agd5f: rebase

Signed-off-by: Christian K?nig <christian.koenig at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/radeon/cik.c         |  111 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/cikd.h        |   28 +++++++++
 drivers/gpu/drm/radeon/radeon_asic.h |    2 +
 drivers/gpu/drm/radeon/radeon_uvd.c  |    8 +++
 4 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index e8ea845..29e0cdd 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -1495,6 +1495,9 @@ static void cik_gpu_init(struct radeon_device *rdev)
        WREG32(DMIF_ADDR_CALC, gb_addr_config);
        WREG32(SDMA0_TILING_CONFIG + SDMA0_REGISTER_OFFSET, gb_addr_config & 
0x70);
        WREG32(SDMA0_TILING_CONFIG + SDMA1_REGISTER_OFFSET, gb_addr_config & 
0x70);
+       WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
+       WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
+       WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);

        cik_tiling_mode_table_init(rdev);

@@ -4906,6 +4909,16 @@ static int cik_startup(struct radeon_device *rdev)
                return r;
        }

+       r = cik_uvd_resume(rdev);
+       if (!r) {
+               r = radeon_fence_driver_start_ring(rdev,
+                                                  R600_RING_TYPE_UVD_INDEX);
+               if (r)
+                       dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
+       }
+       if (r)
+               rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+
        /* Enable IRQ */
        if (!rdev->irq.installed) {
                r = radeon_irq_kms_init(rdev);
@@ -4952,6 +4965,18 @@ static int cik_startup(struct radeon_device *rdev)
        if (r)
                return r;

+       ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+       if (ring->ring_size) {
+               r = radeon_ring_init(rdev, ring, ring->ring_size,
+                                    R600_WB_UVD_RPTR_OFFSET,
+                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+                                    0, 0xfffff, RADEON_CP_PACKET2);
+               if (!r)
+                       r = r600_uvd_init(rdev);
+               if (r)
+                       DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
+       }
+
        r = radeon_ib_pool_init(rdev);
        if (r) {
                dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -5013,6 +5038,8 @@ 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);
+       radeon_uvd_suspend(rdev);
        cik_irq_suspend(rdev);
        radeon_wb_disable(rdev);
        cik_pcie_gart_disable(rdev);
@@ -5096,6 +5123,13 @@ int cik_init(struct radeon_device *rdev)
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 256 * 1024);

+       r = radeon_uvd_init(rdev);
+       if (!r) {
+               ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+               ring->ring_obj = NULL;
+               r600_ring_init(rdev, ring, 4096);
+       }
+
        rdev->ih.ring_obj = NULL;
        r600_ih_ring_init(rdev, 64 * 1024);

@@ -5150,6 +5184,7 @@ void cik_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
+       radeon_uvd_fini(rdev);
        cik_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
@@ -5717,3 +5752,79 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device 
*rdev)
        return clock;
 }

+static int cik_set_uvd_clock(struct radeon_device *rdev, u32 clock,
+                              u32 cntl_reg, u32 status_reg)
+{
+       int r, i;
+       struct atom_clock_dividers dividers;
+       uint32_t tmp;
+
+       r = radeon_atom_get_clock_dividers(rdev, 
COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
+                                          clock, false, &dividers);
+       if (r)
+               return r;
+
+       tmp = RREG32_SMC(cntl_reg);
+       tmp &= ~(DCLK_DIR_CNTL_EN|DCLK_DIVIDER_MASK);
+       tmp |= dividers.post_divider;
+       WREG32_SMC(cntl_reg, tmp);
+
+       for (i = 0; i < 100; i++) {
+               if (RREG32_SMC(status_reg) & DCLK_STATUS)
+                       break;
+               mdelay(10);
+       }
+       if (i == 100)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
+{
+       int r = 0;
+
+       r = cik_set_uvd_clock(rdev, vclk, CG_VCLK_CNTL, CG_VCLK_STATUS);
+       if (r)
+               return r;
+
+       r = cik_set_uvd_clock(rdev, dclk, CG_DCLK_CNTL, CG_DCLK_STATUS);
+       return r;
+}
+
+int 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;
+       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;
+}
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index d23809a..79be39e 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -1204,4 +1204,32 @@
 #       define SDMA_SRBM_WRITE_EXTRA_BYTE_ENABLE(x)       ((x) << 12)
                 /* byte mask */

+/* UVD */
+
+#define UVD_UDEC_ADDR_CONFIG           0xef4c
+#define UVD_UDEC_DB_ADDR_CONFIG                0xef50
+#define UVD_UDEC_DBW_ADDR_CONFIG       0xef54
+
+#define UVD_LMI_EXT40_ADDR             0xf498
+#define UVD_LMI_ADDR_EXT               0xf594
+#define UVD_VCPU_CACHE_OFFSET0         0xf608
+#define UVD_VCPU_CACHE_SIZE0           0xf60c
+#define UVD_VCPU_CACHE_OFFSET1         0xf610
+#define UVD_VCPU_CACHE_SIZE1           0xf614
+#define UVD_VCPU_CACHE_OFFSET2         0xf618
+#define UVD_VCPU_CACHE_SIZE2           0xf61c
+
+#define UVD_RBC_RB_RPTR                        0xf690
+#define UVD_RBC_RB_WPTR                        0xf694
+
+/* UVD clocks */
+
+#define CG_DCLK_CNTL                   0xC050009C
+#      define DCLK_DIVIDER_MASK        0x7f
+#      define DCLK_DIR_CNTL_EN         (1 << 8)
+#define CG_DCLK_STATUS                 0xC05000A0
+#      define DCLK_STATUS              (1 << 0)
+#define CG_VCLK_CNTL                   0xC05000A4
+#define CG_VCLK_STATUS                 0xC05000A8
+
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index 8c19e36..3405742 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -560,5 +560,7 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device 
*rdev);
 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);

 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c 
b/drivers/gpu/drm/radeon/radeon_uvd.c
index cad735d..fdc77d1 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -44,11 +44,13 @@
 #define FIRMWARE_CYPRESS       "radeon/CYPRESS_uvd.bin"
 #define FIRMWARE_SUMO          "radeon/SUMO_uvd.bin"
 #define FIRMWARE_TAHITI                "radeon/TAHITI_uvd.bin"
+#define FIRMWARE_BONAIRE       "radeon/BONAIRE_uvd.bin"

 MODULE_FIRMWARE(FIRMWARE_RV710);
 MODULE_FIRMWARE(FIRMWARE_CYPRESS);
 MODULE_FIRMWARE(FIRMWARE_SUMO);
 MODULE_FIRMWARE(FIRMWARE_TAHITI);
+MODULE_FIRMWARE(FIRMWARE_BONAIRE);

 static void radeon_uvd_idle_work_handler(struct work_struct *work);

@@ -100,6 +102,12 @@ int radeon_uvd_init(struct radeon_device *rdev)
                fw_name = FIRMWARE_TAHITI;
                break;

+       case CHIP_BONAIRE:
+       case CHIP_KABINI:
+       case CHIP_KAVERI:
+               fw_name = FIRMWARE_BONAIRE;
+               break;
+
        default:
                return -EINVAL;
        }
-- 
1.7.7.5

Reply via email to