[PATCH 13/32] drm/amd/display: Add UCLK p-state support message to dcn401

Zaeem Mohamed zaeem.mohamed at amd.com
Fri May 31 16:51:26 UTC 2024


From: Dillon Varone <dillon.varone at amd.com>

[WHY&HOW]
Improves on the SMU interface to explicitly declare P-State support.

Reviewed-by: Alvin Lee <alvin.lee2 at amd.com>
Acked-by: Zaeem Mohamed <zaeem.mohamed at amd.com>
Signed-off-by: Dillon Varone <dillon.varone at amd.com>
---
 .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c        | 133 ++++++++++++------
 .../dc/clk_mgr/dcn401/dcn401_clk_mgr.h        |   3 +-
 .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c   |  14 +-
 .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h   |   6 +-
 .../dc/resource/dcn32/dcn32_resource.c        |   4 +
 5 files changed, 106 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
index e3a3893a9cab..0975986f5989 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
@@ -467,10 +467,10 @@ static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base,
 		if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support)) {
 			clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support;
 
-			/* To enable FCLK P-state switching, send FCLK_PSTATE_SUPPORTED message to PMFW */
+			/* To enable FCLK P-state switching, send PSTATE_SUPPORTED message to PMFW */
 			if (clk_mgr_base->clks.fclk_p_state_change_support) {
 				/* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
-				dcn401_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_SUPPORTED);
+				dcn401_smu_send_fclk_pstate_message(clk_mgr, true);
 			}
 		}
 
@@ -506,7 +506,7 @@ static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base,
 
 
 		p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
-		if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
+		if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.prev_p_state_change_support)) {
 			clk_mgr_base->clks.p_state_change_support = p_state_change_support;
 			clk_mgr_base->clks.fw_based_mclk_switching = p_state_change_support && new_clocks->fw_based_mclk_switching;
 
@@ -525,7 +525,7 @@ static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base,
 				update_fclk &&
 				dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_FCLK)) {
 			/* Handle code for sending a message to PMFW that FCLK P-state change is not supported */
-			dcn401_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_NOTSUPPORTED);
+			dcn401_smu_send_fclk_pstate_message(clk_mgr, false);
 		}
 
 		/* Always update saved value, even if new value not set due to P-State switching unsupported */
@@ -678,7 +678,12 @@ static void dcn401_execute_block_sequence(struct clk_mgr *clk_mgr_base, unsigned
 		case CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT:
 			dcn401_smu_send_fclk_pstate_message(
 					clk_mgr_internal,
-					params->update_fclk_pstate_support_params.support);
+					params->update_pstate_support_params.support);
+			break;
+		case CLK_MGR401_UPDATE_UCLK_PSTATE_SUPPORT:
+			dcn401_smu_send_uclk_pstate_message(
+					clk_mgr_internal,
+					params->update_pstate_support_params.support);
 			break;
 		case CLK_MGR401_UPDATE_CAB_FOR_UCLK:
 			dcn401_smu_send_cab_for_uclk_message(
@@ -773,16 +778,16 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 	/* CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT */
 	clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support;
 	fclk_p_state_change_support = new_clocks->fclk_p_state_change_support || (total_plane_count == 0);
-	if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support)) {
+	if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_prev_p_state_change_support)) {
 		clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support;
 		update_active_fclk = true;
 		update_idle_fclk = true;
 
-		/* To enable FCLK P-state switching, send FCLK_PSTATE_SUPPORTED message to PMFW */
+		/* To enable FCLK P-state switching, send PSTATE_SUPPORTED message to PMFW */
 		if (clk_mgr_base->clks.fclk_p_state_change_support) {
 			/* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
 			if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
-				block_sequence[num_steps].params.update_fclk_pstate_support_params.support = FCLK_PSTATE_SUPPORTED;
+				block_sequence[num_steps].params.update_pstate_support_params.support = true;
 				block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
 				num_steps++;
 			}
@@ -825,12 +830,26 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 		/* We don't actually care about socclk, don't notify SMU of hard min */
 		clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
 
+	/* UCLK */
+	if (new_clocks->fw_based_mclk_switching != clk_mgr_base->clks.fw_based_mclk_switching &&
+			new_clocks->fw_based_mclk_switching) {
+		/* enable FAMS features */
+		clk_mgr_base->clks.fw_based_mclk_switching = new_clocks->fw_based_mclk_switching;
+
+		block_sequence[num_steps].params.update_wait_for_dmub_ack_params.enable = clk_mgr_base->clks.fw_based_mclk_switching;
+		block_sequence[num_steps].func = CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK;
+		num_steps++;
+
+		block_sequence[num_steps].params.indicate_drr_status_params.mod_drr_for_pstate = clk_mgr_base->clks.fw_based_mclk_switching;
+		block_sequence[num_steps].func = CLK_MGR401_INDICATE_DRR_STATUS;
+		num_steps++;
+	}
+
 	/* CLK_MGR401_UPDATE_CAB_FOR_UCLK */
-	clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
 	clk_mgr_base->clks.prev_num_ways = clk_mgr_base->clks.num_ways;
-
 	if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
 			clk_mgr_base->clks.num_ways < new_clocks->num_ways) {
+		/* increase num ways for subvp */
 		clk_mgr_base->clks.num_ways = new_clocks->num_ways;
 		if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) {
 			block_sequence[num_steps].params.update_cab_for_uclk_params.num_ways = clk_mgr_base->clks.num_ways;
@@ -839,15 +858,22 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 		}
 	}
 
-	/* UCLK */
+	clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
 	uclk_p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
-	if (should_update_pstate_support(safe_to_lower, uclk_p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
+	if (should_update_pstate_support(safe_to_lower, uclk_p_state_change_support, clk_mgr_base->clks.prev_p_state_change_support)) {
 		clk_mgr_base->clks.p_state_change_support = uclk_p_state_change_support;
 		update_active_uclk = true;
 		update_idle_uclk = true;
 
-		/* to disable P-State switching, set UCLK min = max */
-		if (!clk_mgr_base->clks.p_state_change_support) {
+		if (clk_mgr_base->clks.p_state_change_support) {
+			/* enable UCLK switching  */
+			if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) {
+				block_sequence[num_steps].params.update_pstate_support_params.support = true;
+				block_sequence[num_steps].func = CLK_MGR401_UPDATE_UCLK_PSTATE_SUPPORT;
+				num_steps++;
+			}
+		} else {
+			/* when disabling P-State switching, set UCLK min = max */
 			if (dc->clk_mgr->dc_mode_softmax_enabled) {
 				/* will never have the functional UCLK min above the softmax
 				* since we calculate mode support based on softmax being the max UCLK
@@ -870,6 +896,7 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 			active_uclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz);
 		}
 	}
+
 	if (should_set_clock(safe_to_lower, new_clocks->idle_dramclk_khz, clk_mgr_base->clks.idle_dramclk_khz)) {
 		clk_mgr_base->clks.idle_dramclk_khz = new_clocks->idle_dramclk_khz;
 
@@ -879,17 +906,6 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 		}
 	}
 
-	/* set UCLK to requested value */
-	if ((update_active_uclk || update_idle_uclk) &&
-			dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK) &&
-			!is_idle_dpm_enabled) {
-		block_sequence[num_steps].params.update_hardmin_params.ppclk = PPCLK_UCLK;
-		block_sequence[num_steps].params.update_hardmin_params.freq_mhz = active_uclk_mhz;
-		block_sequence[num_steps].params.update_hardmin_params.response = NULL;
-		block_sequence[num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK;
-		num_steps++;
-	}
-
 	/* FCLK */
 	/* Always update saved value, even if new value not set due to P-State switching unsupported */
 	if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, clk_mgr_base->clks.fclk_khz)) {
@@ -927,41 +943,66 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
 		num_steps++;
 	}
 
-	/* CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK, CLK_MGR401_INDICATE_DRR_STATUS*/
-	if (clk_mgr_base->clks.fw_based_mclk_switching != new_clocks->fw_based_mclk_switching) {
-		clk_mgr_base->clks.fw_based_mclk_switching = new_clocks->fw_based_mclk_switching;
-
-		block_sequence[num_steps].params.update_wait_for_dmub_ack_params.enable = clk_mgr_base->clks.fw_based_mclk_switching;
-		block_sequence[num_steps].func = CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK;
-		num_steps++;
+	/* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
+	if (update_active_uclk || update_idle_uclk) {
+		if (!is_idle_dpm_enabled) {
+			block_sequence[num_steps].params.update_hardmin_params.ppclk = PPCLK_UCLK;
+			block_sequence[num_steps].params.update_hardmin_params.freq_mhz = active_uclk_mhz;
+			block_sequence[num_steps].params.update_hardmin_params.response = NULL;
+			block_sequence[num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK;
+			num_steps++;
+		}
 
-		block_sequence[num_steps].params.indicate_drr_status_params.mod_drr_for_pstate = clk_mgr_base->clks.fw_based_mclk_switching;
-		block_sequence[num_steps].func = CLK_MGR401_INDICATE_DRR_STATUS;
-		num_steps++;
+		/* disable UCLK P-State support if needed */
+		if (!uclk_p_state_change_support &&
+				should_update_pstate_support(safe_to_lower, uclk_p_state_change_support, clk_mgr_base->clks.prev_p_state_change_support) &&
+				dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) {
+			block_sequence[num_steps].params.update_pstate_support_params.support = false;
+			block_sequence[num_steps].func = CLK_MGR401_UPDATE_UCLK_PSTATE_SUPPORT;
+			num_steps++;
+		}
 	}
 
 	/* set FCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
-	if ((update_active_fclk || update_idle_fclk)) {
+	if (update_active_fclk || update_idle_fclk) {
+		/* No need to send active FCLK hardmin, automatically set based on DCFCLK */
+		// if (!is_idle_dpm_enabled) {
+		// 	block_sequence[*num_steps].update_hardmin_params.clk_mgr = clk_mgr;
+		// 	block_sequence[*num_steps].update_hardmin_params.ppclk = PPCLK_FCLK;
+		// 	block_sequence[*num_steps].update_hardmin_params.freq_mhz = active_fclk_mhz;
+		// 	block_sequence[*num_steps].update_hardmin_params.response = NULL;
+		// 	block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK;
+		// 	(*num_steps)++;
+		// }
+
 		/* disable FCLK P-State support if needed */
-		if (clk_mgr_base->clks.fclk_p_state_change_support != clk_mgr_base->clks.fclk_prev_p_state_change_support &&
+		if (!fclk_p_state_change_support &&
+				should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_prev_p_state_change_support) &&
 				dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
-			block_sequence[num_steps].params.update_fclk_pstate_support_params.support = FCLK_PSTATE_NOTSUPPORTED;
+			block_sequence[num_steps].params.update_pstate_support_params.support = false;
 			block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
 			num_steps++;
 		}
+	}
 
-		/* No need to send active FCLK hardmin, automatically set based on DCFCLK */
-		// block_sequence[*num_steps].update_hardmin_params.clk_mgr = clk_mgr;
-		// block_sequence[*num_steps].update_hardmin_params.ppclk = PPCLK_FCLK;
-		// block_sequence[*num_steps].update_hardmin_params.freq_mhz = active_fclk_mhz;
-		// block_sequence[*num_steps].update_hardmin_params.response = NULL;
-		// block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK;
-		// (*num_steps)++;
+	if (new_clocks->fw_based_mclk_switching != clk_mgr_base->clks.fw_based_mclk_switching &&
+			safe_to_lower && !new_clocks->fw_based_mclk_switching) {
+		/* disable FAMS features */
+		clk_mgr_base->clks.fw_based_mclk_switching = new_clocks->fw_based_mclk_switching;
+
+		block_sequence[num_steps].params.update_wait_for_dmub_ack_params.enable = clk_mgr_base->clks.fw_based_mclk_switching;
+		block_sequence[num_steps].func = CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK;
+		num_steps++;
+
+		block_sequence[num_steps].params.indicate_drr_status_params.mod_drr_for_pstate = clk_mgr_base->clks.fw_based_mclk_switching;
+		block_sequence[num_steps].func = CLK_MGR401_INDICATE_DRR_STATUS;
+		num_steps++;
 	}
 
 	/* CLK_MGR401_UPDATE_CAB_FOR_UCLK */
 	if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
-			clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
+			safe_to_lower && clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
+		/* decrease num ways for subvp */
 		clk_mgr_base->clks.num_ways = new_clocks->num_ways;
 		if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) {
 			block_sequence[num_steps].params.update_cab_for_uclk_params.num_ways = clk_mgr_base->clks.num_ways;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
index 8860b35279d3..8b0461992b22 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
@@ -38,7 +38,7 @@ union dcn401_clk_mgr_block_sequence_params {
 	struct {
 		/* inputs */
 		bool support;
-	} update_fclk_pstate_support_params;
+	} update_pstate_support_params;
 	struct {
 		/* inputs */
 		unsigned int num_ways;
@@ -82,6 +82,7 @@ enum dcn401_clk_mgr_block_sequence_func {
 	CLK_MGR401_UPDATE_IDLE_HARDMINS,
 	CLK_MGR401_UPDATE_DEEP_SLEEP_DCFCLK,
 	CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT,
+	CLK_MGR401_UPDATE_UCLK_PSTATE_SUPPORT,
 	CLK_MGR401_UPDATE_CAB_FOR_UCLK,
 	CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK,
 	CLK_MGR401_INDICATE_DRR_STATUS,
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c
index 84e9203aba3b..7700477d019b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c
@@ -131,12 +131,20 @@ static bool dcn401_smu_send_msg_with_param_delay(struct clk_mgr_internal *clk_mg
 	return false;
 }
 
-void dcn401_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool enable)
+void dcn401_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool support)
 {
-	smu_print("FCLK P-state support value is : %d\n", enable);
+	smu_print("FCLK P-state support value is : %d\n", support);
 
 	dcn401_smu_send_msg_with_param(clk_mgr,
-			DALSMC_MSG_SetFclkSwitchAllow, enable ? FCLK_PSTATE_SUPPORTED : FCLK_PSTATE_NOTSUPPORTED, NULL);
+			DALSMC_MSG_SetFclkSwitchAllow, support, NULL);
+}
+
+void dcn401_smu_send_uclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool support)
+{
+	smu_print("UCLK P-state support value is : %d\n", support);
+
+	dcn401_smu_send_msg_with_param(clk_mgr,
+			DALSMC_MSG_SetUclkPstateAllow, support, NULL);
 }
 
 void dcn401_smu_send_cab_for_uclk_message(struct clk_mgr_internal *clk_mgr, unsigned int num_ways)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h
index 892881d11ce8..651fb8d62864 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h
@@ -9,10 +9,8 @@
 #include "core_types.h"
 #include "dcn32/dcn32_clk_mgr_smu_msg.h"
 
-#define FCLK_PSTATE_NOTSUPPORTED       0x00
-#define FCLK_PSTATE_SUPPORTED          0x01
-
-void dcn401_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn401_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool support);
+void dcn401_smu_send_uclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool support);
 void dcn401_smu_send_cab_for_uclk_message(struct clk_mgr_internal *clk_mgr, unsigned int num_ways);
 void dcn401_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
 void dcn401_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index 022d320be1d5..ab9df1cc1d3c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -1978,6 +1978,10 @@ unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned
 {
 	uint32_t cache_lines_used, lines_per_way, total_cache_lines, num_ways;
 
+	if (total_size_in_mall_bytes == 0) {
+		return 0;
+	}
+
 	/* add 2 lines for worst case alignment */
 	cache_lines_used = total_size_in_mall_bytes / dc->caps.cache_line_size + 2;
 
-- 
2.34.1



More information about the amd-gfx mailing list