]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Increase minimum clock for TMDS 420 with pipe splitting
authorRelja Vojvodic <rvojvodi@amd.com>
Thu, 14 Aug 2025 15:33:22 +0000 (11:33 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:16 +0000 (15:34 -0500)
[ Upstream commit 002a612023c8b105bd3829d81862dee04368d6de ]

[Why]
-Pipe splitting allows for clocks to be reduced, but when using TMDS 420,
reduced clocks lead to missed clocks cycles on clock resyncing

[How]
-Impose a minimum clock when using TMDS 420

Reviewed-by: Chris Park <chris.park@amd.com>
Signed-off-by: Relja Vojvodic <rvojvodi@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c

index 157903115f3b4c371a3f8cd5a5f9713f84dfbc02..54969ba7e2b7ebad83b52222c2c8a06301d37dc0 100644 (file)
@@ -1262,18 +1262,27 @@ static void CalculateDETBufferSize(
 
 static double CalculateRequiredDispclk(
        enum dml2_odm_mode ODMMode,
-       double PixelClock)
+       double PixelClock,
+       bool isTMDS420)
 {
+       double DispClk;
 
        if (ODMMode == dml2_odm_mode_combine_4to1) {
-               return PixelClock / 4.0;
+               DispClk = PixelClock / 4.0;
        } else if (ODMMode == dml2_odm_mode_combine_3to1) {
-               return PixelClock / 3.0;
+               DispClk = PixelClock / 3.0;
        } else if (ODMMode == dml2_odm_mode_combine_2to1) {
-               return PixelClock / 2.0;
+               DispClk = PixelClock / 2.0;
        } else {
-               return PixelClock;
+               DispClk = PixelClock;
+       }
+
+       if (isTMDS420) {
+               double TMDS420MinPixClock = PixelClock / 2.0;
+               DispClk = math_max2(DispClk, TMDS420MinPixClock);
        }
+
+       return DispClk;
 }
 
 static double TruncToValidBPP(
@@ -4088,11 +4097,12 @@ static void CalculateODMMode(
        bool success;
        bool UseDSC = DSCEnable && (NumberOfDSCSlices > 0);
        enum dml2_odm_mode DecidedODMMode;
+       bool isTMDS420 = (OutFormat == dml2_420 && Output == dml2_hdmi);
 
-       SurfaceRequiredDISPCLKWithoutODMCombine = CalculateRequiredDispclk(dml2_odm_mode_bypass, PixelClock);
-       SurfaceRequiredDISPCLKWithODMCombineTwoToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_2to1, PixelClock);
-       SurfaceRequiredDISPCLKWithODMCombineThreeToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_3to1, PixelClock);
-       SurfaceRequiredDISPCLKWithODMCombineFourToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_4to1, PixelClock);
+       SurfaceRequiredDISPCLKWithoutODMCombine = CalculateRequiredDispclk(dml2_odm_mode_bypass, PixelClock, isTMDS420);
+       SurfaceRequiredDISPCLKWithODMCombineTwoToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_2to1, PixelClock, isTMDS420);
+       SurfaceRequiredDISPCLKWithODMCombineThreeToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_3to1, PixelClock, isTMDS420);
+       SurfaceRequiredDISPCLKWithODMCombineFourToOne = CalculateRequiredDispclk(dml2_odm_mode_combine_4to1, PixelClock, isTMDS420);
 #ifdef __DML_VBA_DEBUG__
        dml2_printf("DML::%s: ODMUse = %d\n", __func__, ODMUse);
        dml2_printf("DML::%s: Output = %d\n", __func__, Output);