From: Nicholas Kazlauskas <[email protected]> [Why] The MinTTU policy in DML2.1 does not guarantee that we support p-state in blank. This is a delta vs dml2 and earlier revisions as the prefetch mode override has been removed in favor of a more configurable pstate optimizer.
[How] The policy has been added in a prior patch, this patch enables it based on pmo flag. Reviewed-by: Dillon Varone <[email protected]> Signed-off-by: Nicholas Kazlauskas <[email protected]> Signed-off-by: Ivan Lipski <[email protected]> --- .../dml2_0/dml21/dml21_translation_helper.c | 5 +- .../dc/dml2_0/dml21/inc/dml_top_types.h | 1 + .../dml21/src/dml2_pmo/dml2_pmo_dcn42.c | 144 ++++++++++++++++-- .../dml21/src/dml2_pmo/dml2_pmo_dcn42.h | 1 + .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c | 4 - .../dml21/src/dml2_pmo/dml2_pmo_factory.c | 16 ++ .../dml21/src/dml2_top/dml2_top_soc15.c | 30 +++- .../drm/amd/display/dc/dml2_0/dml2_wrapper.h | 1 + 8 files changed, 184 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c index 25557c99a28e..f849fb882b2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c @@ -36,6 +36,8 @@ static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options, pmo_options->disable_drr_var_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE || in_dc->debug.disable_fams_gaming == INGAME_FAMS_MULTI_DISP_CLAMPED_ONLY; pmo_options->disable_drr_clamped_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE; + + pmo_options->force_mandatory_uclk_pstate_support = config->pmo.force_mandatory_uclk_pstate_support; } static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version) @@ -690,7 +692,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm plane->overrides.gpuvm_min_page_size_kbytes = soc_bb->gpuvm_min_page_size_kbytes; plane->overrides.hostvm_min_page_size_kbytes = soc_bb->hostvm_min_page_size_kbytes; - plane->immediate_flip = plane_state->flip_immediate; + //Always true for DAL, we want to validate the worst case scenario as we have to switch b/w the two without possibility of failure. + plane->immediate_flip = true; plane->composition.rect_out_height_spans_vactive = plane_state->dst_rect.height >= stream->src.height && diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h index dff903a103db..8d7960a340c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h @@ -71,6 +71,7 @@ struct dml2_pmo_options { bool disable_dyn_odm; bool disable_dyn_odm_for_multi_stream; bool disable_dyn_odm_for_stream_with_svp; + bool force_mandatory_uclk_pstate_support; struct dml2_pmo_pstate_strategy *override_strategy_lists[DML2_MAX_PLANES]; unsigned int num_override_strategies_per_list[DML2_MAX_PLANES]; }; 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 30fd5efe4b87..4e0d757388ca 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,10 +13,12 @@ * 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 { - .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na }, + .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na }, .allow_state_increase = true, }, }; @@ -26,7 +28,7 @@ static const int dcn42_strategy_list_1_display_size = sizeof(dcn42_strategy_list static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_2_display[] = { // VBlank only for both displays { - .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na }, + .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_na, dml2_pstate_method_na }, .allow_state_increase = true, }, }; @@ -36,7 +38,7 @@ static const int dcn42_strategy_list_2_display_size = sizeof(dcn42_strategy_list static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_3_display[] = { // VBlank only for all three displays { - .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_na }, + .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_na }, .allow_state_increase = true, }, }; @@ -46,31 +48,149 @@ static const int dcn42_strategy_list_3_display_size = sizeof(dcn42_strategy_list static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_4_display[] = { // VBlank only for all four displays { - .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank }, + .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive }, .allow_state_increase = true, }, }; static const int dcn42_strategy_list_4_display_size = sizeof(dcn42_strategy_list_4_display) / sizeof(struct dml2_pmo_pstate_strategy); +static bool is_bit_set_in_bitfield(unsigned int bit_field, unsigned int bit_offset) +{ + if (bit_field & (0x1 << bit_offset)) + return true; + + return false; +} + +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; + } + } +} + +static void reset_display_configuration(struct display_configuation_with_meta *display_config) +{ + unsigned int plane_index; + unsigned int stream_index; + struct dml2_plane_parameters *plane; + + for (stream_index = 0; stream_index < display_config->display_config.num_streams; stream_index++) { + display_config->stage3.stream_svp_meta[stream_index].valid = false; + } + + for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) { + plane = &display_config->display_config.plane_descriptors[plane_index]; + + // Unset SubVP + plane->overrides.legacy_svp_config = dml2_svp_mode_override_auto; + + // Remove reserve time + plane->overrides.reserved_vblank_time_ns = 0; + + // Reset strategy to auto + plane->overrides.uclk_pstate_change_strategy = dml2_uclk_pstate_change_strategy_auto; + + display_config->stage3.pstate_switch_modes[plane_index] = dml2_pstate_method_na; + } +} + +static bool setup_display_config(struct display_configuation_with_meta *display_config, struct dml2_pmo_instance *pmo, int strategy_index) +{ + struct dml2_pmo_scratch *scratch = &pmo->scratch; + + bool fams2_required = false; + bool success = true; + unsigned int stream_index; + + reset_display_configuration(display_config); + + for (stream_index = 0; stream_index < display_config->display_config.num_streams; stream_index++) { + + if (pmo->scratch.pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_na) { + success = false; + break; + } else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_vactive) { + setup_planes_for_vactive_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]); + } + } + + /* 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_fams2_optimize_for_pstate_support(struct dml2_pmo_optimize_for_pstate_support_in_out *in_out) +{ + bool success = false; + struct dml2_pmo_scratch *s = &in_out->instance->scratch; + + memcpy(in_out->optimized_display_config, in_out->base_display_config, sizeof(struct display_configuation_with_meta)); + + if (in_out->last_candidate_failed) { + if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].allow_state_increase && + s->pmo_dcn4.cur_latency_index < s->pmo_dcn4.max_latency_index - 1) { + s->pmo_dcn4.cur_latency_index++; + + success = true; + } + } + + if (!success) { + s->pmo_dcn4.cur_latency_index = s->pmo_dcn4.min_latency_index; + s->pmo_dcn4.cur_pstate_candidate++; + + if (s->pmo_dcn4.cur_pstate_candidate < s->pmo_dcn4.num_pstate_candidates) { + success = true; + } + } + + if (success) { + in_out->optimized_display_config->stage3.min_clk_index_for_latency = s->pmo_dcn4.cur_latency_index; + setup_display_config(in_out->optimized_display_config, in_out->instance, in_out->instance->scratch.pmo_dcn4.cur_pstate_candidate); + } + + return success; +} + 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; - const int REQUIRED_RESERVED_TIME = - (int)in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us; bool p_state_supported = true; unsigned int stream_index; - if (in_out->base_display_config->display_config.overrides.all_streams_blanked) - return true; - if (s->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_vblank) { - if (dcn4_get_minimum_reserved_time_us_for_planes(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < REQUIRED_RESERVED_TIME || - dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) > 0) { + 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; } 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 31ba8575351d..5db7877bb8ca 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_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); #endif /* __DML2_PMO_DCN42_H__ */ 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 b348c65a0f75..8301e23ab89f 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 @@ -1884,10 +1884,6 @@ 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; 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 af2ba7d08a61..a1164de13a05 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 @@ -5,6 +5,7 @@ #include "dml2_pmo_factory.h" #include "dml2_pmo_dcn4_fams2.h" #include "dml2_pmo_dcn3.h" +#include "dml2_pmo_dcn42.h" #include "dml2_external_lib_deps.h" static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out) @@ -60,6 +61,21 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * result = true; break; case dml2_project_dcn42: + out->initialize = pmo_dcn42_initialize; + + out->init_for_vmin = pmo_dcn4_fams2_init_for_vmin; + 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->test_for_uclk_pstate = pmo_dcn42_test_for_pstate_support; + out->optimize_for_uclk_pstate = pmo_dcn42_fams2_optimize_for_pstate_support; + + out->init_for_stutter = pmo_dcn4_fams2_init_for_stutter; + out->test_for_stutter = pmo_dcn4_fams2_test_for_stutter; + out->optimize_for_stutter = pmo_dcn4_fams2_optimize_for_stutter; + result = true; + break; case dml2_project_dcn4x_stage2_auto_drr_svp: out->initialize = pmo_dcn4_fams2_initialize; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.c index fa20a91c6e16..e6c49c27035c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.c @@ -782,6 +782,7 @@ static bool dml2_top_soc15_check_mode_supported(struct dml2_check_mode_supported bool result = false; bool mcache_success = false; + bool uclk_pstate_success = false; memset(dpmm_programming, 0, sizeof(struct dml2_display_cfg_programming)); setup_unoptimized_display_config_with_meta(dml, &l->base_display_config_with_meta, in_out->display_config); @@ -805,6 +806,24 @@ static bool dml2_top_soc15_check_mode_supported(struct dml2_check_mode_supported mcache_success = dml2_top_optimization_perform_optimization_phase(&l->optimization_phase_locals, &mcache_phase); } + if (result) { + if (dml->pmo_options.force_mandatory_uclk_pstate_support) { + struct optimization_phase_params uclk_phase = { + .dml = dml, + .display_config = &l->base_display_config_with_meta, + .init_function = dml2_top_optimization_init_function_uclk_pstate, + .test_function = dml2_top_optimization_test_function_uclk_pstate, + .optimize_function = dml2_top_optimization_optimize_function_uclk_pstate, + .optimized_display_config = &l->optimized_display_config_with_meta, + .all_or_nothing = false, + }; + + uclk_pstate_success = dml2_top_optimization_perform_optimization_phase(&l->optimization_phase_locals, &uclk_phase); + } else { + uclk_pstate_success = true; + } + } + /* * Call DPMM to map all requirements to minimum clock state */ @@ -817,7 +836,7 @@ static bool dml2_top_soc15_check_mode_supported(struct dml2_check_mode_supported result = dml->dpmm_instance.map_mode_to_soc_dpm(&l->dppm_map_mode_params); } - in_out->is_supported = mcache_success; + in_out->is_supported = mcache_success & uclk_pstate_success; result = result && in_out->is_supported; return result; @@ -928,6 +947,15 @@ static bool dml2_top_soc15_build_mode_programming(struct dml2_build_mode_program if (uclk_pstate_success) { memcpy(&l->base_display_config_with_meta, &l->optimized_display_config_with_meta, sizeof(struct display_configuation_with_meta)); l->base_display_config_with_meta.stage3.success = true; + } else if (dml->pmo_options.force_mandatory_uclk_pstate_support) { + l->informative_params.instance = &dml->core_instance; + l->informative_params.programming = in_out->programming; + l->informative_params.mode_is_supported = false; + + dml->core_instance.populate_informative(&l->informative_params); + + in_out->programming->informative.failed_mcache_validation = true; + return false; } /* diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h index 5ee489682f2e..2f2ae05dd59c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h @@ -232,6 +232,7 @@ struct dml2_configuration_options { /* Only for debugging purposes when initializing SOCBB params via tool for DML21. */ struct socbb_ip_params_external *external_socbb_ip_params; struct { + bool force_mandatory_uclk_pstate_support; bool force_pstate_method_enable; enum dml2_force_pstate_methods force_pstate_method_values[MAX_PIPES]; } pmo; -- 2.43.0
