Blob Blame History Raw
From affb6683695429d411502933ee16feefa05ba067 Mon Sep 17 00:00:00 2001
From: George Shen <george.shen@amd.com>
Date: Fri, 20 May 2022 11:55:10 -0400
Subject: drm/amd/display: Fix divide-by-zero in DPPCLK and DISPCLK calculation
Git-commit: a3a885878e74d3d81e4742f8dd84faa27c8863ad
Patch-mainline: v6.0-rc1
References: jsc#PED-1166 jsc#PED-1168 jsc#PED-1170 jsc#PED-1218 jsc#PED-1220 jsc#PED-1222 jsc#PED-1223 jsc#PED-1225 jsc#PED-2849

[Why]
Certain use cases will pass in zero in the new_clocks parameter for all
clocks. This results in a divide-by-zero error when attempting to round
up the new clock.

When new_clocks are zero, no rounding is required, so we can skip it.

[How]
Guard the division calculation with a check to make sure clocks are not
zero.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Patrik Jakobsson <pjakobsson@suse.de>
---
 .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c   | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index bab85f3c9c67..8ece88ddfb5b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -335,14 +335,16 @@ static void dcn32_update_dppclk_dispclk_freq(struct clk_mgr_internal *clk_mgr, s
 	int dpp_divider = 0;
 	int disp_divider = 0;
 
-	dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-			* clk_mgr->base.dentist_vco_freq_khz / new_clocks->dppclk_khz;
-	disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-			* clk_mgr->base.dentist_vco_freq_khz / new_clocks->dispclk_khz;
-
-	// Divide back the previous result to round up to the actual clock value that will be set from divider
-	new_clocks->dppclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / dpp_divider;
-	new_clocks->dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+	if (new_clocks->dppclk_khz) {
+		dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+				* clk_mgr->base.dentist_vco_freq_khz / new_clocks->dppclk_khz;
+		new_clocks->dppclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / dpp_divider;
+	}
+	if (new_clocks->dispclk_khz > 0) {
+		disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+				* clk_mgr->base.dentist_vco_freq_khz / new_clocks->dispclk_khz;
+		new_clocks->dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+	}
 }
 
 static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
-- 
2.38.1