brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · c4c5217 Raw
311 lines · c
1/* SPDX-License-Identifier: MIT */2/*3 * Copyright 2023 Advanced Micro Devices, Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21 * OTHER DEALINGS IN THE SOFTWARE.22 *23 * Authors: AMD24 *25 */26 27#include "dml2_policy.h"28 29static void get_optimal_ntuple(30	const struct soc_bounding_box_st *socbb,31	struct soc_state_bounding_box_st *entry)32{33	if (entry->dcfclk_mhz > 0) {34		float bw_on_sdp = (float)(entry->dcfclk_mhz * socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_sdp_bw_after_urgent / 100));35 36		entry->fabricclk_mhz = bw_on_sdp / (socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_fabric_bw_after_urgent / 100));37		entry->dram_speed_mts = bw_on_sdp / (socbb->num_chans *38			socbb->dram_channel_width_bytes * ((float)socbb->pct_ideal_dram_bw_after_urgent_pixel_only / 100));39	} else if (entry->fabricclk_mhz > 0) {40		float bw_on_fabric = (float)(entry->fabricclk_mhz * socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_fabric_bw_after_urgent / 100));41 42		entry->dcfclk_mhz = bw_on_fabric / (socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_sdp_bw_after_urgent / 100));43		entry->dram_speed_mts = bw_on_fabric / (socbb->num_chans *44			socbb->dram_channel_width_bytes * ((float)socbb->pct_ideal_dram_bw_after_urgent_pixel_only / 100));45	} else if (entry->dram_speed_mts > 0) {46		float bw_on_dram = (float)(entry->dram_speed_mts * socbb->num_chans *47			socbb->dram_channel_width_bytes * ((float)socbb->pct_ideal_dram_bw_after_urgent_pixel_only / 100));48 49		entry->fabricclk_mhz = bw_on_dram / (socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_fabric_bw_after_urgent / 100));50		entry->dcfclk_mhz = bw_on_dram / (socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_sdp_bw_after_urgent / 100));51	}52}53 54static float calculate_net_bw_in_mbytes_sec(const struct soc_bounding_box_st *socbb,55	struct soc_state_bounding_box_st *entry)56{57	float memory_bw_mbytes_sec = (float)(entry->dram_speed_mts *  socbb->num_chans *58		socbb->dram_channel_width_bytes * ((float)socbb->pct_ideal_dram_bw_after_urgent_pixel_only / 100));59 60	float fabric_bw_mbytes_sec = (float)(entry->fabricclk_mhz * socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_fabric_bw_after_urgent / 100));61 62	float sdp_bw_mbytes_sec = (float)(entry->dcfclk_mhz * socbb->return_bus_width_bytes * ((float)socbb->pct_ideal_sdp_bw_after_urgent / 100));63 64	float limiting_bw_mbytes_sec = memory_bw_mbytes_sec;65 66	if (fabric_bw_mbytes_sec < limiting_bw_mbytes_sec)67		limiting_bw_mbytes_sec = fabric_bw_mbytes_sec;68 69	if (sdp_bw_mbytes_sec < limiting_bw_mbytes_sec)70		limiting_bw_mbytes_sec = sdp_bw_mbytes_sec;71 72	return limiting_bw_mbytes_sec;73}74 75static void insert_entry_into_table_sorted(const struct soc_bounding_box_st *socbb,76	struct soc_states_st *table,77	struct soc_state_bounding_box_st *entry)78{79	int index = 0;80	int i = 0;81	float net_bw_of_new_state = 0;82 83	get_optimal_ntuple(socbb, entry);84 85	if (table->num_states == 0) {86		index = 0;87	} else {88		net_bw_of_new_state = calculate_net_bw_in_mbytes_sec(socbb, entry);89		while (net_bw_of_new_state > calculate_net_bw_in_mbytes_sec(socbb, &table->state_array[index])) {90			index++;91			if (index >= (int) table->num_states)92				break;93		}94 95		for (i = table->num_states; i > index; i--) {96			table->state_array[i] = table->state_array[i - 1];97		}98		//ASSERT(index < MAX_CLK_TABLE_SIZE);99	}100 101	table->state_array[index] = *entry;102	table->state_array[index].dcfclk_mhz = (int)entry->dcfclk_mhz;103	table->state_array[index].fabricclk_mhz = (int)entry->fabricclk_mhz;104	table->state_array[index].dram_speed_mts = (int)entry->dram_speed_mts;105	table->num_states++;106}107 108static void remove_entry_from_table_at_index(struct soc_states_st *table,109	unsigned int index)110{111	int i;112 113	if (table->num_states == 0)114		return;115 116	for (i = index; i < (int) table->num_states - 1; i++) {117		table->state_array[i] = table->state_array[i + 1];118	}119	memset(&table->state_array[--table->num_states], 0, sizeof(struct soc_state_bounding_box_st));120}121 122int dml2_policy_build_synthetic_soc_states(struct dml2_policy_build_synthetic_soc_states_scratch *s,123	struct dml2_policy_build_synthetic_soc_states_params *p)124{125	int i, j;126	unsigned int min_fclk_mhz = p->in_states->state_array[0].fabricclk_mhz;127	unsigned int min_dcfclk_mhz = p->in_states->state_array[0].dcfclk_mhz;128	unsigned int min_socclk_mhz = p->in_states->state_array[0].socclk_mhz;129 130	int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,131		max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0,132		max_uclk_mhz = 0, max_socclk_mhz = 0;133 134	int num_uclk_dpms = 0, num_fclk_dpms = 0;135 136	for (i = 0; i < __DML_MAX_STATE_ARRAY_SIZE__; i++) {137		if (p->in_states->state_array[i].dcfclk_mhz > max_dcfclk_mhz)138			max_dcfclk_mhz = (int) p->in_states->state_array[i].dcfclk_mhz;139		if (p->in_states->state_array[i].fabricclk_mhz > max_fclk_mhz)140			max_fclk_mhz = (int) p->in_states->state_array[i].fabricclk_mhz;141		if (p->in_states->state_array[i].socclk_mhz > max_socclk_mhz)142			max_socclk_mhz = (int) p->in_states->state_array[i].socclk_mhz;143		if (p->in_states->state_array[i].dram_speed_mts > max_uclk_mhz)144			max_uclk_mhz = (int) p->in_states->state_array[i].dram_speed_mts;145		if (p->in_states->state_array[i].dispclk_mhz > max_dispclk_mhz)146			max_dispclk_mhz = (int) p->in_states->state_array[i].dispclk_mhz;147		if (p->in_states->state_array[i].dppclk_mhz > max_dppclk_mhz)148			max_dppclk_mhz = (int) p->in_states->state_array[i].dppclk_mhz;149		if (p->in_states->state_array[i].phyclk_mhz > max_phyclk_mhz)150			max_phyclk_mhz = (int)p->in_states->state_array[i].phyclk_mhz;151		if (p->in_states->state_array[i].dtbclk_mhz > max_dtbclk_mhz)152			max_dtbclk_mhz = (int)p->in_states->state_array[i].dtbclk_mhz;153 154		if (p->in_states->state_array[i].fabricclk_mhz > 0)155			num_fclk_dpms++;156		if (p->in_states->state_array[i].dram_speed_mts > 0)157			num_uclk_dpms++;158	}159 160	if (!max_dcfclk_mhz || !max_dispclk_mhz || !max_dppclk_mhz || !max_phyclk_mhz || !max_dtbclk_mhz)161		return -1;162 163	p->out_states->num_states = 0;164 165	s->entry = p->in_states->state_array[0];166 167	s->entry.dispclk_mhz = max_dispclk_mhz;168	s->entry.dppclk_mhz = max_dppclk_mhz;169	s->entry.dtbclk_mhz = max_dtbclk_mhz;170	s->entry.phyclk_mhz = max_phyclk_mhz;171 172	s->entry.dscclk_mhz = max_dispclk_mhz / 3;173	s->entry.phyclk_mhz = max_phyclk_mhz;174	s->entry.dtbclk_mhz = max_dtbclk_mhz;175 176	// Insert all the DCFCLK STAs first177	for (i = 0; i < p->num_dcfclk_stas; i++) {178		s->entry.dcfclk_mhz = p->dcfclk_stas_mhz[i];179		s->entry.fabricclk_mhz = 0;180		s->entry.dram_speed_mts = 0;181		if (i > 0)182			s->entry.socclk_mhz = max_socclk_mhz;183 184		insert_entry_into_table_sorted(p->in_bbox, p->out_states, &s->entry);185	}186 187	// Insert the UCLK DPMS188	for (i = 0; i < num_uclk_dpms; i++) {189		s->entry.dcfclk_mhz = 0;190		s->entry.fabricclk_mhz = 0;191		s->entry.dram_speed_mts = p->in_states->state_array[i].dram_speed_mts;192		if (i == 0) {193			s->entry.socclk_mhz = min_socclk_mhz;194		} else {195			s->entry.socclk_mhz = max_socclk_mhz;196		}197 198		insert_entry_into_table_sorted(p->in_bbox, p->out_states, &s->entry);199	}200 201	// Insert FCLK DPMs (if present)202	if (num_fclk_dpms > 2) {203		for (i = 0; i < num_fclk_dpms; i++) {204			s->entry.dcfclk_mhz = 0;205			s->entry.fabricclk_mhz = p->in_states->state_array[i].fabricclk_mhz;206			s->entry.dram_speed_mts = 0;207 208		insert_entry_into_table_sorted(p->in_bbox, p->out_states, &s->entry);209		}210	}211	// Add max FCLK212	else {213		s->entry.dcfclk_mhz = 0;214		s->entry.fabricclk_mhz = p->in_states->state_array[num_fclk_dpms - 1].fabricclk_mhz;215		s->entry.dram_speed_mts = 0;216 217		insert_entry_into_table_sorted(p->in_bbox, p->out_states, &s->entry);218	}219 220	// Remove states that require higher clocks than are supported221	for (i = p->out_states->num_states - 1; i >= 0; i--) {222		if (p->out_states->state_array[i].dcfclk_mhz > max_dcfclk_mhz ||223			p->out_states->state_array[i].fabricclk_mhz > max_fclk_mhz ||224			p->out_states->state_array[i].dram_speed_mts > max_uclk_mhz)225			remove_entry_from_table_at_index(p->out_states, i);226	}227 228	// At this point, the table contains all "points of interest" based on229	// DPMs from PMFW, and STAs. Table is sorted by BW, and all clock230	// ratios (by derate, are exact).231 232	// Round up UCLK to DPMs233	for (i = p->out_states->num_states - 1; i >= 0; i--) {234		for (j = 0; j < num_uclk_dpms; j++) {235			if (p->in_states->state_array[j].dram_speed_mts >= p->out_states->state_array[i].dram_speed_mts) {236				p->out_states->state_array[i].dram_speed_mts = p->in_states->state_array[j].dram_speed_mts;237				break;238			}239		}240	}241 242	// If FCLK is coarse grained, round up to next DPMs243	if (num_fclk_dpms > 2) {244		for (i = p->out_states->num_states - 1; i >= 0; i--) {245			for (j = 0; j < num_fclk_dpms; j++) {246				if (p->in_states->state_array[j].fabricclk_mhz >= p->out_states->state_array[i].fabricclk_mhz) {247					p->out_states->state_array[i].fabricclk_mhz = p->in_states->state_array[j].fabricclk_mhz;248					break;249				}250			}251		}252	}253 254	// Clamp to min FCLK/DCFCLK255	for (i = p->out_states->num_states - 1; i >= 0; i--) {256		if (p->out_states->state_array[i].fabricclk_mhz < min_fclk_mhz) {257			p->out_states->state_array[i].fabricclk_mhz = min_fclk_mhz;258		}259		if (p->out_states->state_array[i].dcfclk_mhz < min_dcfclk_mhz) {260			p->out_states->state_array[i].dcfclk_mhz = min_dcfclk_mhz;261		}262	}263 264	// Remove duplicate states, note duplicate states are always neighbouring since table is sorted.265	i = 0;266	while (i < (int) p->out_states->num_states - 1) {267		if (p->out_states->state_array[i].dcfclk_mhz == p->out_states->state_array[i + 1].dcfclk_mhz &&268			p->out_states->state_array[i].fabricclk_mhz == p->out_states->state_array[i + 1].fabricclk_mhz &&269			p->out_states->state_array[i].dram_speed_mts == p->out_states->state_array[i + 1].dram_speed_mts)270			remove_entry_from_table_at_index(p->out_states, i);271	else272		i++;273	}274 275	return 0;276}277 278void build_unoptimized_policy_settings(enum dml_project_id project, struct dml_mode_eval_policy_st *policy)279{280	for (int i = 0; i < __DML_NUM_PLANES__; i++) {281		policy->MPCCombineUse[i] = dml_mpc_as_needed_for_voltage; // TOREVIEW: Is this still needed?  When is MPCC useful for pstate given CRB?282		policy->ODMUse[i] = dml_odm_use_policy_combine_as_needed;283		policy->ImmediateFlipRequirement[i] = dml_immediate_flip_required;284		policy->AllowForPStateChangeOrStutterInVBlank[i] = dml_prefetch_support_uclk_fclk_and_stutter_if_possible;285	}286 287	/* Change the default policy initializations as per spreadsheet. We might need to288	 * review and change them later on as per Jun's earlier comments.289	 */290	policy->UseUnboundedRequesting = dml_unbounded_requesting_enable;291	policy->UseMinimumRequiredDCFCLK = false;292	policy->DRAMClockChangeRequirementFinal = true; // TOREVIEW: What does this mean?293	policy->FCLKChangeRequirementFinal = true; // TOREVIEW: What does this mean?294	policy->USRRetrainingRequiredFinal = true;295	policy->EnhancedPrefetchScheduleAccelerationFinal = true; // TOREVIEW: What does this mean?296	policy->NomDETInKByteOverrideEnable = false;297	policy->NomDETInKByteOverrideValue = 0;298	policy->DCCProgrammingAssumesScanDirectionUnknownFinal = true;299	policy->SynchronizeTimingsFinal = true;300	policy->SynchronizeDRRDisplaysForUCLKPStateChangeFinal = true;301	policy->AssumeModeSupportAtMaxPwrStateEvenDRAMClockChangeNotSupported = true; // TOREVIEW: What does this mean?302	policy->AssumeModeSupportAtMaxPwrStateEvenFClockChangeNotSupported = true; // TOREVIEW: What does this mean?303	if (project == dml_project_dcn35 ||304		project == dml_project_dcn351) {305		policy->DCCProgrammingAssumesScanDirectionUnknownFinal = false;306		policy->EnhancedPrefetchScheduleAccelerationFinal = 0;307		policy->AllowForPStateChangeOrStutterInVBlankFinal = dml_prefetch_support_uclk_fclk_and_stutter_if_possible; /*new*/308		policy->UseOnlyMaxPrefetchModes = 1;309	}310}311