mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-27 16:49:22 -04:00
drm/amd/display: Enable DCN42 PMO policy
[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 <Dillon.Varone@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Ivan Lipski <ivan.lipski@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
6f6483dbfa
commit
2332eaeb0b
@@ -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 &&
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user