drm/radeon: Fix "slow" audio over DP on DCE8+
authorSlava Grigorev <slava.grigorev@amd.com>
Thu, 17 Dec 2015 16:09:58 +0000 (11:09 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 18 Dec 2015 22:29:46 +0000 (17:29 -0500)
DP audio is derived from the dfs clock.

Signed-off-by: Slava Grigorev <slava.grigorev@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/sid.h

index 752072771388419c6b932f77aecc84db64d89e1b..6bfc46369db1b4f8daa02fba453a382e863a3585 100644 (file)
@@ -301,6 +301,22 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev,
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
        if (ASIC_IS_DCE8(rdev)) {
+               unsigned int div = (RREG32(DENTIST_DISPCLK_CNTL) &
+                       DENTIST_DPREFCLK_WDIVIDER_MASK) >>
+                       DENTIST_DPREFCLK_WDIVIDER_SHIFT;
+
+               if (div < 128 && div >= 96)
+                       div -= 64;
+               else if (div >= 64)
+                       div = div / 2 - 16;
+               else if (div >= 8)
+                       div /= 4;
+               else
+                       div = 0;
+
+               if (div)
+                       clock = rdev->clock.gpupll_outputfreq * 10 / div;
+
                WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000);
                WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock);
        } else {
index cf09102a2aca6385ee3e82c3847d1df28829f606..a9955e85009a463a32fa75ca97244688a18ff315 100644 (file)
@@ -268,6 +268,7 @@ struct radeon_clock {
        uint32_t current_dispclk;
        uint32_t dp_extclk;
        uint32_t max_pixel_clock;
+       uint32_t gpupll_outputfreq;
 };
 
 /*
index 8f285244c839a8c85ad186a1b877f94749776a58..13e5513b73af556c8fa126080fd0a9ef5f01ba10 100644 (file)
@@ -1263,6 +1263,13 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                rdev->mode_info.firmware_flags =
                        le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);
 
+               if (ASIC_IS_DCE8(rdev)) {
+                       rdev->clock.gpupll_outputfreq =
+                               le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq);
+                       if (rdev->clock.gpupll_outputfreq == 0)
+                               rdev->clock.gpupll_outputfreq = 360000; /* 3.6 GHz */
+               }
+
                return true;
        }
 
index 4c4a7218a3bd63c11f7f9c8d6b96583bef27368b..d1a7b58dd291f8798666276acded0290aae805e2 100644 (file)
 #define DCCG_AUDIO_DTO1_PHASE                           0x05c0
 #define DCCG_AUDIO_DTO1_MODULE                          0x05c4
 
+#define DENTIST_DISPCLK_CNTL                           0x0490
+#      define DENTIST_DPREFCLK_WDIVIDER(x)             (((x) & 0x7f) << 24)
+#      define DENTIST_DPREFCLK_WDIVIDER_MASK           (0x7f << 24)
+#      define DENTIST_DPREFCLK_WDIVIDER_SHIFT          24
+
 #define AFMT_AUDIO_SRC_CONTROL                          0x713c
 #define                AFMT_AUDIO_SRC_SELECT(x)                (((x) & 7) << 0)
 /* AFMT_AUDIO_SRC_SELECT