From: Dmytro Laktyushkin Date: Tue, 12 May 2026 17:15:13 +0000 (-0400) Subject: drm/amd/display: Add DCN42 PMO init_for_pstate_support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16e3e5aaa9a57a0f29f46f6663ca8c9cc8ee0bcc;p=thirdparty%2Flinux.git drm/amd/display: Add DCN42 PMO init_for_pstate_support [Why & How] Add pmo_dcn42_init_for_pstate_support mirroring the DCN4 FAMS2 version, but dropping the meta build for scheduling check that is unnecessary and skipping the cofunctionality check. This solves vrr validation issues in multidisplay configs. Reviewed-by: Dillon Varone Signed-off-by: Dmytro Laktyushkin Signed-off-by: Ray Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- 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 4e0d757388ca5..790aef95caa60 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 @@ -63,25 +63,24 @@ static bool is_bit_set_in_bitfield(unsigned int bit_field, unsigned int bit_offs return false; } +static void dcn42_set_bit_in_bitfield(unsigned int *bit_field, unsigned int bit_offset) +{ + *bit_field = *bit_field | (0x1 << bit_offset); +} + static void setup_planes_for_vactive_by_mask(struct display_configuation_with_meta *display_config, struct dml2_pmo_instance *pmo, int plane_mask) { unsigned int plane_index; - unsigned int stream_index; struct dml2_plane_parameters *plane; for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) { if (is_bit_set_in_bitfield(plane_mask, plane_index)) { plane = &display_config->display_config.plane_descriptors[plane_index]; - stream_index = display_config->display_config.plane_descriptors[plane_index].stream_index; plane->overrides.reserved_vblank_time_ns = (long)math_max2(pmo->soc_bb->power_management_parameters.dram_clk_change_blackout_us * 1000.0, plane->overrides.reserved_vblank_time_ns); - if (!pmo->options->disable_vactive_det_fill_bw_pad) { - display_config->display_config.plane_descriptors[plane_index].overrides.max_vactive_det_fill_delay_us[dml2_pstate_type_uclk] = - (unsigned int)math_floor(pmo->scratch.pmo_dcn4.stream_pstate_meta[stream_index].method_vactive.max_vactive_det_fill_delay_us); - } display_config->stage3.pstate_switch_modes[plane_index] = dml2_pstate_method_vactive; } @@ -118,7 +117,6 @@ static bool setup_display_config(struct display_configuation_with_meta *display_ { struct dml2_pmo_scratch *scratch = &pmo->scratch; - bool fams2_required = false; bool success = true; unsigned int stream_index; @@ -134,15 +132,96 @@ static bool setup_display_config(struct display_configuation_with_meta *display_ } } - /* copy FAMS2 meta */ - if (success) { - display_config->stage3.fams2_required = fams2_required; - memcpy(&display_config->stage3.stream_pstate_meta, - &scratch->pmo_dcn4.stream_pstate_meta, - sizeof(struct dml2_pstate_meta) * DML2_MAX_PLANES); + return success; +} + +bool pmo_dcn42_init_for_pstate_support(struct dml2_pmo_init_for_pstate_support_in_out *in_out) +{ + struct dml2_pmo_instance *pmo = in_out->instance; + struct dml2_optimization_stage3_state *state = &in_out->base_display_config->stage3; + struct dml2_pmo_scratch *s = &pmo->scratch; + + struct display_configuation_with_meta *display_config; + const struct dml2_plane_parameters *plane_descriptor; + const struct dml2_pmo_pstate_strategy *strategy_list = NULL; + struct dml2_pmo_pstate_strategy override_base_strategy = { 0 }; + unsigned int strategy_list_size = 0; + unsigned int plane_index, stream_index, i; + bool build_override_strategy = true; + + state->performed = true; + in_out->base_display_config->stage3.min_clk_index_for_latency = in_out->base_display_config->stage1.min_clk_index_for_latency; + + display_config = in_out->base_display_config; + display_config->display_config.overrides.enable_subvp_implicit_pmo = true; + + memset(s, 0, sizeof(struct dml2_pmo_scratch)); + + if (display_config->display_config.num_streams == 0) + return false; + + pmo->scratch.pmo_dcn4.min_latency_index = in_out->base_display_config->stage1.min_clk_index_for_latency; + pmo->scratch.pmo_dcn4.max_latency_index = pmo->mcg_clock_table_size; + pmo->scratch.pmo_dcn4.cur_latency_index = in_out->base_display_config->stage1.min_clk_index_for_latency; + + // First build the stream plane mask (array of bitfields indexed by stream, indicating plane mapping) + for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) { + plane_descriptor = &display_config->display_config.plane_descriptors[plane_index]; + + dcn42_set_bit_in_bitfield(&s->pmo_dcn4.stream_plane_mask[plane_descriptor->stream_index], plane_index); + + state->pstate_switch_modes[plane_index] = dml2_pstate_method_vactive; + + build_override_strategy &= plane_descriptor->overrides.uclk_pstate_change_strategy != dml2_uclk_pstate_change_strategy_auto; + override_base_strategy.per_stream_pstate_method[plane_descriptor->stream_index] = + dcn4_uclk_pstate_strategy_override_to_pstate_method(plane_descriptor->overrides.uclk_pstate_change_strategy); } - return success; + // 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)) + dcn42_set_bit_in_bitfield(&s->pmo_dcn4.stream_vactive_capability_mask, stream_index); + } + + if (build_override_strategy) { + /* build expanded override strategy list (no permutations) */ + override_base_strategy.allow_state_increase = true; + s->pmo_dcn4.num_expanded_override_strategies = 0; + dcn4_insert_strategy_into_expanded_list(&override_base_strategy, + display_config->display_config.num_streams, + s->pmo_dcn4.expanded_override_strategy_list, + &s->pmo_dcn4.num_expanded_override_strategies); + dcn4_expand_variant_strategy(&override_base_strategy, + display_config->display_config.num_streams, + false, + s->pmo_dcn4.expanded_override_strategy_list, + &s->pmo_dcn4.num_expanded_override_strategies); + + /* use override strategy list */ + strategy_list = s->pmo_dcn4.expanded_override_strategy_list; + strategy_list_size = s->pmo_dcn4.num_expanded_override_strategies; + } else { + /* use predefined strategy list */ + strategy_list = dcn4_get_expanded_strategy_list(&pmo->init_data, display_config->display_config.num_streams); + strategy_list_size = dcn4_get_num_expanded_strategies(&pmo->init_data, display_config->display_config.num_streams); + } + + if (!strategy_list || strategy_list_size == 0) + return false; + + s->pmo_dcn4.num_pstate_candidates = 0; + + for (i = 0; i < strategy_list_size && s->pmo_dcn4.num_pstate_candidates < DML2_PMO_PSTATE_CANDIDATE_LIST_SIZE; i++) { + dcn4_insert_into_candidate_list(&strategy_list[i], display_config->display_config.num_streams, s); + } + + if (s->pmo_dcn4.num_pstate_candidates > 0) { + s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.num_pstate_candidates-1].allow_state_increase = true; + s->pmo_dcn4.cur_pstate_candidate = -1; + return true; + } else { + return false; + } } bool pmo_dcn42_fams2_optimize_for_pstate_support(struct dml2_pmo_optimize_for_pstate_support_in_out *in_out) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.h index 5db7877bb8ca9..5b11c47874bbe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.h @@ -12,6 +12,7 @@ struct dml2_pmo_initialize_in_out; struct dml2_pmo_test_for_pstate_support_in_out; bool pmo_dcn42_initialize(struct dml2_pmo_initialize_in_out *in_out); +bool pmo_dcn42_init_for_pstate_support(struct dml2_pmo_init_for_pstate_support_in_out *in_out); bool pmo_dcn42_fams2_optimize_for_pstate_support(struct dml2_pmo_optimize_for_pstate_support_in_out *in_out); bool pmo_dcn42_test_for_pstate_support(struct dml2_pmo_test_for_pstate_support_in_out *in_out); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c index 8301e23ab89f5..d5f20c85006e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c @@ -391,7 +391,7 @@ static enum dml2_pstate_method convert_strategy_to_drr_variant(const enum dml2_p return variant_strategy; } -static struct dml2_pmo_pstate_strategy *get_expanded_strategy_list(struct dml2_pmo_init_data *init_data, int stream_count) +struct dml2_pmo_pstate_strategy *dcn4_get_expanded_strategy_list(struct dml2_pmo_init_data *init_data, int stream_count) { struct dml2_pmo_pstate_strategy *expanded_strategy_list = NULL; @@ -415,14 +415,14 @@ static struct dml2_pmo_pstate_strategy *get_expanded_strategy_list(struct dml2_p return expanded_strategy_list; } -static unsigned int get_num_expanded_strategies( +unsigned int dcn4_get_num_expanded_strategies( struct dml2_pmo_init_data *init_data, int stream_count) { return init_data->pmo_dcn4.num_expanded_strategies_per_list[stream_count - 1]; } -static void insert_strategy_into_expanded_list( +void dcn4_insert_strategy_into_expanded_list( const struct dml2_pmo_pstate_strategy *per_stream_pstate_strategy, const int stream_count, struct dml2_pmo_pstate_strategy *expanded_strategy_list, @@ -478,7 +478,7 @@ static void expand_base_strategy( if (i >= stream_count - 1) { /* insert into strategy list */ - insert_strategy_into_expanded_list(&cur_strategy_list, stream_count, expanded_strategy_list, num_expanded_strategies); + dcn4_insert_strategy_into_expanded_list(&cur_strategy_list, stream_count, expanded_strategy_list, num_expanded_strategies); expanded_strategy_added = true; } else { /* skip to next stream */ @@ -539,7 +539,7 @@ static bool is_variant_method_valid(const struct dml2_pmo_pstate_strategy *base_ return valid; } -static void expand_variant_strategy( +void dcn4_expand_variant_strategy( const struct dml2_pmo_pstate_strategy *base_strategy, const unsigned int stream_count, const bool should_permute, @@ -599,7 +599,7 @@ static void expand_variant_strategy( expand_base_strategy(&variant_strategy, stream_count, expanded_strategy_list, num_expanded_strategies); } else { /* no permutations allowed, so add to list now */ - insert_strategy_into_expanded_list(&variant_strategy, stream_count, expanded_strategy_list, num_expanded_strategies); + dcn4_insert_strategy_into_expanded_list(&variant_strategy, stream_count, expanded_strategy_list, num_expanded_strategies); } } @@ -639,7 +639,7 @@ void pmo_dcn4_fams2_expand_base_pstate_strategies( /* expand every explicit base strategy (except all DRR) */ for (i = 0; i < num_base_strategies; i++) { expand_base_strategy(&base_strategies_list[i], stream_count, expanded_strategy_list, num_expanded_strategies); - expand_variant_strategy(&base_strategies_list[i], stream_count, true, expanded_strategy_list, num_expanded_strategies); + dcn4_expand_variant_strategy(&base_strategies_list[i], stream_count, true, expanded_strategy_list, num_expanded_strategies); } } @@ -1180,14 +1180,14 @@ static bool all_timings_support_svp(const struct dml2_pmo_instance *pmo, return true; } -static void insert_into_candidate_list(const struct dml2_pmo_pstate_strategy *pstate_strategy, int stream_count, struct dml2_pmo_scratch *scratch) +void dcn4_insert_into_candidate_list(const struct dml2_pmo_pstate_strategy *pstate_strategy, int stream_count, struct dml2_pmo_scratch *scratch) { (void)stream_count; scratch->pmo_dcn4.pstate_strategy_candidates[scratch->pmo_dcn4.num_pstate_candidates] = *pstate_strategy; scratch->pmo_dcn4.num_pstate_candidates++; } -static enum dml2_pstate_method uclk_pstate_strategy_override_to_pstate_method(const enum dml2_uclk_pstate_change_strategy override_strategy) +enum dml2_pstate_method dcn4_uclk_pstate_strategy_override_to_pstate_method(const enum dml2_uclk_pstate_change_strategy override_strategy) { enum dml2_pstate_method method = dml2_pstate_method_na; @@ -1884,6 +1884,10 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp memset(s, 0, sizeof(struct dml2_pmo_scratch)); + if (display_config->display_config.overrides.all_streams_blanked) { + return true; + } + pmo->scratch.pmo_dcn4.min_latency_index = in_out->base_display_config->stage1.min_clk_index_for_latency; pmo->scratch.pmo_dcn4.max_latency_index = pmo->mcg_clock_table_size; pmo->scratch.pmo_dcn4.cur_latency_index = in_out->base_display_config->stage1.min_clk_index_for_latency; @@ -1898,7 +1902,7 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp build_override_strategy &= plane_descriptor->overrides.uclk_pstate_change_strategy != dml2_uclk_pstate_change_strategy_auto; override_base_strategy.per_stream_pstate_method[plane_descriptor->stream_index] = - uclk_pstate_strategy_override_to_pstate_method(plane_descriptor->overrides.uclk_pstate_change_strategy); + dcn4_uclk_pstate_strategy_override_to_pstate_method(plane_descriptor->overrides.uclk_pstate_change_strategy); } // Figure out which streams can do vactive, and also build up implicit SVP and FAMS2 meta @@ -1920,11 +1924,11 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp /* build expanded override strategy list (no permutations) */ override_base_strategy.allow_state_increase = true; s->pmo_dcn4.num_expanded_override_strategies = 0; - insert_strategy_into_expanded_list(&override_base_strategy, + dcn4_insert_strategy_into_expanded_list(&override_base_strategy, display_config->display_config.num_streams, s->pmo_dcn4.expanded_override_strategy_list, &s->pmo_dcn4.num_expanded_override_strategies); - expand_variant_strategy(&override_base_strategy, + dcn4_expand_variant_strategy(&override_base_strategy, display_config->display_config.num_streams, false, s->pmo_dcn4.expanded_override_strategy_list, @@ -1935,8 +1939,8 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp strategy_list_size = s->pmo_dcn4.num_expanded_override_strategies; } else { /* use predefined strategy list */ - strategy_list = get_expanded_strategy_list(&pmo->init_data, display_config->display_config.num_streams); - strategy_list_size = get_num_expanded_strategies(&pmo->init_data, display_config->display_config.num_streams); + strategy_list = dcn4_get_expanded_strategy_list(&pmo->init_data, display_config->display_config.num_streams); + strategy_list_size = dcn4_get_num_expanded_strategies(&pmo->init_data, display_config->display_config.num_streams); } if (!strategy_list || strategy_list_size == 0) @@ -1946,7 +1950,7 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp for (i = 0; i < strategy_list_size && s->pmo_dcn4.num_pstate_candidates < DML2_PMO_PSTATE_CANDIDATE_LIST_SIZE; i++) { if (validate_pstate_support_strategy_cofunctionality(pmo, display_config, &strategy_list[i])) { - insert_into_candidate_list(&strategy_list[i], display_config->display_config.num_streams, s); + dcn4_insert_into_candidate_list(&strategy_list[i], display_config->display_config.num_streams, s); } } diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.h index f0afa8002a2f3..7828fe5a42327 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.h @@ -9,14 +9,6 @@ struct display_configuation_with_meta; -int dcn4_get_vactive_pstate_margin( - const struct display_configuation_with_meta *display_cfg, - int plane_mask); - -int dcn4_get_minimum_reserved_time_us_for_planes( - const struct display_configuation_with_meta *display_config, - int plane_mask); - bool pmo_dcn4_fams2_initialize(struct dml2_pmo_initialize_in_out *in_out); bool pmo_dcn4_fams2_optimize_dcc_mcache(struct dml2_pmo_optimize_dcc_mcache_in_out *in_out); @@ -40,4 +32,42 @@ void pmo_dcn4_fams2_expand_base_pstate_strategies( struct dml2_pmo_pstate_strategy *expanded_strategy_list, unsigned int *num_expanded_strategies); +/* Helpers shared with derived PMO implementations (e.g. DCN42). */ +int dcn4_get_vactive_pstate_margin( + const struct display_configuation_with_meta *display_cfg, + int plane_mask); + +int dcn4_get_minimum_reserved_time_us_for_planes( + const struct display_configuation_with_meta *display_config, + int plane_mask); + +enum dml2_pstate_method dcn4_uclk_pstate_strategy_override_to_pstate_method( + const enum dml2_uclk_pstate_change_strategy override_strategy); + +struct dml2_pmo_pstate_strategy *dcn4_get_expanded_strategy_list( + struct dml2_pmo_init_data *init_data, + int stream_count); + +unsigned int dcn4_get_num_expanded_strategies( + struct dml2_pmo_init_data *init_data, + int stream_count); + +void dcn4_insert_strategy_into_expanded_list( + const struct dml2_pmo_pstate_strategy *per_stream_pstate_strategy, + const int stream_count, + struct dml2_pmo_pstate_strategy *expanded_strategy_list, + unsigned int *num_expanded_strategies); + +void dcn4_expand_variant_strategy( + const struct dml2_pmo_pstate_strategy *base_strategy, + const unsigned int stream_count, + const bool should_permute, + struct dml2_pmo_pstate_strategy *expanded_strategy_list, + unsigned int *num_expanded_strategies); + +void dcn4_insert_into_candidate_list( + const struct dml2_pmo_pstate_strategy *pstate_strategy, + int stream_count, + struct dml2_pmo_scratch *scratch); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c index a1164de13a054..21109a19f177f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c @@ -67,7 +67,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * out->test_for_vmin = pmo_dcn4_fams2_test_for_vmin; out->optimize_for_vmin = pmo_dcn4_fams2_optimize_for_vmin; - out->init_for_uclk_pstate = pmo_dcn4_fams2_init_for_pstate_support; + out->init_for_uclk_pstate = pmo_dcn42_init_for_pstate_support; out->test_for_uclk_pstate = pmo_dcn42_test_for_pstate_support; out->optimize_for_uclk_pstate = pmo_dcn42_fams2_optimize_for_pstate_support;