drm/amd/display: plumb PMO per-plane pstate methods into mode_support

[Why]
mode_support reads mode_lib.ms.uclk_pstate_switch_modes to enforce the
vactive pstate margin, but nothing populates it: the memset clears it and
the PMO selection is never passed in. The check always sees na and never
runs, so a plane with negative vactive margin can still pass and blank the
display.

[How]
Add a const per-plane pstate-method pointer to mode_support_ex, point it at
stage3.pstate_switch_modes when stage 3 has run (NULL otherwise), and copy
it into mode_lib.ms after the memset. Scope the support-required check to
the vactive methods it governs (vactive, fw_vactive_drr) so SVP, DRR and
vblank planes are not rejected by the vactive support flag.

Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Signed-off-by: Alexander Chechik <alexander.chechik@amd.com>
Signed-off-by: Matthew Stewart <matthew.stewart2@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alexander Chechik
2026-06-23 23:50:56 -04:00
committed by Alex Deucher
parent fa0300333d
commit 9fcd9c7545
3 changed files with 17 additions and 11 deletions

View File

@@ -554,13 +554,9 @@ 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;
}
l->mode_support_ex_params.uclk_pstate_switch_modes =
in_out->display_cfg->stage3.performed ?
in_out->display_cfg->stage3.pstate_switch_modes : NULL;
result = dml2_core_calcs_mode_support_ex(&l->mode_support_ex_params);

View File

@@ -8057,6 +8057,16 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
memset(&mode_lib->ms, 0, sizeof(struct dml2_core_internal_mode_support));
mode_lib->ms.num_active_planes = display_cfg->num_planes;
for (k = 0; k < mode_lib->ms.num_active_planes; k++) {
if (in_out_params->uclk_pstate_switch_modes &&
!dml_is_phantom_pipe(&display_cfg->plane_descriptors[k]))
mode_lib->ms.uclk_pstate_switch_modes[k] =
in_out_params->uclk_pstate_switch_modes[k];
else
mode_lib->ms.uclk_pstate_switch_modes[k] = dml2_pstate_method_na;
}
get_stream_output_bpp(s->OutputBpp, display_cfg);
mode_lib->ms.state_idx = in_out_params->min_clk_index;
@@ -9644,14 +9654,13 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
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)
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)
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)
if (mode_lib->ms.VActiveLatencyHidingMargin[k] < 0)
mode_lib->ms.support.global_dram_clock_change_supported = false;
}
}

View File

@@ -2333,6 +2333,7 @@ struct dml2_core_calcs_mode_support_ex {
int min_clk_index;
//unsigned int in_state_index;
struct dml2_core_internal_mode_support_info *out_evaluation_info;
const enum dml2_pstate_method *uclk_pstate_switch_modes;
};
struct core_display_cfg_support_info;