]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Fix DCE 6.0 and 6.4 PLL programming.
authorTimur Kristóf <timur.kristof@gmail.com>
Tue, 22 Jul 2025 15:58:30 +0000 (17:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:34:31 +0000 (16:34 +0200)
commit 1c8dc3e088e09531bcdfc9fe348204abc3decb6c upstream.

Apparently, both DCE 6.0 and 6.4 have 3 PLLs, but PLL0 can only
be used for DP. Make sure to initialize the correct amount of PLLs
in DC for these DCE versions and use PLL0 only for DP.

Also, on DCE 6.0 and 6.4, the PLL0 needs to be powered on at
initialization as opposed to DCE 6.1 and 7.x which use a different
clock source for DFS.

The following functions were used as reference from the old
radeon driver implementation of DCE 6.x:
- radeon_atom_pick_pll
- atombios_crtc_set_disp_eng_pll

Reviewed-by: Rodrigo Siqueira <siqueira@igalia.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 35222b5934ec8d762473592ece98659baf6bc48e)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c

index 26feefbb8990ae52481fa6af7f044962d7ea60ba..f5ad0a1770388c0844814178feb90c1007644cf2 100644 (file)
@@ -245,6 +245,11 @@ int dce_set_clock(
        pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10;
        pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
 
+       /* DCE 6.0, DCE 6.4: engine clock is the same as PLL0 */
+       if (clk_mgr_base->ctx->dce_version == DCE_VERSION_6_0 ||
+           clk_mgr_base->ctx->dce_version == DCE_VERSION_6_4)
+               pxl_clk_params.pll_id = CLOCK_SOURCE_ID_PLL0;
+
        if (clk_mgr_dce->dfs_bypass_active)
                pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
 
index d9ffdded5ce1e176678b2570bc2ea0dc32888ebf..6944bac4ea9b2ec0ff4e7a19613842ae40c610b4 100644 (file)
@@ -373,7 +373,7 @@ static const struct resource_caps res_cap = {
                .num_timing_generator = 6,
                .num_audio = 6,
                .num_stream_encoder = 6,
-               .num_pll = 2,
+               .num_pll = 3,
                .num_ddc = 6,
 };
 
@@ -389,7 +389,7 @@ static const struct resource_caps res_cap_64 = {
                .num_timing_generator = 2,
                .num_audio = 2,
                .num_stream_encoder = 2,
-               .num_pll = 2,
+               .num_pll = 3,
                .num_ddc = 2,
 };
 
@@ -973,21 +973,24 @@ static bool dce60_construct(
 
        if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) {
                pool->base.dp_clock_source =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
 
+               /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */
                pool->base.clock_sources[0] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
                pool->base.clock_sources[1] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
                pool->base.clk_src_count = 2;
 
        } else {
                pool->base.dp_clock_source =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
 
                pool->base.clock_sources[0] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
-               pool->base.clk_src_count = 1;
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+               pool->base.clock_sources[1] =
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
+               pool->base.clk_src_count = 2;
        }
 
        if (pool->base.dp_clock_source == NULL) {
@@ -1365,21 +1368,24 @@ static bool dce64_construct(
 
        if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) {
                pool->base.dp_clock_source =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
 
+               /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */
                pool->base.clock_sources[0] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
                pool->base.clock_sources[1] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
                pool->base.clk_src_count = 2;
 
        } else {
                pool->base.dp_clock_source =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true);
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
 
                pool->base.clock_sources[0] =
-                               dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
-               pool->base.clk_src_count = 1;
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
+               pool->base.clock_sources[1] =
+                       dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
+               pool->base.clk_src_count = 2;
        }
 
        if (pool->base.dp_clock_source == NULL) {