[PATCH 43/49] drm/amd/display: enforce UCLK pstate support in mode_support

Fangzhi Zuo <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Alexander Chechik <[email protected]>

[Why]
mode_support does not require UCLK pstate today, so later PMO optimization
stages can push a plane's VActive latency-hiding margin below zero without
rechecking that the config still supports UCLK pstate. This can blank the
display on high-bandwidth configs.

[How]
Plumb the PMO-selected per-plane pstate method into mode_support and fail
the config only when UCLK pstate is required (method != na) but not
supported. For planes committed to a vactive method, require a non-negative
VActive latency-hiding margin, and skip the check when all streams are
blanked. No-op the PMO DCN42 pstate test (returning false only on the
initial candidate so the optimize/FAMS2 stage-3 setup still runs), since
reserved time is guaranteed by the override and the vactive margin is now
enforced in core mode_support.

Reviewed-by: Dillon Varone <[email protected]>
Signed-off-by: Alexander Chechik <[email protected]>
Signed-off-by: Matthew Stewart <[email protected]>
Tested-by: Dan Wheeler <[email protected]>
---
 .../dml21/src/dml2_core/dml2_core_dcn4.c      |  8 +++++
 .../src/dml2_core/dml2_core_dcn4_calcs.c      | 18 +++++++++++
 .../dml21/src/dml2_pmo/dml2_pmo_dcn42.c       | 32 ++++++-------------
 3 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
index 727b01ca18bf..45f1bf5e14bf 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
@@ -554,6 +554,14 @@ bool core_dcn4_mode_support(struct dml2_core_mode_support_in_out *in_out)
 	l->mode_support_ex_params.min_clk_index = in_out->min_clk_index;
 	l->mode_support_ex_params.out_evaluation_info = &in_out->mode_support_result.cfg_support_info.clean_me_up.support_info;
 
+	for (i = 0; i < l->svp_expanded_display_cfg.num_planes; i++) {
+		if (i < in_out->display_cfg->display_config.num_planes)
+			core->clean_me_up.mode_lib.ms.uclk_pstate_switch_modes[i] =
+				in_out->display_cfg->stage3.pstate_switch_modes[i];
+		else
+			core->clean_me_up.mode_lib.ms.uclk_pstate_switch_modes[i] = dml2_pstate_method_na;
+	}
+
 	result = dml2_core_calcs_mode_support_ex(&l->mode_support_ex_params);
 
 	in_out->mode_support_result.cfg_support_info.is_supported = result;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 110ab26a6a39..da9a1c4e2bdc 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -9637,6 +9637,22 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
 	DML_LOG_VERBOSE("DML::%s: ROBSupport = %u\n", __func__, mode_lib->ms.support.ROBSupport);
 #endif
 
+	mode_lib->ms.support.global_dram_clock_change_support_required = false;
+
+	if (!display_cfg->overrides.all_streams_blanked) {
+		for (k = 0; k < mode_lib->ms.num_active_planes; k++) {
+			if (mode_lib->ms.uclk_pstate_switch_modes[k] == dml2_pstate_method_na)
+				continue;
+
+			mode_lib->ms.support.global_dram_clock_change_support_required = true;
+
+			if ((mode_lib->ms.uclk_pstate_switch_modes[k] == dml2_pstate_method_vactive ||
+					mode_lib->ms.uclk_pstate_switch_modes[k] == dml2_pstate_method_fw_vactive_drr) &&
+					mode_lib->ms.VActiveLatencyHidingMargin[k] < 0)
+				mode_lib->ms.support.global_dram_clock_change_supported = false;
+		}
+	}
+
 	/*Mode Support, Voltage State and SOC Configuration*/
 	{
 		if (mode_lib->ms.support.ScaleRatioAndTapsSupport
@@ -9683,6 +9699,8 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
 			&& mode_lib->ms.support.DCCMetaBufferSizeNotExceeded
 			&& !mode_lib->ms.support.ExceededMALLSize
 			&& mode_lib->ms.support.g6_temp_read_support
+			&& (mode_lib->ms.support.global_dram_clock_change_supported
+				|| !mode_lib->ms.support.global_dram_clock_change_support_required)
 			&& ((!display_cfg->hostvm_enable && !s->ImmediateFlipRequired) || mode_lib->ms.support.ImmediateFlipSupport)) {
 			DML_LOG_VERBOSE("DML::%s: mode is supported\n", __func__);
 			mode_lib->ms.support.ModeSupport = true;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.c
index 790aef95caa6..57a6a7d5b740 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.c
@@ -13,8 +13,6 @@
  * configurations, ensuring p-state watermark support in the blank period only.
  */
 
-static const double MIN_VACTIVE_MARGIN_PCT = 0.25; // We need more than non-zero margin because DET buffer granularity can alter vactive latency hiding
-
 static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_1_display[] = {
 	// VBlank only
 	{
@@ -179,7 +177,7 @@ bool pmo_dcn42_init_for_pstate_support(struct dml2_pmo_init_for_pstate_support_i
 
 	// Figure out which streams can do vactive, and also build up implicit SVP and FAMS2 meta
 	for (stream_index = 0; stream_index < display_config->display_config.num_streams; stream_index++) {
-		if (dcn4_get_vactive_pstate_margin(display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) >= (int)(MIN_VACTIVE_MARGIN_PCT * pmo->soc_bb->power_management_parameters.dram_clk_change_blackout_us))
+		if (dcn4_get_vactive_pstate_margin(display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) >= 0)
 			dcn42_set_bit_in_bitfield(&s->pmo_dcn4.stream_vactive_capability_mask, stream_index);
 	}
 
@@ -259,27 +257,17 @@ bool pmo_dcn42_fams2_optimize_for_pstate_support(struct dml2_pmo_optimize_for_ps
 
 bool pmo_dcn42_test_for_pstate_support(struct dml2_pmo_test_for_pstate_support_in_out *in_out)
 {
-	const struct dml2_pmo_scratch *s = &in_out->instance->scratch;
-	bool p_state_supported = true;
-	unsigned int stream_index;
-
-	if (s->pmo_dcn4.cur_pstate_candidate < 0)
+	/* Return false on the initial candidate (cur_pstate_candidate == -1) so the
+	 * optimization phase runs at least one optimize iteration; otherwise the
+	 * FAMS2/stage-3 setup in the optimize callback is skipped.
+	 */
+	if (in_out->instance->scratch.pmo_dcn4.cur_pstate_candidate < 0)
 		return false;
 
-	for (stream_index = 0; stream_index < in_out->base_display_config->display_config.num_streams; stream_index++) {
-		if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_vactive) {
-			if (dcn4_get_minimum_reserved_time_us_for_planes(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < (int)in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us ||
-			    dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < (int)(MIN_VACTIVE_MARGIN_PCT * in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us)) {
-				p_state_supported = false;
-				break;
-			}
-		} else {
-			p_state_supported = false;
-			break;
-		}
-	}
-
-	return p_state_supported;
+	/* No-op: reserved time is guaranteed by the override and vactive p-state
+	 * margin is now enforced in core mode support.
+	 */
+	return true;
 }
 
 bool pmo_dcn42_initialize(struct dml2_pmo_initialize_in_out *in_out)
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.