drm/radeon: add set_uvd_clocks callback for ON/LN/TN (v4)
authorAlex Deucher <alexander.deucher@amd.com>
Mon, 8 Apr 2013 10:41:32 +0000 (12:41 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 9 Apr 2013 14:31:35 +0000 (10:31 -0400)
v2: write clk registers only once!
v3: update cg scratch register properly
v4: add TN support

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>
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h

index 18b66ff..bdd3d34 100644 (file)
@@ -84,6 +84,53 @@ void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
        }
 }
 
+static int sumo_set_uvd_clock(struct radeon_device *rdev, u32 clock,
+                             u32 cntl_reg, u32 status_reg)
+{
+       int r, i;
+       struct atom_clock_dividers dividers;
+
+        r = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                          clock, false, &dividers);
+       if (r)
+               return r;
+
+       WREG32_P(cntl_reg, dividers.post_div, ~(DCLK_DIR_CNTL_EN|DCLK_DIVIDER_MASK));
+
+       for (i = 0; i < 100; i++) {
+               if (RREG32(status_reg) & DCLK_STATUS)
+                       break;
+               mdelay(10);
+       }
+       if (i == 100)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
+{
+       int r = 0;
+       u32 cg_scratch = RREG32(CG_SCRATCH1);
+
+       r = sumo_set_uvd_clock(rdev, vclk, CG_VCLK_CNTL, CG_VCLK_STATUS);
+       if (r)
+               goto done;
+       cg_scratch &= 0xffff0000;
+       cg_scratch |= vclk / 100; /* Mhz */
+
+       r = sumo_set_uvd_clock(rdev, dclk, CG_DCLK_CNTL, CG_DCLK_STATUS);
+       if (r)
+               goto done;
+       cg_scratch &= 0x0000ffff;
+       cg_scratch |= (dclk / 100) << 16; /* Mhz */
+
+done:
+       WREG32(CG_SCRATCH1, cg_scratch);
+
+       return r;
+}
+
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
        u16 ctl, v;
index c5d873e..b6491a3 100644 (file)
 #define RCU_IND_INDEX                                  0x100
 #define RCU_IND_DATA                                   0x104
 
+/* fusion uvd clocks */
+#define CG_DCLK_CNTL                                    0x610
+#       define DCLK_DIVIDER_MASK                        0x7f
+#       define DCLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_DCLK_STATUS                                  0x614
+#       define DCLK_STATUS                              (1 << 0)
+#define CG_VCLK_CNTL                                    0x618
+#define CG_VCLK_STATUS                                  0x61c
+#define        CG_SCRATCH1                                     0x820
+
 #define GRBM_GFX_INDEX                                 0x802C
 #define                INSTANCE_INDEX(x)                       ((x) << 0)
 #define                SE_INDEX(x)                             ((x) << 16)
index a7a7b2b..d3992d9 100644 (file)
@@ -1373,6 +1373,7 @@ static struct radeon_asic sumo_asic = {
                .get_pcie_lanes = NULL,
                .set_pcie_lanes = NULL,
                .set_clock_gating = NULL,
+               .set_uvd_clocks = &sumo_set_uvd_clocks,
        },
        .pflip = {
                .pre_page_flip = &evergreen_pre_page_flip,
@@ -1744,6 +1745,7 @@ static struct radeon_asic trinity_asic = {
                .get_pcie_lanes = NULL,
                .set_pcie_lanes = NULL,
                .set_clock_gating = NULL,
+               .set_uvd_clocks = &sumo_set_uvd_clocks,
        },
        .pflip = {
                .pre_page_flip = &evergreen_pre_page_flip,
index 515db96..37f28a3 100644 (file)
@@ -459,6 +459,7 @@ extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
 extern void sumo_pm_init_profile(struct radeon_device *rdev);
 extern void btc_pm_init_profile(struct radeon_device *rdev);
+int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);