[PATCH 06/19] drm/amd/display: Floor to mhz when requesting dpp disp clock changes to SMU

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Wenjing Liu <wenjing.liu@xxxxxxx>

[Why]
SMU uses discrete dpp and disp clock levels. When we submit SMU request
for clock changes in Mhz we need to floor the requested value from Khz so
SMU will choose the next higher clock level in Khz to set. If we ceil to
Mhz, SMU will have to choose the next higher clock level after the ceil,
which could result in unnecessarily jumpping to the next level.

For example, we request 1911,111Khz which is exactly one of the SMU preset
level. If we pass 1912Mhz, SMU will choose 2150,000 khz. If we pass
1911Mhz, SMU will choose 1911,111kHz, which is the expected value.

Reviewed-by: Alvin Lee <alvin.lee2@xxxxxxx>
Acked-by: Alex Hung <alex.hung@xxxxxxx>
Signed-off-by: Wenjing Liu <wenjing.liu@xxxxxxx>
---
 .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c  | 40 +++++++++++++++++--
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |  5 +++
 2 files changed, 41 insertions(+), 4 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 aadd07bc68c5..8fa0aae941c3 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
@@ -387,7 +387,15 @@ static void dcn32_update_clocks_update_dentist(
 		uint32_t temp_dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / temp_disp_divider;
 
 		if (clk_mgr->smu_present)
-			dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(temp_dispclk_khz));
+			/*
+			 * SMU uses discrete dispclk presets. We applied
+			 * the same formula to increase our dppclk_khz
+			 * to the next matching discrete value. By
+			 * contract, we should use the preset dispclk
+			 * floored in Mhz to describe the intended clock.
+			 */
+			dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK,
+					khz_to_mhz_floor(temp_dispclk_khz));
 
 		if (dc->debug.override_dispclk_programming) {
 			REG_GET(DENTIST_DISPCLK_CNTL,
@@ -426,7 +434,15 @@ static void dcn32_update_clocks_update_dentist(
 
 	/* do requested DISPCLK updates*/
 	if (clk_mgr->smu_present)
-		dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr->base.clks.dispclk_khz));
+		/*
+		 * SMU uses discrete dispclk presets. We applied
+		 * the same formula to increase our dppclk_khz
+		 * to the next matching discrete value. By
+		 * contract, we should use the preset dispclk
+		 * floored in Mhz to describe the intended clock.
+		 */
+		dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK,
+				khz_to_mhz_floor(clk_mgr->base.clks.dispclk_khz));
 
 	if (dc->debug.override_dispclk_programming) {
 		REG_GET(DENTIST_DISPCLK_CNTL,
@@ -734,7 +750,15 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
 		clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
 
 		if (clk_mgr->smu_present && !dpp_clock_lowered)
-			dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
+			/*
+			 * SMU uses discrete dppclk presets. We applied
+			 * the same formula to increase our dppclk_khz
+			 * to the next matching discrete value. By
+			 * contract, we should use the preset dppclk
+			 * floored in Mhz to describe the intended clock.
+			 */
+			dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK,
+					khz_to_mhz_floor(clk_mgr_base->clks.dppclk_khz));
 
 		update_dppclk = true;
 	}
@@ -765,7 +789,15 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
 			dcn32_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
 			dcn32_update_clocks_update_dentist(clk_mgr, context);
 			if (clk_mgr->smu_present)
-				dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
+				/*
+				 * SMU uses discrete dppclk presets. We applied
+				 * the same formula to increase our dppclk_khz
+				 * to the next matching discrete value. By
+				 * contract, we should use the preset dppclk
+				 * floored in Mhz to describe the intended clock.
+				 */
+				dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK,
+						khz_to_mhz_floor(clk_mgr_base->clks.dppclk_khz));
 		} else {
 			/* if clock is being raised, increase refclk before lowering DTO */
 			if (update_dppclk || update_dispclk)
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index 6f4c97543c14..e668cc21cd28 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -393,6 +393,11 @@ static inline int khz_to_mhz_ceil(int khz)
 	return (khz + 999) / 1000;
 }
 
+static inline int khz_to_mhz_floor(int khz)
+{
+	return khz / 1000;
+}
+
 int clk_mgr_helper_get_active_display_cnt(
 		struct dc *dc,
 		struct dc_state *context);
-- 
2.34.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux