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;
}
{
struct dml2_pmo_scratch *scratch = &pmo->scratch;
- bool fams2_required = false;
bool success = true;
unsigned int 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_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)
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);
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;
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,
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 */
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,
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);
}
}
/* 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);
}
}
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;
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;
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
/* 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,
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)
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);
}
}
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);
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
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;