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 4e0d757388ca..790aef95caa6 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 5db7877bb8ca..5b11c47874bb 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 8301e23ab89f..d5f20c85006e 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 f0afa8002a2f..7828fe5a4232 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 a1164de13a05..21109a19f177 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;