Home | History | Annotate | Line # | Download | only in powerplay
      1 /*	$NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2019 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  */
     25 
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $");
     28 
     29 #include "pp_debug.h"
     30 #include <linux/firmware.h>
     31 #include "amdgpu.h"
     32 #include "amdgpu_smu.h"
     33 #include "smu_internal.h"
     34 #include "atomfirmware.h"
     35 #include "amdgpu_atomfirmware.h"
     36 #include "smu_v11_0.h"
     37 #include "smu11_driver_if.h"
     38 #include "soc15_common.h"
     39 #include "atom.h"
     40 #include "power_state.h"
     41 #include "vega20_ppt.h"
     42 #include "vega20_pptable.h"
     43 #include "vega20_ppsmc.h"
     44 #include "nbio/nbio_7_4_sh_mask.h"
     45 #include "asic_reg/thm/thm_11_0_2_offset.h"
     46 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
     47 
     48 #include <linux/nbsd-namespace.h>
     49 
     50 #define smnPCIE_LC_SPEED_CNTL			0x11140290
     51 #define smnPCIE_LC_LINK_WIDTH_CNTL		0x11140288
     52 
     53 #define CTF_OFFSET_EDGE			5
     54 #define CTF_OFFSET_HOTSPOT		5
     55 #define CTF_OFFSET_HBM			5
     56 
     57 #define MSG_MAP(msg) \
     58 	[SMU_MSG_##msg] = {1, PPSMC_MSG_##msg}
     59 
     60 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
     61 			 FEATURE_DPM_GFXCLK_MASK | \
     62 			 FEATURE_DPM_UCLK_MASK | \
     63 			 FEATURE_DPM_SOCCLK_MASK | \
     64 			 FEATURE_DPM_UVD_MASK | \
     65 			 FEATURE_DPM_VCE_MASK | \
     66 			 FEATURE_DPM_MP0CLK_MASK | \
     67 			 FEATURE_DPM_LINK_MASK | \
     68 			 FEATURE_DPM_DCEFCLK_MASK)
     69 
     70 static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] = {
     71 	MSG_MAP(TestMessage),
     72 	MSG_MAP(GetSmuVersion),
     73 	MSG_MAP(GetDriverIfVersion),
     74 	MSG_MAP(SetAllowedFeaturesMaskLow),
     75 	MSG_MAP(SetAllowedFeaturesMaskHigh),
     76 	MSG_MAP(EnableAllSmuFeatures),
     77 	MSG_MAP(DisableAllSmuFeatures),
     78 	MSG_MAP(EnableSmuFeaturesLow),
     79 	MSG_MAP(EnableSmuFeaturesHigh),
     80 	MSG_MAP(DisableSmuFeaturesLow),
     81 	MSG_MAP(DisableSmuFeaturesHigh),
     82 	MSG_MAP(GetEnabledSmuFeaturesLow),
     83 	MSG_MAP(GetEnabledSmuFeaturesHigh),
     84 	MSG_MAP(SetWorkloadMask),
     85 	MSG_MAP(SetPptLimit),
     86 	MSG_MAP(SetDriverDramAddrHigh),
     87 	MSG_MAP(SetDriverDramAddrLow),
     88 	MSG_MAP(SetToolsDramAddrHigh),
     89 	MSG_MAP(SetToolsDramAddrLow),
     90 	MSG_MAP(TransferTableSmu2Dram),
     91 	MSG_MAP(TransferTableDram2Smu),
     92 	MSG_MAP(UseDefaultPPTable),
     93 	MSG_MAP(UseBackupPPTable),
     94 	MSG_MAP(RunBtc),
     95 	MSG_MAP(RequestI2CBus),
     96 	MSG_MAP(ReleaseI2CBus),
     97 	MSG_MAP(SetFloorSocVoltage),
     98 	MSG_MAP(SoftReset),
     99 	MSG_MAP(StartBacoMonitor),
    100 	MSG_MAP(CancelBacoMonitor),
    101 	MSG_MAP(EnterBaco),
    102 	MSG_MAP(SetSoftMinByFreq),
    103 	MSG_MAP(SetSoftMaxByFreq),
    104 	MSG_MAP(SetHardMinByFreq),
    105 	MSG_MAP(SetHardMaxByFreq),
    106 	MSG_MAP(GetMinDpmFreq),
    107 	MSG_MAP(GetMaxDpmFreq),
    108 	MSG_MAP(GetDpmFreqByIndex),
    109 	MSG_MAP(GetDpmClockFreq),
    110 	MSG_MAP(GetSsVoltageByDpm),
    111 	MSG_MAP(SetMemoryChannelConfig),
    112 	MSG_MAP(SetGeminiMode),
    113 	MSG_MAP(SetGeminiApertureHigh),
    114 	MSG_MAP(SetGeminiApertureLow),
    115 	MSG_MAP(SetMinLinkDpmByIndex),
    116 	MSG_MAP(OverridePcieParameters),
    117 	MSG_MAP(OverDriveSetPercentage),
    118 	MSG_MAP(SetMinDeepSleepDcefclk),
    119 	MSG_MAP(ReenableAcDcInterrupt),
    120 	MSG_MAP(NotifyPowerSource),
    121 	MSG_MAP(SetUclkFastSwitch),
    122 	MSG_MAP(SetUclkDownHyst),
    123 	MSG_MAP(GetCurrentRpm),
    124 	MSG_MAP(SetVideoFps),
    125 	MSG_MAP(SetTjMax),
    126 	MSG_MAP(SetFanTemperatureTarget),
    127 	MSG_MAP(PrepareMp1ForUnload),
    128 	MSG_MAP(DramLogSetDramAddrHigh),
    129 	MSG_MAP(DramLogSetDramAddrLow),
    130 	MSG_MAP(DramLogSetDramSize),
    131 	MSG_MAP(SetFanMaxRpm),
    132 	MSG_MAP(SetFanMinPwm),
    133 	MSG_MAP(ConfigureGfxDidt),
    134 	MSG_MAP(NumOfDisplays),
    135 	MSG_MAP(RemoveMargins),
    136 	MSG_MAP(ReadSerialNumTop32),
    137 	MSG_MAP(ReadSerialNumBottom32),
    138 	MSG_MAP(SetSystemVirtualDramAddrHigh),
    139 	MSG_MAP(SetSystemVirtualDramAddrLow),
    140 	MSG_MAP(WaflTest),
    141 	MSG_MAP(SetFclkGfxClkRatio),
    142 	MSG_MAP(AllowGfxOff),
    143 	MSG_MAP(DisallowGfxOff),
    144 	MSG_MAP(GetPptLimit),
    145 	MSG_MAP(GetDcModeMaxDpmFreq),
    146 	MSG_MAP(GetDebugData),
    147 	MSG_MAP(SetXgmiMode),
    148 	MSG_MAP(RunAfllBtc),
    149 	MSG_MAP(ExitBaco),
    150 	MSG_MAP(PrepareMp1ForReset),
    151 	MSG_MAP(PrepareMp1ForShutdown),
    152 	MSG_MAP(SetMGpuFanBoostLimitRpm),
    153 	MSG_MAP(GetAVFSVoltageByDpm),
    154 	MSG_MAP(DFCstateControl),
    155 };
    156 
    157 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = {
    158 	CLK_MAP(GFXCLK, PPCLK_GFXCLK),
    159 	CLK_MAP(VCLK, PPCLK_VCLK),
    160 	CLK_MAP(DCLK, PPCLK_DCLK),
    161 	CLK_MAP(ECLK, PPCLK_ECLK),
    162 	CLK_MAP(SOCCLK, PPCLK_SOCCLK),
    163 	CLK_MAP(UCLK, PPCLK_UCLK),
    164 	CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
    165 	CLK_MAP(DISPCLK, PPCLK_DISPCLK),
    166 	CLK_MAP(PIXCLK, PPCLK_PIXCLK),
    167 	CLK_MAP(PHYCLK, PPCLK_PHYCLK),
    168 	CLK_MAP(FCLK, PPCLK_FCLK),
    169 };
    170 
    171 static struct smu_11_0_cmn2aisc_mapping vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
    172 	FEA_MAP(DPM_PREFETCHER),
    173 	FEA_MAP(DPM_GFXCLK),
    174 	FEA_MAP(DPM_UCLK),
    175 	FEA_MAP(DPM_SOCCLK),
    176 	FEA_MAP(DPM_UVD),
    177 	FEA_MAP(DPM_VCE),
    178 	FEA_MAP(ULV),
    179 	FEA_MAP(DPM_MP0CLK),
    180 	FEA_MAP(DPM_LINK),
    181 	FEA_MAP(DPM_DCEFCLK),
    182 	FEA_MAP(DS_GFXCLK),
    183 	FEA_MAP(DS_SOCCLK),
    184 	FEA_MAP(DS_LCLK),
    185 	FEA_MAP(PPT),
    186 	FEA_MAP(TDC),
    187 	FEA_MAP(THERMAL),
    188 	FEA_MAP(GFX_PER_CU_CG),
    189 	FEA_MAP(RM),
    190 	FEA_MAP(DS_DCEFCLK),
    191 	FEA_MAP(ACDC),
    192 	FEA_MAP(VR0HOT),
    193 	FEA_MAP(VR1HOT),
    194 	FEA_MAP(FW_CTF),
    195 	FEA_MAP(LED_DISPLAY),
    196 	FEA_MAP(FAN_CONTROL),
    197 	FEA_MAP(GFX_EDC),
    198 	FEA_MAP(GFXOFF),
    199 	FEA_MAP(CG),
    200 	FEA_MAP(DPM_FCLK),
    201 	FEA_MAP(DS_FCLK),
    202 	FEA_MAP(DS_MP1CLK),
    203 	FEA_MAP(DS_MP0CLK),
    204 	FEA_MAP(XGMI),
    205 };
    206 
    207 static struct smu_11_0_cmn2aisc_mapping vega20_table_map[SMU_TABLE_COUNT] = {
    208 	TAB_MAP(PPTABLE),
    209 	TAB_MAP(WATERMARKS),
    210 	TAB_MAP(AVFS),
    211 	TAB_MAP(AVFS_PSM_DEBUG),
    212 	TAB_MAP(AVFS_FUSE_OVERRIDE),
    213 	TAB_MAP(PMSTATUSLOG),
    214 	TAB_MAP(SMU_METRICS),
    215 	TAB_MAP(DRIVER_SMU_CONFIG),
    216 	TAB_MAP(ACTIVITY_MONITOR_COEFF),
    217 	TAB_MAP(OVERDRIVE),
    218 };
    219 
    220 static struct smu_11_0_cmn2aisc_mapping vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
    221 	PWR_MAP(AC),
    222 	PWR_MAP(DC),
    223 };
    224 
    225 static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
    226 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,	WORKLOAD_DEFAULT_BIT),
    227 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
    228 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,		WORKLOAD_PPLIB_POWER_SAVING_BIT),
    229 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
    230 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
    231 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
    232 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
    233 };
    234 
    235 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
    236 {
    237 	struct smu_11_0_cmn2aisc_mapping mapping;
    238 
    239 	if (index >= SMU_TABLE_COUNT)
    240 		return -EINVAL;
    241 
    242 	mapping = vega20_table_map[index];
    243 	if (!(mapping.valid_mapping)) {
    244 		return -EINVAL;
    245 	}
    246 
    247 	return mapping.map_to;
    248 }
    249 
    250 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
    251 {
    252 	struct smu_11_0_cmn2aisc_mapping mapping;
    253 
    254 	if (index >= SMU_POWER_SOURCE_COUNT)
    255 		return -EINVAL;
    256 
    257 	mapping = vega20_pwr_src_map[index];
    258 	if (!(mapping.valid_mapping)) {
    259 		return -EINVAL;
    260 	}
    261 
    262 	return mapping.map_to;
    263 }
    264 
    265 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
    266 {
    267 	struct smu_11_0_cmn2aisc_mapping mapping;
    268 
    269 	if (index >= SMU_FEATURE_COUNT)
    270 		return -EINVAL;
    271 
    272 	mapping = vega20_feature_mask_map[index];
    273 	if (!(mapping.valid_mapping)) {
    274 		return -EINVAL;
    275 	}
    276 
    277 	return mapping.map_to;
    278 }
    279 
    280 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
    281 {
    282 	struct smu_11_0_cmn2aisc_mapping mapping;
    283 
    284 	if (index >= SMU_CLK_COUNT)
    285 		return -EINVAL;
    286 
    287 	mapping = vega20_clk_map[index];
    288 	if (!(mapping.valid_mapping)) {
    289 		return -EINVAL;
    290 	}
    291 
    292 	return mapping.map_to;
    293 }
    294 
    295 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
    296 {
    297 	struct smu_11_0_cmn2aisc_mapping mapping;
    298 
    299 	if (index >= SMU_MSG_MAX_COUNT)
    300 		return -EINVAL;
    301 
    302 	mapping = vega20_message_map[index];
    303 	if (!(mapping.valid_mapping)) {
    304 		return -EINVAL;
    305 	}
    306 
    307 	return mapping.map_to;
    308 }
    309 
    310 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
    311 {
    312 	struct smu_11_0_cmn2aisc_mapping mapping;
    313 
    314 	if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
    315 		return -EINVAL;
    316 
    317 	mapping = vega20_workload_map[profile];
    318 	if (!(mapping.valid_mapping)) {
    319 		return -EINVAL;
    320 	}
    321 
    322 	return mapping.map_to;
    323 }
    324 
    325 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
    326 {
    327 	struct smu_table_context *smu_table = &smu->smu_table;
    328 
    329 	SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
    330 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
    331 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
    332 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
    333 	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
    334 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
    335 	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
    336 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
    337 	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
    338 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
    339 	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
    340 		       sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
    341 	               AMDGPU_GEM_DOMAIN_VRAM);
    342 
    343 	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
    344 	if (!smu_table->metrics_table)
    345 		return -ENOMEM;
    346 	smu_table->metrics_time = 0;
    347 
    348 	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
    349 	if (!smu_table->watermarks_table)
    350 		return -ENOMEM;
    351 
    352 	return 0;
    353 }
    354 
    355 static int vega20_allocate_dpm_context(struct smu_context *smu)
    356 {
    357 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
    358 
    359 	if (smu_dpm->dpm_context)
    360 		return -EINVAL;
    361 
    362 	smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
    363 				       GFP_KERNEL);
    364 	if (!smu_dpm->dpm_context)
    365 		return -ENOMEM;
    366 
    367 	if (smu_dpm->golden_dpm_context)
    368 		return -EINVAL;
    369 
    370 	smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
    371 					      GFP_KERNEL);
    372 	if (!smu_dpm->golden_dpm_context)
    373 		return -ENOMEM;
    374 
    375 	smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
    376 
    377 	smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
    378 				       GFP_KERNEL);
    379 	if (!smu_dpm->dpm_current_power_state)
    380 		return -ENOMEM;
    381 
    382 	smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
    383 				       GFP_KERNEL);
    384 	if (!smu_dpm->dpm_request_power_state)
    385 		return -ENOMEM;
    386 
    387 	return 0;
    388 }
    389 
    390 static int vega20_setup_od8_information(struct smu_context *smu)
    391 {
    392 	const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
    393 	struct smu_table_context *table_context = &smu->smu_table;
    394 	struct vega20_od8_settings *od8_settings = (struct vega20_od8_settings *)smu->od_settings;
    395 
    396 	uint32_t od_feature_count, od_feature_array_size,
    397 		 od_setting_count, od_setting_array_size;
    398 
    399 	if (!table_context->power_play_table)
    400 		return -EINVAL;
    401 
    402 	powerplay_table = table_context->power_play_table;
    403 
    404 	if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
    405 		/* Setup correct ODFeatureCount, and store ODFeatureArray from
    406 		 * powerplay table to od_feature_capabilities */
    407 		od_feature_count =
    408 			(le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
    409 			 ATOM_VEGA20_ODFEATURE_COUNT) ?
    410 			ATOM_VEGA20_ODFEATURE_COUNT :
    411 			le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
    412 
    413 		od_feature_array_size = sizeof(uint8_t) * od_feature_count;
    414 
    415 		if (od8_settings->od_feature_capabilities)
    416 			return -EINVAL;
    417 
    418 		od8_settings->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
    419 								 od_feature_array_size,
    420 								 GFP_KERNEL);
    421 		if (!od8_settings->od_feature_capabilities)
    422 			return -ENOMEM;
    423 
    424 		/* Setup correct ODSettingCount, and store ODSettingArray from
    425 		 * powerplay table to od_settings_max and od_setting_min */
    426 		od_setting_count =
    427 			(le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
    428 			 ATOM_VEGA20_ODSETTING_COUNT) ?
    429 			ATOM_VEGA20_ODSETTING_COUNT :
    430 			le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
    431 
    432 		od_setting_array_size = sizeof(uint32_t) * od_setting_count;
    433 
    434 		if (od8_settings->od_settings_max)
    435 			return -EINVAL;
    436 
    437 		od8_settings->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
    438 							 od_setting_array_size,
    439 							 GFP_KERNEL);
    440 
    441 		if (!od8_settings->od_settings_max) {
    442 			kfree(od8_settings->od_feature_capabilities);
    443 			od8_settings->od_feature_capabilities = NULL;
    444 			return -ENOMEM;
    445 		}
    446 
    447 		if (od8_settings->od_settings_min)
    448 			return -EINVAL;
    449 
    450 		od8_settings->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
    451 							 od_setting_array_size,
    452 							 GFP_KERNEL);
    453 
    454 		if (!od8_settings->od_settings_min) {
    455 			kfree(od8_settings->od_feature_capabilities);
    456 			od8_settings->od_feature_capabilities = NULL;
    457 			kfree(od8_settings->od_settings_max);
    458 			od8_settings->od_settings_max = NULL;
    459 			return -ENOMEM;
    460 		}
    461 	}
    462 
    463 	return 0;
    464 }
    465 
    466 static int vega20_store_powerplay_table(struct smu_context *smu)
    467 {
    468 	const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
    469 	struct smu_table_context *table_context = &smu->smu_table;
    470 
    471 	if (!table_context->power_play_table)
    472 		return -EINVAL;
    473 
    474 	powerplay_table = table_context->power_play_table;
    475 
    476 	memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
    477 	       sizeof(PPTable_t));
    478 
    479 	table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
    480 
    481 	return 0;
    482 }
    483 
    484 static int vega20_append_powerplay_table(struct smu_context *smu)
    485 {
    486 	struct smu_table_context *table_context = &smu->smu_table;
    487 	PPTable_t *smc_pptable = table_context->driver_pptable;
    488 	struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
    489 	int index, i, ret;
    490 
    491 	index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
    492 					   smc_dpm_info);
    493 
    494 	ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
    495 				      (uint8_t **)&smc_dpm_table);
    496 	if (ret)
    497 		return ret;
    498 
    499 	smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
    500 	smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
    501 
    502 	smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
    503 	smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
    504 	smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
    505 	smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
    506 
    507 	smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
    508 	smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
    509 	smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
    510 
    511 	smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
    512 	smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
    513 	smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
    514 
    515 	smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
    516 	smc_pptable->SocOffset = smc_dpm_table->socoffset;
    517 	smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
    518 
    519 	smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
    520 	smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
    521 	smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
    522 
    523 	smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
    524 	smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
    525 	smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
    526 
    527 	smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
    528 	smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
    529 	smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
    530 	smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
    531 
    532 	smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
    533 	smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
    534 	smc_pptable->Padding1 = smc_dpm_table->padding1;
    535 	smc_pptable->Padding2 = smc_dpm_table->padding2;
    536 
    537 	smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
    538 	smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
    539 	smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
    540 
    541 	smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
    542 	smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
    543 	smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
    544 
    545 	smc_pptable->UclkSpreadEnabled = 0;
    546 	smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
    547 	smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
    548 
    549 	smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
    550 	smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
    551 	smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
    552 
    553 	smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
    554 	smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
    555 	smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
    556 
    557 	for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
    558 		smc_pptable->I2cControllers[i].Enabled =
    559 			smc_dpm_table->i2ccontrollers[i].enabled;
    560 		smc_pptable->I2cControllers[i].SlaveAddress =
    561 			smc_dpm_table->i2ccontrollers[i].slaveaddress;
    562 		smc_pptable->I2cControllers[i].ControllerPort =
    563 			smc_dpm_table->i2ccontrollers[i].controllerport;
    564 		smc_pptable->I2cControllers[i].ThermalThrottler =
    565 			smc_dpm_table->i2ccontrollers[i].thermalthrottler;
    566 		smc_pptable->I2cControllers[i].I2cProtocol =
    567 			smc_dpm_table->i2ccontrollers[i].i2cprotocol;
    568 		smc_pptable->I2cControllers[i].I2cSpeed =
    569 			smc_dpm_table->i2ccontrollers[i].i2cspeed;
    570 	}
    571 
    572 	return 0;
    573 }
    574 
    575 static int vega20_check_powerplay_table(struct smu_context *smu)
    576 {
    577 	const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
    578 	struct smu_table_context *table_context = &smu->smu_table;
    579 
    580 	powerplay_table = table_context->power_play_table;
    581 
    582 	if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
    583 		pr_err("Unsupported PPTable format!");
    584 		return -EINVAL;
    585 	}
    586 
    587 	if (!powerplay_table->sHeader.structuresize) {
    588 		pr_err("Invalid PowerPlay Table!");
    589 		return -EINVAL;
    590 	}
    591 
    592 	return 0;
    593 }
    594 
    595 static int vega20_run_btc_afll(struct smu_context *smu)
    596 {
    597 	return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
    598 }
    599 
    600 #define FEATURE_MASK(feature) (1ULL << feature)
    601 static int
    602 vega20_get_allowed_feature_mask(struct smu_context *smu,
    603 				  uint32_t *feature_mask, uint32_t num)
    604 {
    605 	if (num > 2)
    606 		return -EINVAL;
    607 
    608 	memset(feature_mask, 0, sizeof(uint32_t) * num);
    609 
    610 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
    611 				| FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
    612 				| FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
    613 				| FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
    614 				| FEATURE_MASK(FEATURE_DPM_UVD_BIT)
    615 				| FEATURE_MASK(FEATURE_DPM_VCE_BIT)
    616 				| FEATURE_MASK(FEATURE_ULV_BIT)
    617 				| FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
    618 				| FEATURE_MASK(FEATURE_DPM_LINK_BIT)
    619 				| FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
    620 				| FEATURE_MASK(FEATURE_PPT_BIT)
    621 				| FEATURE_MASK(FEATURE_TDC_BIT)
    622 				| FEATURE_MASK(FEATURE_THERMAL_BIT)
    623 				| FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT)
    624 				| FEATURE_MASK(FEATURE_RM_BIT)
    625 				| FEATURE_MASK(FEATURE_ACDC_BIT)
    626 				| FEATURE_MASK(FEATURE_VR0HOT_BIT)
    627 				| FEATURE_MASK(FEATURE_VR1HOT_BIT)
    628 				| FEATURE_MASK(FEATURE_FW_CTF_BIT)
    629 				| FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
    630 				| FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
    631 				| FEATURE_MASK(FEATURE_GFX_EDC_BIT)
    632 				| FEATURE_MASK(FEATURE_GFXOFF_BIT)
    633 				| FEATURE_MASK(FEATURE_CG_BIT)
    634 				| FEATURE_MASK(FEATURE_DPM_FCLK_BIT)
    635 				| FEATURE_MASK(FEATURE_XGMI_BIT);
    636 	return 0;
    637 }
    638 
    639 static enum
    640 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
    641 {
    642 	enum amd_pm_state_type pm_type;
    643 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
    644 
    645 	if (!smu_dpm_ctx->dpm_context ||
    646 	    !smu_dpm_ctx->dpm_current_power_state)
    647 		return -EINVAL;
    648 
    649 	switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
    650 	case SMU_STATE_UI_LABEL_BATTERY:
    651 		pm_type = POWER_STATE_TYPE_BATTERY;
    652 		break;
    653 	case SMU_STATE_UI_LABEL_BALLANCED:
    654 		pm_type = POWER_STATE_TYPE_BALANCED;
    655 		break;
    656 	case SMU_STATE_UI_LABEL_PERFORMANCE:
    657 		pm_type = POWER_STATE_TYPE_PERFORMANCE;
    658 		break;
    659 	default:
    660 		if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
    661 			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
    662 		else
    663 			pm_type = POWER_STATE_TYPE_DEFAULT;
    664 		break;
    665 	}
    666 
    667 	return pm_type;
    668 }
    669 
    670 static int
    671 vega20_set_single_dpm_table(struct smu_context *smu,
    672 			    struct vega20_single_dpm_table *single_dpm_table,
    673 			    PPCLK_e clk_id)
    674 {
    675 	int ret = 0;
    676 	uint32_t i, num_of_levels = 0, clk;
    677 
    678 	ret = smu_send_smc_msg_with_param(smu,
    679 			SMU_MSG_GetDpmFreqByIndex,
    680 			(clk_id << 16 | 0xFF));
    681 	if (ret) {
    682 		pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
    683 		return ret;
    684 	}
    685 
    686 	smu_read_smc_arg(smu, &num_of_levels);
    687 	if (!num_of_levels) {
    688 		pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
    689 		return -EINVAL;
    690 	}
    691 
    692 	single_dpm_table->count = num_of_levels;
    693 
    694 	for (i = 0; i < num_of_levels; i++) {
    695 		ret = smu_send_smc_msg_with_param(smu,
    696 				SMU_MSG_GetDpmFreqByIndex,
    697 				(clk_id << 16 | i));
    698 		if (ret) {
    699 			pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
    700 			return ret;
    701 		}
    702 		smu_read_smc_arg(smu, &clk);
    703 		if (!clk) {
    704 			pr_err("[GetDpmFreqByIndex] clk value is invalid!");
    705 			return -EINVAL;
    706 		}
    707 		single_dpm_table->dpm_levels[i].value = clk;
    708 		single_dpm_table->dpm_levels[i].enabled = true;
    709 	}
    710 	return 0;
    711 }
    712 
    713 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
    714 {
    715 	dpm_state->soft_min_level = 0x0;
    716 	dpm_state->soft_max_level = 0xffff;
    717         dpm_state->hard_min_level = 0x0;
    718         dpm_state->hard_max_level = 0xffff;
    719 }
    720 
    721 static int vega20_set_default_dpm_table(struct smu_context *smu)
    722 {
    723 	int ret;
    724 
    725 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
    726 	struct vega20_dpm_table *dpm_table = NULL;
    727 	struct vega20_single_dpm_table *single_dpm_table;
    728 
    729 	dpm_table = smu_dpm->dpm_context;
    730 
    731 	/* socclk */
    732 	single_dpm_table = &(dpm_table->soc_table);
    733 
    734 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
    735 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    736 						  PPCLK_SOCCLK);
    737 		if (ret) {
    738 			pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
    739 			return ret;
    740 		}
    741 	} else {
    742 		single_dpm_table->count = 1;
    743 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
    744 	}
    745 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    746 
    747 	/* gfxclk */
    748 	single_dpm_table = &(dpm_table->gfx_table);
    749 
    750 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
    751 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    752 						  PPCLK_GFXCLK);
    753 		if (ret) {
    754 			pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
    755 			return ret;
    756 		}
    757 	} else {
    758 		single_dpm_table->count = 1;
    759 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
    760 	}
    761 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    762 
    763 	/* memclk */
    764 	single_dpm_table = &(dpm_table->mem_table);
    765 
    766 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
    767 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    768 						  PPCLK_UCLK);
    769 		if (ret) {
    770 			pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
    771 			return ret;
    772 		}
    773 	} else {
    774 		single_dpm_table->count = 1;
    775 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
    776 	}
    777 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    778 
    779 	/* eclk */
    780 	single_dpm_table = &(dpm_table->eclk_table);
    781 
    782 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) {
    783 		ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
    784 		if (ret) {
    785 			pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
    786 			return ret;
    787 		}
    788 	} else {
    789 		single_dpm_table->count = 1;
    790 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
    791 	}
    792 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    793 
    794 	/* vclk */
    795 	single_dpm_table = &(dpm_table->vclk_table);
    796 
    797 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
    798 		ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
    799 		if (ret) {
    800 			pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
    801 			return ret;
    802 		}
    803 	} else {
    804 		single_dpm_table->count = 1;
    805 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
    806 	}
    807 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    808 
    809 	/* dclk */
    810 	single_dpm_table = &(dpm_table->dclk_table);
    811 
    812 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
    813 		ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
    814 		if (ret) {
    815 			pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
    816 			return ret;
    817 		}
    818 	} else {
    819 		single_dpm_table->count = 1;
    820 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
    821 	}
    822 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    823 
    824 	/* dcefclk */
    825 	single_dpm_table = &(dpm_table->dcef_table);
    826 
    827 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
    828 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    829 						  PPCLK_DCEFCLK);
    830 		if (ret) {
    831 			pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
    832 			return ret;
    833 		}
    834 	} else {
    835 		single_dpm_table->count = 1;
    836 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
    837 	}
    838 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    839 
    840 	/* pixclk */
    841 	single_dpm_table = &(dpm_table->pixel_table);
    842 
    843 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
    844 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    845 						  PPCLK_PIXCLK);
    846 		if (ret) {
    847 			pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
    848 			return ret;
    849 		}
    850 	} else {
    851 		single_dpm_table->count = 0;
    852 	}
    853 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    854 
    855 	/* dispclk */
    856 	single_dpm_table = &(dpm_table->display_table);
    857 
    858 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
    859 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    860 						  PPCLK_DISPCLK);
    861 		if (ret) {
    862 			pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
    863 			return ret;
    864 		}
    865 	} else {
    866 		single_dpm_table->count = 0;
    867 	}
    868 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    869 
    870 	/* phyclk */
    871 	single_dpm_table = &(dpm_table->phy_table);
    872 
    873 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
    874 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    875 						  PPCLK_PHYCLK);
    876 		if (ret) {
    877 			pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
    878 			return ret;
    879 		}
    880 	} else {
    881 		single_dpm_table->count = 0;
    882 	}
    883 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    884 
    885 	/* fclk */
    886 	single_dpm_table = &(dpm_table->fclk_table);
    887 
    888 	if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
    889 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
    890 						  PPCLK_FCLK);
    891 		if (ret) {
    892 			pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
    893 			return ret;
    894 		}
    895 	} else {
    896 		single_dpm_table->count = 0;
    897 	}
    898 	vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
    899 
    900 	memcpy(smu_dpm->golden_dpm_context, dpm_table,
    901 	       sizeof(struct vega20_dpm_table));
    902 
    903 	return 0;
    904 }
    905 
    906 static int vega20_populate_umd_state_clk(struct smu_context *smu)
    907 {
    908 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
    909 	struct vega20_dpm_table *dpm_table = NULL;
    910 	struct vega20_single_dpm_table *gfx_table = NULL;
    911 	struct vega20_single_dpm_table *mem_table = NULL;
    912 
    913 	dpm_table = smu_dpm->dpm_context;
    914 	gfx_table = &(dpm_table->gfx_table);
    915 	mem_table = &(dpm_table->mem_table);
    916 
    917 	smu->pstate_sclk = gfx_table->dpm_levels[0].value;
    918 	smu->pstate_mclk = mem_table->dpm_levels[0].value;
    919 
    920 	if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
    921 	    mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
    922 		smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
    923 		smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
    924 	}
    925 
    926 	smu->pstate_sclk = smu->pstate_sclk * 100;
    927 	smu->pstate_mclk = smu->pstate_mclk * 100;
    928 
    929 	return 0;
    930 }
    931 
    932 static int vega20_get_clk_table(struct smu_context *smu,
    933 			struct pp_clock_levels_with_latency *clocks,
    934 			struct vega20_single_dpm_table *dpm_table)
    935 {
    936 	int i, count;
    937 
    938 	count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
    939 	clocks->num_levels = count;
    940 
    941 	for (i = 0; i < count; i++) {
    942 		clocks->data[i].clocks_in_khz =
    943 			dpm_table->dpm_levels[i].value * 1000;
    944 		clocks->data[i].latency_in_us = 0;
    945 	}
    946 
    947 	return 0;
    948 }
    949 
    950 static int vega20_print_clk_levels(struct smu_context *smu,
    951 			enum smu_clk_type type, char *buf)
    952 {
    953 	int i, now, size = 0;
    954 	int ret = 0;
    955 	uint32_t gen_speed, lane_width;
    956 	struct amdgpu_device *adev = smu->adev;
    957 	struct pp_clock_levels_with_latency clocks;
    958 	struct vega20_single_dpm_table *single_dpm_table;
    959 	struct smu_table_context *table_context = &smu->smu_table;
    960 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
    961 	struct vega20_dpm_table *dpm_table = NULL;
    962 	struct vega20_od8_settings *od8_settings =
    963 		(struct vega20_od8_settings *)smu->od_settings;
    964 	OverDriveTable_t *od_table =
    965 		(OverDriveTable_t *)(table_context->overdrive_table);
    966 	PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
    967 
    968 	dpm_table = smu_dpm->dpm_context;
    969 
    970 	switch (type) {
    971 	case SMU_SCLK:
    972 		ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now);
    973 		if (ret) {
    974 			pr_err("Attempt to get current gfx clk Failed!");
    975 			return ret;
    976 		}
    977 
    978 		single_dpm_table = &(dpm_table->gfx_table);
    979 		ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
    980 		if (ret) {
    981 			pr_err("Attempt to get gfx clk levels Failed!");
    982 			return ret;
    983 		}
    984 
    985 		for (i = 0; i < clocks.num_levels; i++)
    986 			size += sprintf(buf + size, "%d: %uMhz %s\n", i,
    987 					clocks.data[i].clocks_in_khz / 1000,
    988 					(clocks.data[i].clocks_in_khz == now * 10)
    989 					? "*" : "");
    990 		break;
    991 
    992 	case SMU_MCLK:
    993 		ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now);
    994 		if (ret) {
    995 			pr_err("Attempt to get current mclk Failed!");
    996 			return ret;
    997 		}
    998 
    999 		single_dpm_table = &(dpm_table->mem_table);
   1000 		ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
   1001 		if (ret) {
   1002 			pr_err("Attempt to get memory clk levels Failed!");
   1003 			return ret;
   1004 		}
   1005 
   1006 		for (i = 0; i < clocks.num_levels; i++)
   1007 			size += sprintf(buf + size, "%d: %uMhz %s\n",
   1008 				i, clocks.data[i].clocks_in_khz / 1000,
   1009 				(clocks.data[i].clocks_in_khz == now * 10)
   1010 				? "*" : "");
   1011 		break;
   1012 
   1013 	case SMU_SOCCLK:
   1014 		ret = smu_get_current_clk_freq(smu, SMU_SOCCLK, &now);
   1015 		if (ret) {
   1016 			pr_err("Attempt to get current socclk Failed!");
   1017 			return ret;
   1018 		}
   1019 
   1020 		single_dpm_table = &(dpm_table->soc_table);
   1021 		ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
   1022 		if (ret) {
   1023 			pr_err("Attempt to get socclk levels Failed!");
   1024 			return ret;
   1025 		}
   1026 
   1027 		for (i = 0; i < clocks.num_levels; i++)
   1028 			size += sprintf(buf + size, "%d: %uMhz %s\n",
   1029 				i, clocks.data[i].clocks_in_khz / 1000,
   1030 				(clocks.data[i].clocks_in_khz == now * 10)
   1031 				? "*" : "");
   1032 		break;
   1033 
   1034 	case SMU_FCLK:
   1035 		ret = smu_get_current_clk_freq(smu, SMU_FCLK, &now);
   1036 		if (ret) {
   1037 			pr_err("Attempt to get current fclk Failed!");
   1038 			return ret;
   1039 		}
   1040 
   1041 		single_dpm_table = &(dpm_table->fclk_table);
   1042 		for (i = 0; i < single_dpm_table->count; i++)
   1043 			size += sprintf(buf + size, "%d: %uMhz %s\n",
   1044 				i, single_dpm_table->dpm_levels[i].value,
   1045 				(single_dpm_table->dpm_levels[i].value == now / 100)
   1046 				? "*" : "");
   1047 		break;
   1048 
   1049 	case SMU_DCEFCLK:
   1050 		ret = smu_get_current_clk_freq(smu, SMU_DCEFCLK, &now);
   1051 		if (ret) {
   1052 			pr_err("Attempt to get current dcefclk Failed!");
   1053 			return ret;
   1054 		}
   1055 
   1056 		single_dpm_table = &(dpm_table->dcef_table);
   1057 		ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
   1058 		if (ret) {
   1059 			pr_err("Attempt to get dcefclk levels Failed!");
   1060 			return ret;
   1061 		}
   1062 
   1063 		for (i = 0; i < clocks.num_levels; i++)
   1064 			size += sprintf(buf + size, "%d: %uMhz %s\n",
   1065 				i, clocks.data[i].clocks_in_khz / 1000,
   1066 				(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
   1067 		break;
   1068 
   1069 	case SMU_PCIE:
   1070 		gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
   1071 			     PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
   1072 			>> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
   1073 		lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
   1074 			      PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
   1075 			>> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
   1076 		for (i = 0; i < NUM_LINK_LEVELS; i++)
   1077 			size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
   1078 					(pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
   1079 					(pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
   1080 					(pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
   1081 					(pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
   1082 					(pptable->PcieLaneCount[i] == 1) ? "x1" :
   1083 					(pptable->PcieLaneCount[i] == 2) ? "x2" :
   1084 					(pptable->PcieLaneCount[i] == 3) ? "x4" :
   1085 					(pptable->PcieLaneCount[i] == 4) ? "x8" :
   1086 					(pptable->PcieLaneCount[i] == 5) ? "x12" :
   1087 					(pptable->PcieLaneCount[i] == 6) ? "x16" : "",
   1088 					pptable->LclkFreq[i],
   1089 					(gen_speed == pptable->PcieGenSpeed[i]) &&
   1090 					(lane_width == pptable->PcieLaneCount[i]) ?
   1091 					"*" : "");
   1092 		break;
   1093 
   1094 	case SMU_OD_SCLK:
   1095 		if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
   1096 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
   1097 			size = sprintf(buf, "%s:\n", "OD_SCLK");
   1098 			size += sprintf(buf + size, "0: %10uMhz\n",
   1099 					od_table->GfxclkFmin);
   1100 			size += sprintf(buf + size, "1: %10uMhz\n",
   1101 					od_table->GfxclkFmax);
   1102 		}
   1103 
   1104 		break;
   1105 
   1106 	case SMU_OD_MCLK:
   1107 		if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
   1108 			size = sprintf(buf, "%s:\n", "OD_MCLK");
   1109 			size += sprintf(buf + size, "1: %10uMhz\n",
   1110 					 od_table->UclkFmax);
   1111 		}
   1112 
   1113 		break;
   1114 
   1115 	case SMU_OD_VDDC_CURVE:
   1116 		if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
   1117 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
   1118 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
   1119 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
   1120 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
   1121 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
   1122 			size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
   1123 			size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
   1124 					od_table->GfxclkFreq1,
   1125 					od_table->GfxclkVolt1 / VOLTAGE_SCALE);
   1126 			size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
   1127 					od_table->GfxclkFreq2,
   1128 					od_table->GfxclkVolt2 / VOLTAGE_SCALE);
   1129 			size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
   1130 					od_table->GfxclkFreq3,
   1131 					od_table->GfxclkVolt3 / VOLTAGE_SCALE);
   1132 		}
   1133 
   1134 		break;
   1135 
   1136 	case SMU_OD_RANGE:
   1137 		size = sprintf(buf, "%s:\n", "OD_RANGE");
   1138 
   1139 		if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
   1140 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
   1141 			size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
   1142 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
   1143 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
   1144 		}
   1145 
   1146 		if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
   1147 			single_dpm_table = &(dpm_table->mem_table);
   1148 			ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
   1149 			if (ret) {
   1150 				pr_err("Attempt to get memory clk levels Failed!");
   1151 				return ret;
   1152 			}
   1153 
   1154 			size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
   1155 					clocks.data[0].clocks_in_khz / 1000,
   1156 					od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
   1157 		}
   1158 
   1159 		if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
   1160 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
   1161 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
   1162 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
   1163 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
   1164 		    od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
   1165 			size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
   1166 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
   1167 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
   1168 			size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
   1169 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
   1170 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
   1171 			size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
   1172 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
   1173 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
   1174 			size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
   1175 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
   1176 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
   1177 			size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
   1178 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
   1179 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
   1180 			size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
   1181 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
   1182 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
   1183 		}
   1184 
   1185 		break;
   1186 
   1187 	default:
   1188 		break;
   1189 	}
   1190 	return size;
   1191 }
   1192 
   1193 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
   1194 				   uint32_t feature_mask)
   1195 {
   1196 	struct vega20_dpm_table *dpm_table;
   1197 	struct vega20_single_dpm_table *single_dpm_table;
   1198 	uint32_t freq;
   1199 	int ret = 0;
   1200 
   1201 	dpm_table = smu->smu_dpm.dpm_context;
   1202 
   1203 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
   1204 	    (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
   1205 		single_dpm_table = &(dpm_table->gfx_table);
   1206 		freq = max ? single_dpm_table->dpm_state.soft_max_level :
   1207 			single_dpm_table->dpm_state.soft_min_level;
   1208 		ret = smu_send_smc_msg_with_param(smu,
   1209 			(max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
   1210 			(PPCLK_GFXCLK << 16) | (freq & 0xffff));
   1211 		if (ret) {
   1212 			pr_err("Failed to set soft %s gfxclk !\n",
   1213 						max ? "max" : "min");
   1214 			return ret;
   1215 		}
   1216 	}
   1217 
   1218 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
   1219 	    (feature_mask & FEATURE_DPM_UCLK_MASK)) {
   1220 		single_dpm_table = &(dpm_table->mem_table);
   1221 		freq = max ? single_dpm_table->dpm_state.soft_max_level :
   1222 			single_dpm_table->dpm_state.soft_min_level;
   1223 		ret = smu_send_smc_msg_with_param(smu,
   1224 			(max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
   1225 			(PPCLK_UCLK << 16) | (freq & 0xffff));
   1226 		if (ret) {
   1227 			pr_err("Failed to set soft %s memclk !\n",
   1228 						max ? "max" : "min");
   1229 			return ret;
   1230 		}
   1231 	}
   1232 
   1233 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
   1234 	    (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
   1235 		single_dpm_table = &(dpm_table->soc_table);
   1236 		freq = max ? single_dpm_table->dpm_state.soft_max_level :
   1237 			single_dpm_table->dpm_state.soft_min_level;
   1238 		ret = smu_send_smc_msg_with_param(smu,
   1239 			(max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
   1240 			(PPCLK_SOCCLK << 16) | (freq & 0xffff));
   1241 		if (ret) {
   1242 			pr_err("Failed to set soft %s socclk !\n",
   1243 						max ? "max" : "min");
   1244 			return ret;
   1245 		}
   1246 	}
   1247 
   1248 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) &&
   1249 	    (feature_mask & FEATURE_DPM_FCLK_MASK)) {
   1250 		single_dpm_table = &(dpm_table->fclk_table);
   1251 		freq = max ? single_dpm_table->dpm_state.soft_max_level :
   1252 			single_dpm_table->dpm_state.soft_min_level;
   1253 		ret = smu_send_smc_msg_with_param(smu,
   1254 			(max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
   1255 			(PPCLK_FCLK << 16) | (freq & 0xffff));
   1256 		if (ret) {
   1257 			pr_err("Failed to set soft %s fclk !\n",
   1258 						max ? "max" : "min");
   1259 			return ret;
   1260 		}
   1261 	}
   1262 
   1263 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
   1264 	    (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
   1265 		single_dpm_table = &(dpm_table->dcef_table);
   1266 		freq = single_dpm_table->dpm_state.hard_min_level;
   1267 		if (!max) {
   1268 			ret = smu_send_smc_msg_with_param(smu,
   1269 				SMU_MSG_SetHardMinByFreq,
   1270 				(PPCLK_DCEFCLK << 16) | (freq & 0xffff));
   1271 			if (ret) {
   1272 				pr_err("Failed to set hard min dcefclk !\n");
   1273 				return ret;
   1274 			}
   1275 		}
   1276 	}
   1277 
   1278 	return ret;
   1279 }
   1280 
   1281 static int vega20_force_clk_levels(struct smu_context *smu,
   1282 			enum  smu_clk_type clk_type, uint32_t mask)
   1283 {
   1284 	struct vega20_dpm_table *dpm_table;
   1285 	struct vega20_single_dpm_table *single_dpm_table;
   1286 	uint32_t soft_min_level, soft_max_level, hard_min_level;
   1287 	int ret = 0;
   1288 
   1289 	soft_min_level = mask ? (ffs(mask) - 1) : 0;
   1290 	soft_max_level = mask ? (fls(mask) - 1) : 0;
   1291 
   1292 	dpm_table = smu->smu_dpm.dpm_context;
   1293 
   1294 	switch (clk_type) {
   1295 	case SMU_SCLK:
   1296 		single_dpm_table = &(dpm_table->gfx_table);
   1297 
   1298 		if (soft_max_level >= single_dpm_table->count) {
   1299 			pr_err("Clock level specified %d is over max allowed %d\n",
   1300 					soft_max_level, single_dpm_table->count - 1);
   1301 			ret = -EINVAL;
   1302 			break;
   1303 		}
   1304 
   1305 		single_dpm_table->dpm_state.soft_min_level =
   1306 			single_dpm_table->dpm_levels[soft_min_level].value;
   1307 		single_dpm_table->dpm_state.soft_max_level =
   1308 			single_dpm_table->dpm_levels[soft_max_level].value;
   1309 
   1310 		ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
   1311 		if (ret) {
   1312 			pr_err("Failed to upload boot level to lowest!\n");
   1313 			break;
   1314 		}
   1315 
   1316 		ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
   1317 		if (ret)
   1318 			pr_err("Failed to upload dpm max level to highest!\n");
   1319 
   1320 		break;
   1321 
   1322 	case SMU_MCLK:
   1323 		single_dpm_table = &(dpm_table->mem_table);
   1324 
   1325 		if (soft_max_level >= single_dpm_table->count) {
   1326 			pr_err("Clock level specified %d is over max allowed %d\n",
   1327 					soft_max_level, single_dpm_table->count - 1);
   1328 			ret = -EINVAL;
   1329 			break;
   1330 		}
   1331 
   1332 		single_dpm_table->dpm_state.soft_min_level =
   1333 			single_dpm_table->dpm_levels[soft_min_level].value;
   1334 		single_dpm_table->dpm_state.soft_max_level =
   1335 			single_dpm_table->dpm_levels[soft_max_level].value;
   1336 
   1337 		ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
   1338 		if (ret) {
   1339 			pr_err("Failed to upload boot level to lowest!\n");
   1340 			break;
   1341 		}
   1342 
   1343 		ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
   1344 		if (ret)
   1345 			pr_err("Failed to upload dpm max level to highest!\n");
   1346 
   1347 		break;
   1348 
   1349 	case SMU_SOCCLK:
   1350 		single_dpm_table = &(dpm_table->soc_table);
   1351 
   1352 		if (soft_max_level >= single_dpm_table->count) {
   1353 			pr_err("Clock level specified %d is over max allowed %d\n",
   1354 					soft_max_level, single_dpm_table->count - 1);
   1355 			ret = -EINVAL;
   1356 			break;
   1357 		}
   1358 
   1359 		single_dpm_table->dpm_state.soft_min_level =
   1360 			single_dpm_table->dpm_levels[soft_min_level].value;
   1361 		single_dpm_table->dpm_state.soft_max_level =
   1362 			single_dpm_table->dpm_levels[soft_max_level].value;
   1363 
   1364 		ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
   1365 		if (ret) {
   1366 			pr_err("Failed to upload boot level to lowest!\n");
   1367 			break;
   1368 		}
   1369 
   1370 		ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
   1371 		if (ret)
   1372 			pr_err("Failed to upload dpm max level to highest!\n");
   1373 
   1374 		break;
   1375 
   1376 	case SMU_FCLK:
   1377 		single_dpm_table = &(dpm_table->fclk_table);
   1378 
   1379 		if (soft_max_level >= single_dpm_table->count) {
   1380 			pr_err("Clock level specified %d is over max allowed %d\n",
   1381 					soft_max_level, single_dpm_table->count - 1);
   1382 			ret = -EINVAL;
   1383 			break;
   1384 		}
   1385 
   1386 		single_dpm_table->dpm_state.soft_min_level =
   1387 			single_dpm_table->dpm_levels[soft_min_level].value;
   1388 		single_dpm_table->dpm_state.soft_max_level =
   1389 			single_dpm_table->dpm_levels[soft_max_level].value;
   1390 
   1391 		ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
   1392 		if (ret) {
   1393 			pr_err("Failed to upload boot level to lowest!\n");
   1394 			break;
   1395 		}
   1396 
   1397 		ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
   1398 		if (ret)
   1399 			pr_err("Failed to upload dpm max level to highest!\n");
   1400 
   1401 		break;
   1402 
   1403 	case SMU_DCEFCLK:
   1404 		hard_min_level = soft_min_level;
   1405 		single_dpm_table = &(dpm_table->dcef_table);
   1406 
   1407 		if (hard_min_level >= single_dpm_table->count) {
   1408 			pr_err("Clock level specified %d is over max allowed %d\n",
   1409 					hard_min_level, single_dpm_table->count - 1);
   1410 			ret = -EINVAL;
   1411 			break;
   1412 		}
   1413 
   1414 		single_dpm_table->dpm_state.hard_min_level =
   1415 			single_dpm_table->dpm_levels[hard_min_level].value;
   1416 
   1417 		ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
   1418 		if (ret)
   1419 			pr_err("Failed to upload boot level to lowest!\n");
   1420 
   1421 		break;
   1422 
   1423 	case SMU_PCIE:
   1424 		if (soft_min_level >= NUM_LINK_LEVELS ||
   1425 		    soft_max_level >= NUM_LINK_LEVELS) {
   1426 			ret = -EINVAL;
   1427 			break;
   1428 		}
   1429 
   1430 		ret = smu_send_smc_msg_with_param(smu,
   1431 				SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
   1432 		if (ret)
   1433 			pr_err("Failed to set min link dpm level!\n");
   1434 
   1435 		break;
   1436 
   1437 	default:
   1438 		break;
   1439 	}
   1440 
   1441 	return ret;
   1442 }
   1443 
   1444 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
   1445 						 enum smu_clk_type clk_type,
   1446 						 struct pp_clock_levels_with_latency *clocks)
   1447 {
   1448 	int ret;
   1449 	struct vega20_single_dpm_table *single_dpm_table;
   1450 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
   1451 	struct vega20_dpm_table *dpm_table = NULL;
   1452 
   1453 	dpm_table = smu_dpm->dpm_context;
   1454 
   1455 	switch (clk_type) {
   1456 	case SMU_GFXCLK:
   1457 		single_dpm_table = &(dpm_table->gfx_table);
   1458 		ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
   1459 		break;
   1460 	case SMU_MCLK:
   1461 		single_dpm_table = &(dpm_table->mem_table);
   1462 		ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
   1463 		break;
   1464 	case SMU_DCEFCLK:
   1465 		single_dpm_table = &(dpm_table->dcef_table);
   1466 		ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
   1467 		break;
   1468 	case SMU_SOCCLK:
   1469 		single_dpm_table = &(dpm_table->soc_table);
   1470 		ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
   1471 		break;
   1472 	default:
   1473 		ret = -EINVAL;
   1474 	}
   1475 
   1476 	return ret;
   1477 }
   1478 
   1479 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
   1480 						     uint32_t *voltage,
   1481 						     uint32_t freq)
   1482 {
   1483 	int ret;
   1484 
   1485 	ret = smu_send_smc_msg_with_param(smu,
   1486 			SMU_MSG_GetAVFSVoltageByDpm,
   1487 			((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
   1488 	if (ret) {
   1489 		pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
   1490 		return ret;
   1491 	}
   1492 
   1493 	smu_read_smc_arg(smu, voltage);
   1494 	*voltage = *voltage / VOLTAGE_SCALE;
   1495 
   1496 	return 0;
   1497 }
   1498 
   1499 static int vega20_set_default_od8_setttings(struct smu_context *smu)
   1500 {
   1501 	struct smu_table_context *table_context = &smu->smu_table;
   1502 	OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
   1503 	struct vega20_od8_settings *od8_settings = NULL;
   1504 	PPTable_t *smc_pptable = table_context->driver_pptable;
   1505 	int i, ret;
   1506 
   1507 	if (smu->od_settings)
   1508 		return -EINVAL;
   1509 
   1510 	od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
   1511 
   1512 	if (!od8_settings)
   1513 		return -ENOMEM;
   1514 
   1515 	smu->od_settings = (void *)od8_settings;
   1516 
   1517 	ret = vega20_setup_od8_information(smu);
   1518 	if (ret) {
   1519 		pr_err("Retrieve board OD limits failed!\n");
   1520 		return ret;
   1521 	}
   1522 
   1523 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
   1524 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
   1525 		    od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
   1526 		    od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
   1527 		    (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
   1528 		     od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
   1529 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
   1530 				OD8_GFXCLK_LIMITS;
   1531 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
   1532 				OD8_GFXCLK_LIMITS;
   1533 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
   1534 				od_table->GfxclkFmin;
   1535 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
   1536 				od_table->GfxclkFmax;
   1537 		}
   1538 
   1539 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
   1540 		    (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
   1541 		     smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
   1542 		    (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
   1543 		     smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
   1544 		    (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
   1545 		     od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
   1546 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
   1547 				OD8_GFXCLK_CURVE;
   1548 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
   1549 				OD8_GFXCLK_CURVE;
   1550 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
   1551 				OD8_GFXCLK_CURVE;
   1552 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
   1553 				OD8_GFXCLK_CURVE;
   1554 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
   1555 				OD8_GFXCLK_CURVE;
   1556 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
   1557 				OD8_GFXCLK_CURVE;
   1558 
   1559 			od_table->GfxclkFreq1 = od_table->GfxclkFmin;
   1560 			od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
   1561 			od_table->GfxclkFreq3 = od_table->GfxclkFmax;
   1562 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
   1563 				od_table->GfxclkFreq1;
   1564 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
   1565 				od_table->GfxclkFreq2;
   1566 			od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
   1567 				od_table->GfxclkFreq3;
   1568 
   1569 			ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
   1570 				&od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
   1571 				od_table->GfxclkFreq1);
   1572 			if (ret)
   1573 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
   1574 			od_table->GfxclkVolt1 =
   1575 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
   1576 				* VOLTAGE_SCALE;
   1577 			ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
   1578 				&od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
   1579 				od_table->GfxclkFreq2);
   1580 			if (ret)
   1581 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
   1582 			od_table->GfxclkVolt2 =
   1583 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
   1584 				* VOLTAGE_SCALE;
   1585 			ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
   1586 				&od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
   1587 				od_table->GfxclkFreq3);
   1588 			if (ret)
   1589 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
   1590 			od_table->GfxclkVolt3 =
   1591 				od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
   1592 				* VOLTAGE_SCALE;
   1593 		}
   1594 	}
   1595 
   1596 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
   1597 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
   1598 		    od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
   1599 		    od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
   1600 		    (od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
   1601 		     od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
   1602 			od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
   1603 				OD8_UCLK_MAX;
   1604 			od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
   1605 				od_table->UclkFmax;
   1606 		}
   1607 	}
   1608 
   1609 	if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
   1610 	    od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
   1611 	    od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
   1612 	    od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
   1613 	    od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
   1614 		od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
   1615 			OD8_POWER_LIMIT;
   1616 		od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
   1617 			od_table->OverDrivePct;
   1618 	}
   1619 
   1620 	if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) {
   1621 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
   1622 		    od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
   1623 		    od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
   1624 		    (od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
   1625 		     od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
   1626 			od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
   1627 				OD8_ACOUSTIC_LIMIT_SCLK;
   1628 			od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
   1629 				od_table->FanMaximumRpm;
   1630 		}
   1631 
   1632 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
   1633 		    od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
   1634 		    od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
   1635 		    (od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
   1636 		     od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
   1637 			od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
   1638 				OD8_FAN_SPEED_MIN;
   1639 			od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
   1640 				od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
   1641 		}
   1642 	}
   1643 
   1644 	if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) {
   1645 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
   1646 		    od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
   1647 		    od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
   1648 		    (od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
   1649 		     od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
   1650 			od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
   1651 				OD8_TEMPERATURE_FAN;
   1652 			od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
   1653 				od_table->FanTargetTemperature;
   1654 		}
   1655 
   1656 		if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
   1657 		    od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
   1658 		    od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
   1659 		    (od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
   1660 		     od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
   1661 			od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
   1662 				OD8_TEMPERATURE_SYSTEM;
   1663 			od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
   1664 				od_table->MaxOpTemp;
   1665 		}
   1666 	}
   1667 
   1668 	for (i = 0; i < OD8_SETTING_COUNT; i++) {
   1669 		if (od8_settings->od8_settings_array[i].feature_id) {
   1670 			od8_settings->od8_settings_array[i].min_value =
   1671 				od8_settings->od_settings_min[i];
   1672 			od8_settings->od8_settings_array[i].max_value =
   1673 				od8_settings->od_settings_max[i];
   1674 			od8_settings->od8_settings_array[i].current_value =
   1675 				od8_settings->od8_settings_array[i].default_value;
   1676 		} else {
   1677 			od8_settings->od8_settings_array[i].min_value = 0;
   1678 			od8_settings->od8_settings_array[i].max_value = 0;
   1679 			od8_settings->od8_settings_array[i].current_value = 0;
   1680 		}
   1681 	}
   1682 
   1683 	return 0;
   1684 }
   1685 
   1686 static int vega20_get_metrics_table(struct smu_context *smu,
   1687 				    SmuMetrics_t *metrics_table)
   1688 {
   1689 	struct smu_table_context *smu_table= &smu->smu_table;
   1690 	int ret = 0;
   1691 
   1692 	mutex_lock(&smu->metrics_lock);
   1693 	if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
   1694 		ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
   1695 				(void *)smu_table->metrics_table, false);
   1696 		if (ret) {
   1697 			pr_info("Failed to export SMU metrics table!\n");
   1698 			mutex_unlock(&smu->metrics_lock);
   1699 			return ret;
   1700 		}
   1701 		smu_table->metrics_time = jiffies;
   1702 	}
   1703 
   1704 	memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
   1705 	mutex_unlock(&smu->metrics_lock);
   1706 
   1707 	return ret;
   1708 }
   1709 
   1710 static int vega20_set_default_od_settings(struct smu_context *smu,
   1711 					  bool initialize)
   1712 {
   1713 	struct smu_table_context *table_context = &smu->smu_table;
   1714 	int ret;
   1715 
   1716 	ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t));
   1717 	if (ret)
   1718 		return ret;
   1719 
   1720 	if (initialize) {
   1721 		ret = vega20_set_default_od8_setttings(smu);
   1722 		if (ret)
   1723 			return ret;
   1724 	}
   1725 
   1726 	ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
   1727 			       table_context->overdrive_table, true);
   1728 	if (ret) {
   1729 		pr_err("Failed to import over drive table!\n");
   1730 		return ret;
   1731 	}
   1732 
   1733 	return 0;
   1734 }
   1735 
   1736 static int vega20_get_od_percentage(struct smu_context *smu,
   1737 				    enum smu_clk_type clk_type)
   1738 {
   1739 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
   1740 	struct vega20_dpm_table *dpm_table = NULL;
   1741 	struct vega20_dpm_table *golden_table = NULL;
   1742 	struct vega20_single_dpm_table *single_dpm_table;
   1743 	struct vega20_single_dpm_table *golden_dpm_table;
   1744 	int value, golden_value;
   1745 
   1746 	dpm_table = smu_dpm->dpm_context;
   1747 	golden_table = smu_dpm->golden_dpm_context;
   1748 
   1749 	switch (clk_type) {
   1750 	case SMU_OD_SCLK:
   1751 		single_dpm_table = &(dpm_table->gfx_table);
   1752 		golden_dpm_table = &(golden_table->gfx_table);
   1753 		break;
   1754 	case SMU_OD_MCLK:
   1755 		single_dpm_table = &(dpm_table->mem_table);
   1756 		golden_dpm_table = &(golden_table->mem_table);
   1757 		break;
   1758 	default:
   1759 		return -EINVAL;
   1760 		break;
   1761 	}
   1762 
   1763 	value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
   1764 	golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
   1765 
   1766 	value -= golden_value;
   1767 	value = DIV_ROUND_UP(value * 100, golden_value);
   1768 
   1769 	return value;
   1770 }
   1771 
   1772 static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
   1773 {
   1774 	DpmActivityMonitorCoeffInt_t activity_monitor;
   1775 	uint32_t i, size = 0;
   1776 	int16_t workload_type = 0;
   1777 	static const char *profile_name[] = {
   1778 					"BOOTUP_DEFAULT",
   1779 					"3D_FULL_SCREEN",
   1780 					"POWER_SAVING",
   1781 					"VIDEO",
   1782 					"VR",
   1783 					"COMPUTE",
   1784 					"CUSTOM"};
   1785 	static const char *title[] = {
   1786 			"PROFILE_INDEX(NAME)",
   1787 			"CLOCK_TYPE(NAME)",
   1788 			"FPS",
   1789 			"UseRlcBusy",
   1790 			"MinActiveFreqType",
   1791 			"MinActiveFreq",
   1792 			"BoosterFreqType",
   1793 			"BoosterFreq",
   1794 			"PD_Data_limit_c",
   1795 			"PD_Data_error_coeff",
   1796 			"PD_Data_error_rate_coeff"};
   1797 	int result = 0;
   1798 
   1799 	if (!smu->pm_enabled || !buf)
   1800 		return -EINVAL;
   1801 
   1802 	size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
   1803 			title[0], title[1], title[2], title[3], title[4], title[5],
   1804 			title[6], title[7], title[8], title[9], title[10]);
   1805 
   1806 	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
   1807 		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
   1808 		workload_type = smu_workload_get_type(smu, i);
   1809 		if (workload_type < 0)
   1810 			return -EINVAL;
   1811 
   1812 		result = smu_update_table(smu,
   1813 					  SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
   1814 					  (void *)(&activity_monitor), false);
   1815 		if (result) {
   1816 			pr_err("[%s] Failed to get activity monitor!", __func__);
   1817 			return result;
   1818 		}
   1819 
   1820 		size += sprintf(buf + size, "%2d %14s%s:\n",
   1821 			i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
   1822 
   1823 		size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
   1824 			" ",
   1825 			0,
   1826 			"GFXCLK",
   1827 			activity_monitor.Gfx_FPS,
   1828 			activity_monitor.Gfx_UseRlcBusy,
   1829 			activity_monitor.Gfx_MinActiveFreqType,
   1830 			activity_monitor.Gfx_MinActiveFreq,
   1831 			activity_monitor.Gfx_BoosterFreqType,
   1832 			activity_monitor.Gfx_BoosterFreq,
   1833 			activity_monitor.Gfx_PD_Data_limit_c,
   1834 			activity_monitor.Gfx_PD_Data_error_coeff,
   1835 			activity_monitor.Gfx_PD_Data_error_rate_coeff);
   1836 
   1837 		size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
   1838 			" ",
   1839 			1,
   1840 			"SOCCLK",
   1841 			activity_monitor.Soc_FPS,
   1842 			activity_monitor.Soc_UseRlcBusy,
   1843 			activity_monitor.Soc_MinActiveFreqType,
   1844 			activity_monitor.Soc_MinActiveFreq,
   1845 			activity_monitor.Soc_BoosterFreqType,
   1846 			activity_monitor.Soc_BoosterFreq,
   1847 			activity_monitor.Soc_PD_Data_limit_c,
   1848 			activity_monitor.Soc_PD_Data_error_coeff,
   1849 			activity_monitor.Soc_PD_Data_error_rate_coeff);
   1850 
   1851 		size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
   1852 			" ",
   1853 			2,
   1854 			"UCLK",
   1855 			activity_monitor.Mem_FPS,
   1856 			activity_monitor.Mem_UseRlcBusy,
   1857 			activity_monitor.Mem_MinActiveFreqType,
   1858 			activity_monitor.Mem_MinActiveFreq,
   1859 			activity_monitor.Mem_BoosterFreqType,
   1860 			activity_monitor.Mem_BoosterFreq,
   1861 			activity_monitor.Mem_PD_Data_limit_c,
   1862 			activity_monitor.Mem_PD_Data_error_coeff,
   1863 			activity_monitor.Mem_PD_Data_error_rate_coeff);
   1864 
   1865 		size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
   1866 			" ",
   1867 			3,
   1868 			"FCLK",
   1869 			activity_monitor.Fclk_FPS,
   1870 			activity_monitor.Fclk_UseRlcBusy,
   1871 			activity_monitor.Fclk_MinActiveFreqType,
   1872 			activity_monitor.Fclk_MinActiveFreq,
   1873 			activity_monitor.Fclk_BoosterFreqType,
   1874 			activity_monitor.Fclk_BoosterFreq,
   1875 			activity_monitor.Fclk_PD_Data_limit_c,
   1876 			activity_monitor.Fclk_PD_Data_error_coeff,
   1877 			activity_monitor.Fclk_PD_Data_error_rate_coeff);
   1878 	}
   1879 
   1880 	return size;
   1881 }
   1882 
   1883 static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
   1884 {
   1885 	DpmActivityMonitorCoeffInt_t activity_monitor;
   1886 	int workload_type = 0, ret = 0;
   1887 
   1888 	smu->power_profile_mode = input[size];
   1889 
   1890 	if (!smu->pm_enabled)
   1891 		return ret;
   1892 	if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
   1893 		pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
   1894 		return -EINVAL;
   1895 	}
   1896 
   1897 	if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
   1898 		ret = smu_update_table(smu,
   1899 				       SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
   1900 				       (void *)(&activity_monitor), false);
   1901 		if (ret) {
   1902 			pr_err("[%s] Failed to get activity monitor!", __func__);
   1903 			return ret;
   1904 		}
   1905 
   1906 		switch (input[0]) {
   1907 		case 0: /* Gfxclk */
   1908 			activity_monitor.Gfx_FPS = input[1];
   1909 			activity_monitor.Gfx_UseRlcBusy = input[2];
   1910 			activity_monitor.Gfx_MinActiveFreqType = input[3];
   1911 			activity_monitor.Gfx_MinActiveFreq = input[4];
   1912 			activity_monitor.Gfx_BoosterFreqType = input[5];
   1913 			activity_monitor.Gfx_BoosterFreq = input[6];
   1914 			activity_monitor.Gfx_PD_Data_limit_c = input[7];
   1915 			activity_monitor.Gfx_PD_Data_error_coeff = input[8];
   1916 			activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
   1917 			break;
   1918 		case 1: /* Socclk */
   1919 			activity_monitor.Soc_FPS = input[1];
   1920 			activity_monitor.Soc_UseRlcBusy = input[2];
   1921 			activity_monitor.Soc_MinActiveFreqType = input[3];
   1922 			activity_monitor.Soc_MinActiveFreq = input[4];
   1923 			activity_monitor.Soc_BoosterFreqType = input[5];
   1924 			activity_monitor.Soc_BoosterFreq = input[6];
   1925 			activity_monitor.Soc_PD_Data_limit_c = input[7];
   1926 			activity_monitor.Soc_PD_Data_error_coeff = input[8];
   1927 			activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
   1928 			break;
   1929 		case 2: /* Uclk */
   1930 			activity_monitor.Mem_FPS = input[1];
   1931 			activity_monitor.Mem_UseRlcBusy = input[2];
   1932 			activity_monitor.Mem_MinActiveFreqType = input[3];
   1933 			activity_monitor.Mem_MinActiveFreq = input[4];
   1934 			activity_monitor.Mem_BoosterFreqType = input[5];
   1935 			activity_monitor.Mem_BoosterFreq = input[6];
   1936 			activity_monitor.Mem_PD_Data_limit_c = input[7];
   1937 			activity_monitor.Mem_PD_Data_error_coeff = input[8];
   1938 			activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
   1939 			break;
   1940 		case 3: /* Fclk */
   1941 			activity_monitor.Fclk_FPS = input[1];
   1942 			activity_monitor.Fclk_UseRlcBusy = input[2];
   1943 			activity_monitor.Fclk_MinActiveFreqType = input[3];
   1944 			activity_monitor.Fclk_MinActiveFreq = input[4];
   1945 			activity_monitor.Fclk_BoosterFreqType = input[5];
   1946 			activity_monitor.Fclk_BoosterFreq = input[6];
   1947 			activity_monitor.Fclk_PD_Data_limit_c = input[7];
   1948 			activity_monitor.Fclk_PD_Data_error_coeff = input[8];
   1949 			activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
   1950 			break;
   1951 		}
   1952 
   1953 		ret = smu_update_table(smu,
   1954 				       SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
   1955 				       (void *)(&activity_monitor), true);
   1956 		if (ret) {
   1957 			pr_err("[%s] Failed to set activity monitor!", __func__);
   1958 			return ret;
   1959 		}
   1960 	}
   1961 
   1962 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
   1963 	workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
   1964 	if (workload_type < 0)
   1965 		return -EINVAL;
   1966 	smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
   1967 				    1 << workload_type);
   1968 
   1969 	return ret;
   1970 }
   1971 
   1972 static int
   1973 vega20_get_profiling_clk_mask(struct smu_context *smu,
   1974 			      enum amd_dpm_forced_level level,
   1975 			      uint32_t *sclk_mask,
   1976 			      uint32_t *mclk_mask,
   1977 			      uint32_t *soc_mask)
   1978 {
   1979 	struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
   1980 	struct vega20_single_dpm_table *gfx_dpm_table;
   1981 	struct vega20_single_dpm_table *mem_dpm_table;
   1982 	struct vega20_single_dpm_table *soc_dpm_table;
   1983 
   1984 	if (!smu->smu_dpm.dpm_context)
   1985 		return -EINVAL;
   1986 
   1987 	gfx_dpm_table = &dpm_table->gfx_table;
   1988 	mem_dpm_table = &dpm_table->mem_table;
   1989 	soc_dpm_table = &dpm_table->soc_table;
   1990 
   1991 	*sclk_mask = 0;
   1992 	*mclk_mask = 0;
   1993 	*soc_mask  = 0;
   1994 
   1995 	if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
   1996 	    mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
   1997 	    soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
   1998 		*sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
   1999 		*mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
   2000 		*soc_mask  = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
   2001 	}
   2002 
   2003 	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
   2004 		*sclk_mask = 0;
   2005 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
   2006 		*mclk_mask = 0;
   2007 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2008 		*sclk_mask = gfx_dpm_table->count - 1;
   2009 		*mclk_mask = mem_dpm_table->count - 1;
   2010 		*soc_mask  = soc_dpm_table->count - 1;
   2011 	}
   2012 
   2013 	return 0;
   2014 }
   2015 
   2016 static int
   2017 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
   2018 				     struct vega20_single_dpm_table *dpm_table)
   2019 {
   2020 	int ret = 0;
   2021 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
   2022 	if (!smu_dpm_ctx->dpm_context)
   2023 		return -EINVAL;
   2024 
   2025 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
   2026 		if (dpm_table->count <= 0) {
   2027 			pr_err("[%s] Dpm table has no entry!", __func__);
   2028 				return -EINVAL;
   2029 		}
   2030 
   2031 		if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
   2032 			pr_err("[%s] Dpm table has too many entries!", __func__);
   2033 				return -EINVAL;
   2034 		}
   2035 
   2036 		dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2037 		ret = smu_send_smc_msg_with_param(smu,
   2038 				SMU_MSG_SetHardMinByFreq,
   2039 				(PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
   2040 		if (ret) {
   2041 			pr_err("[%s] Set hard min uclk failed!", __func__);
   2042 				return ret;
   2043 		}
   2044 	}
   2045 
   2046 	return ret;
   2047 }
   2048 
   2049 static int vega20_pre_display_config_changed(struct smu_context *smu)
   2050 {
   2051 	int ret = 0;
   2052 	struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
   2053 
   2054 	if (!smu->smu_dpm.dpm_context)
   2055 		return -EINVAL;
   2056 
   2057 	smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
   2058 	ret = vega20_set_uclk_to_highest_dpm_level(smu,
   2059 						   &dpm_table->mem_table);
   2060 	if (ret)
   2061 		pr_err("Failed to set uclk to highest dpm level");
   2062 	return ret;
   2063 }
   2064 
   2065 static int vega20_display_config_changed(struct smu_context *smu)
   2066 {
   2067 	int ret = 0;
   2068 
   2069 	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
   2070 	    !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
   2071 		ret = smu_write_watermarks_table(smu);
   2072 		if (ret) {
   2073 			pr_err("Failed to update WMTABLE!");
   2074 			return ret;
   2075 		}
   2076 		smu->watermarks_bitmap |= WATERMARKS_LOADED;
   2077 	}
   2078 
   2079 	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
   2080 	    smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
   2081 	    smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
   2082 		smu_send_smc_msg_with_param(smu,
   2083 					    SMU_MSG_NumOfDisplays,
   2084 					    smu->display_config->num_display);
   2085 	}
   2086 
   2087 	return ret;
   2088 }
   2089 
   2090 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
   2091 {
   2092 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
   2093 	struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
   2094 	struct vega20_single_dpm_table *dpm_table;
   2095 	bool vblank_too_short = false;
   2096 	bool disable_mclk_switching;
   2097 	uint32_t i, latency;
   2098 
   2099 	disable_mclk_switching = ((1 < smu->display_config->num_display) &&
   2100 				  !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
   2101 	latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
   2102 
   2103 	/* gfxclk */
   2104 	dpm_table = &(dpm_ctx->gfx_table);
   2105 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2106 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2107 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2108 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2109 
   2110 		if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
   2111 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
   2112 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
   2113 		}
   2114 
   2115 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
   2116 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2117 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
   2118 		}
   2119 
   2120 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2121 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2122 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2123 		}
   2124 
   2125 	/* memclk */
   2126 	dpm_table = &(dpm_ctx->mem_table);
   2127 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2128 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2129 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2130 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2131 
   2132 		if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
   2133 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
   2134 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
   2135 		}
   2136 
   2137 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
   2138 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2139 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
   2140 		}
   2141 
   2142 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2143 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2144 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2145 		}
   2146 
   2147 	/* honour DAL's UCLK Hardmin */
   2148 	if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
   2149 		dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
   2150 
   2151 	/* Hardmin is dependent on displayconfig */
   2152 	if (disable_mclk_switching) {
   2153 		dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2154 		for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
   2155 			if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
   2156 				if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
   2157 					dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
   2158 					break;
   2159 				}
   2160 			}
   2161 		}
   2162 	}
   2163 
   2164 	if (smu->display_config->nb_pstate_switch_disable)
   2165 		dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2166 
   2167 	/* vclk */
   2168 	dpm_table = &(dpm_ctx->vclk_table);
   2169 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2170 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2171 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2172 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2173 
   2174 		if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
   2175 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
   2176 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
   2177 		}
   2178 
   2179 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2180 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2181 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2182 		}
   2183 
   2184 	/* dclk */
   2185 	dpm_table = &(dpm_ctx->dclk_table);
   2186 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2187 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2188 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2189 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2190 
   2191 		if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
   2192 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
   2193 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
   2194 		}
   2195 
   2196 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2197 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2198 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2199 		}
   2200 
   2201 	/* socclk */
   2202 	dpm_table = &(dpm_ctx->soc_table);
   2203 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2204 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2205 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2206 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2207 
   2208 		if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
   2209 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
   2210 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
   2211 		}
   2212 
   2213 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2214 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2215 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2216 		}
   2217 
   2218 	/* eclk */
   2219 	dpm_table = &(dpm_ctx->eclk_table);
   2220 	dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
   2221 	dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2222 	dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
   2223 	dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2224 
   2225 		if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
   2226 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
   2227 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
   2228 		}
   2229 
   2230 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
   2231 			dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2232 			dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
   2233 		}
   2234 	return 0;
   2235 }
   2236 
   2237 static int
   2238 vega20_notify_smc_display_config(struct smu_context *smu)
   2239 {
   2240 	struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
   2241 	struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
   2242 	struct smu_clocks min_clocks = {0};
   2243 	struct pp_display_clock_request clock_req;
   2244 	int ret = 0;
   2245 
   2246 	min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
   2247 	min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
   2248 	min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
   2249 
   2250 	if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
   2251 		clock_req.clock_type = amd_pp_dcef_clock;
   2252 		clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
   2253 		if (!smu_v11_0_display_clock_voltage_request(smu, &clock_req)) {
   2254 			if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
   2255 				ret = smu_send_smc_msg_with_param(smu,
   2256 								  SMU_MSG_SetMinDeepSleepDcefclk,
   2257 								  min_clocks.dcef_clock_in_sr/100);
   2258 				if (ret) {
   2259 					pr_err("Attempt to set divider for DCEFCLK Failed!");
   2260 					return ret;
   2261 				}
   2262 			}
   2263 		} else {
   2264 			pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
   2265 		}
   2266 	}
   2267 
   2268 	if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
   2269 		memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
   2270 		ret = smu_send_smc_msg_with_param(smu,
   2271 						  SMU_MSG_SetHardMinByFreq,
   2272 						  (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
   2273 		if (ret) {
   2274 			pr_err("[%s] Set hard min uclk failed!", __func__);
   2275 			return ret;
   2276 		}
   2277 	}
   2278 
   2279 	return 0;
   2280 }
   2281 
   2282 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
   2283 {
   2284 	uint32_t i;
   2285 
   2286 	for (i = 0; i < table->count; i++) {
   2287 		if (table->dpm_levels[i].enabled)
   2288 			break;
   2289 	}
   2290 	if (i >= table->count) {
   2291 		i = 0;
   2292 		table->dpm_levels[i].enabled = true;
   2293 	}
   2294 
   2295 	return i;
   2296 }
   2297 
   2298 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
   2299 {
   2300 	int i = 0;
   2301 
   2302 	if (!table) {
   2303 		pr_err("[%s] DPM Table does not exist!", __func__);
   2304 		return 0;
   2305 	}
   2306 	if (table->count <= 0) {
   2307 		pr_err("[%s] DPM Table has no entry!", __func__);
   2308 		return 0;
   2309 	}
   2310 	if (table->count > MAX_REGULAR_DPM_NUMBER) {
   2311 		pr_err("[%s] DPM Table has too many entries!", __func__);
   2312 		return MAX_REGULAR_DPM_NUMBER - 1;
   2313 	}
   2314 
   2315 	for (i = table->count - 1; i >= 0; i--) {
   2316 		if (table->dpm_levels[i].enabled)
   2317 			break;
   2318 	}
   2319 	if (i < 0) {
   2320 		i = 0;
   2321 		table->dpm_levels[i].enabled = true;
   2322 	}
   2323 
   2324 	return i;
   2325 }
   2326 
   2327 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
   2328 {
   2329 	uint32_t soft_level;
   2330 	int ret = 0;
   2331 	struct vega20_dpm_table *dpm_table =
   2332 		(struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
   2333 
   2334 	if (highest)
   2335 		soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
   2336 	else
   2337 		soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
   2338 
   2339 	dpm_table->gfx_table.dpm_state.soft_min_level =
   2340 		dpm_table->gfx_table.dpm_state.soft_max_level =
   2341 		dpm_table->gfx_table.dpm_levels[soft_level].value;
   2342 
   2343 	if (highest)
   2344 		soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
   2345 	else
   2346 		soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
   2347 
   2348 	dpm_table->mem_table.dpm_state.soft_min_level =
   2349 		dpm_table->mem_table.dpm_state.soft_max_level =
   2350 		dpm_table->mem_table.dpm_levels[soft_level].value;
   2351 
   2352 	if (highest)
   2353 		soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
   2354 	else
   2355 		soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
   2356 
   2357 	dpm_table->soc_table.dpm_state.soft_min_level =
   2358 		dpm_table->soc_table.dpm_state.soft_max_level =
   2359 		dpm_table->soc_table.dpm_levels[soft_level].value;
   2360 
   2361 	ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
   2362 	if (ret) {
   2363 		pr_err("Failed to upload boot level to %s!\n",
   2364 				highest ? "highest" : "lowest");
   2365 		return ret;
   2366 	}
   2367 
   2368 	ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
   2369 	if (ret) {
   2370 		pr_err("Failed to upload dpm max level to %s!\n!",
   2371 				highest ? "highest" : "lowest");
   2372 		return ret;
   2373 	}
   2374 
   2375 	return ret;
   2376 }
   2377 
   2378 static int vega20_unforce_dpm_levels(struct smu_context *smu)
   2379 {
   2380 	uint32_t soft_min_level, soft_max_level;
   2381 	int ret = 0;
   2382 	struct vega20_dpm_table *dpm_table =
   2383 		(struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
   2384 
   2385 	soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
   2386 	soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
   2387 	dpm_table->gfx_table.dpm_state.soft_min_level =
   2388 		dpm_table->gfx_table.dpm_levels[soft_min_level].value;
   2389 	dpm_table->gfx_table.dpm_state.soft_max_level =
   2390 		dpm_table->gfx_table.dpm_levels[soft_max_level].value;
   2391 
   2392 	soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
   2393 	soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
   2394 	dpm_table->mem_table.dpm_state.soft_min_level =
   2395 		dpm_table->gfx_table.dpm_levels[soft_min_level].value;
   2396 	dpm_table->mem_table.dpm_state.soft_max_level =
   2397 		dpm_table->gfx_table.dpm_levels[soft_max_level].value;
   2398 
   2399 	soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
   2400 	soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
   2401 	dpm_table->soc_table.dpm_state.soft_min_level =
   2402 		dpm_table->soc_table.dpm_levels[soft_min_level].value;
   2403 	dpm_table->soc_table.dpm_state.soft_max_level =
   2404 		dpm_table->soc_table.dpm_levels[soft_max_level].value;
   2405 
   2406 	ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
   2407 	if (ret) {
   2408 		pr_err("Failed to upload DPM Bootup Levels!");
   2409 		return ret;
   2410 	}
   2411 
   2412 	ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
   2413 	if (ret) {
   2414 		pr_err("Failed to upload DPM Max Levels!");
   2415 		return ret;
   2416 	}
   2417 
   2418 	return ret;
   2419 }
   2420 
   2421 static int vega20_update_specified_od8_value(struct smu_context *smu,
   2422 					     uint32_t index,
   2423 					     uint32_t value)
   2424 {
   2425 	struct smu_table_context *table_context = &smu->smu_table;
   2426 	OverDriveTable_t *od_table =
   2427 		(OverDriveTable_t *)(table_context->overdrive_table);
   2428 	struct vega20_od8_settings *od8_settings =
   2429 		(struct vega20_od8_settings *)smu->od_settings;
   2430 
   2431 	switch (index) {
   2432 	case OD8_SETTING_GFXCLK_FMIN:
   2433 		od_table->GfxclkFmin = (uint16_t)value;
   2434 		break;
   2435 
   2436 	case OD8_SETTING_GFXCLK_FMAX:
   2437 		if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
   2438 		    value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
   2439 			return -EINVAL;
   2440 		od_table->GfxclkFmax = (uint16_t)value;
   2441 		break;
   2442 
   2443 	case OD8_SETTING_GFXCLK_FREQ1:
   2444 		od_table->GfxclkFreq1 = (uint16_t)value;
   2445 		break;
   2446 
   2447 	case OD8_SETTING_GFXCLK_VOLTAGE1:
   2448 		od_table->GfxclkVolt1 = (uint16_t)value;
   2449 		break;
   2450 
   2451 	case OD8_SETTING_GFXCLK_FREQ2:
   2452 		od_table->GfxclkFreq2 = (uint16_t)value;
   2453 		break;
   2454 
   2455 	case OD8_SETTING_GFXCLK_VOLTAGE2:
   2456 		od_table->GfxclkVolt2 = (uint16_t)value;
   2457 		break;
   2458 
   2459 	case OD8_SETTING_GFXCLK_FREQ3:
   2460 		od_table->GfxclkFreq3 = (uint16_t)value;
   2461 		break;
   2462 
   2463 	case OD8_SETTING_GFXCLK_VOLTAGE3:
   2464 		od_table->GfxclkVolt3 = (uint16_t)value;
   2465 		break;
   2466 
   2467 	case OD8_SETTING_UCLK_FMAX:
   2468 		if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
   2469 		    value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
   2470 			return -EINVAL;
   2471 		od_table->UclkFmax = (uint16_t)value;
   2472 		break;
   2473 
   2474 	case OD8_SETTING_POWER_PERCENTAGE:
   2475 		od_table->OverDrivePct = (int16_t)value;
   2476 		break;
   2477 
   2478 	case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
   2479 		od_table->FanMaximumRpm = (uint16_t)value;
   2480 		break;
   2481 
   2482 	case OD8_SETTING_FAN_MIN_SPEED:
   2483 		od_table->FanMinimumPwm = (uint16_t)value;
   2484 		break;
   2485 
   2486 	case OD8_SETTING_FAN_TARGET_TEMP:
   2487 		od_table->FanTargetTemperature = (uint16_t)value;
   2488 		break;
   2489 
   2490 	case OD8_SETTING_OPERATING_TEMP_MAX:
   2491 		od_table->MaxOpTemp = (uint16_t)value;
   2492 		break;
   2493 	}
   2494 
   2495 	return 0;
   2496 }
   2497 
   2498 static int vega20_update_od8_settings(struct smu_context *smu,
   2499 				      uint32_t index,
   2500 				      uint32_t value)
   2501 {
   2502 	struct smu_table_context *table_context = &smu->smu_table;
   2503 	int ret;
   2504 
   2505 	ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
   2506 			       table_context->overdrive_table, false);
   2507 	if (ret) {
   2508 		pr_err("Failed to export over drive table!\n");
   2509 		return ret;
   2510 	}
   2511 
   2512 	ret = vega20_update_specified_od8_value(smu, index, value);
   2513 	if (ret)
   2514 		return ret;
   2515 
   2516 	ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
   2517 			       table_context->overdrive_table, true);
   2518 	if (ret) {
   2519 		pr_err("Failed to import over drive table!\n");
   2520 		return ret;
   2521 	}
   2522 
   2523 	return 0;
   2524 }
   2525 
   2526 static int vega20_set_od_percentage(struct smu_context *smu,
   2527 				    enum smu_clk_type clk_type,
   2528 				    uint32_t value)
   2529 {
   2530 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
   2531 	struct vega20_dpm_table *dpm_table = NULL;
   2532 	struct vega20_dpm_table *golden_table = NULL;
   2533 	struct vega20_single_dpm_table *single_dpm_table;
   2534 	struct vega20_single_dpm_table *golden_dpm_table;
   2535 	uint32_t od_clk, index;
   2536 	int ret = 0;
   2537 	int feature_enabled;
   2538 	PPCLK_e clk_id;
   2539 
   2540 	dpm_table = smu_dpm->dpm_context;
   2541 	golden_table = smu_dpm->golden_dpm_context;
   2542 
   2543 	switch (clk_type) {
   2544 	case SMU_OD_SCLK:
   2545 		single_dpm_table = &(dpm_table->gfx_table);
   2546 		golden_dpm_table = &(golden_table->gfx_table);
   2547 		feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT);
   2548 		clk_id = PPCLK_GFXCLK;
   2549 		index = OD8_SETTING_GFXCLK_FMAX;
   2550 		break;
   2551 	case SMU_OD_MCLK:
   2552 		single_dpm_table = &(dpm_table->mem_table);
   2553 		golden_dpm_table = &(golden_table->mem_table);
   2554 		feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT);
   2555 		clk_id = PPCLK_UCLK;
   2556 		index = OD8_SETTING_UCLK_FMAX;
   2557 		break;
   2558 	default:
   2559 		ret = -EINVAL;
   2560 		break;
   2561 	}
   2562 
   2563 	if (ret)
   2564 		goto set_od_failed;
   2565 
   2566 	od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
   2567 	od_clk /= 100;
   2568 	od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
   2569 
   2570 	ret = vega20_update_od8_settings(smu, index, od_clk);
   2571 	if (ret) {
   2572 		pr_err("[Setoverdrive] failed to set od clk!\n");
   2573 		goto set_od_failed;
   2574 	}
   2575 
   2576 	if (feature_enabled) {
   2577 		ret = vega20_set_single_dpm_table(smu, single_dpm_table,
   2578 						  clk_id);
   2579 		if (ret) {
   2580 			pr_err("[Setoverdrive] failed to refresh dpm table!\n");
   2581 			goto set_od_failed;
   2582 		}
   2583 	} else {
   2584 		single_dpm_table->count = 1;
   2585 		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
   2586 	}
   2587 
   2588 	ret = smu_handle_task(smu, smu_dpm->dpm_level,
   2589 			      AMD_PP_TASK_READJUST_POWER_STATE,
   2590 			      false);
   2591 
   2592 set_od_failed:
   2593 	return ret;
   2594 }
   2595 
   2596 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
   2597 				     enum PP_OD_DPM_TABLE_COMMAND type,
   2598 				     long *input, uint32_t size)
   2599 {
   2600 	struct smu_table_context *table_context = &smu->smu_table;
   2601 	OverDriveTable_t *od_table =
   2602 		(OverDriveTable_t *)(table_context->overdrive_table);
   2603 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
   2604 	struct vega20_dpm_table *dpm_table = NULL;
   2605 	struct vega20_single_dpm_table *single_dpm_table;
   2606 	struct vega20_od8_settings *od8_settings =
   2607 		(struct vega20_od8_settings *)smu->od_settings;
   2608 	struct pp_clock_levels_with_latency clocks;
   2609 	int32_t input_index, input_clk, input_vol, i;
   2610 	int od8_id;
   2611 	int ret = 0;
   2612 
   2613 	dpm_table = smu_dpm->dpm_context;
   2614 
   2615 	if (!input) {
   2616 		pr_warn("NULL user input for clock and voltage\n");
   2617 		return -EINVAL;
   2618 	}
   2619 
   2620 	switch (type) {
   2621 	case PP_OD_EDIT_SCLK_VDDC_TABLE:
   2622 		if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
   2623 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
   2624 			pr_info("Sclk min/max frequency overdrive not supported\n");
   2625 			return -EOPNOTSUPP;
   2626 		}
   2627 
   2628 		for (i = 0; i < size; i += 2) {
   2629 			if (i + 2 > size) {
   2630 				pr_info("invalid number of input parameters %d\n", size);
   2631 				return -EINVAL;
   2632 			}
   2633 
   2634 			input_index = input[i];
   2635 			input_clk = input[i + 1];
   2636 
   2637 			if (input_index != 0 && input_index != 1) {
   2638 				pr_info("Invalid index %d\n", input_index);
   2639 				pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
   2640 				return -EINVAL;
   2641 			}
   2642 
   2643 			if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
   2644 			    input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
   2645 				pr_info("clock freq %d is not within allowed range [%d - %d]\n",
   2646 					input_clk,
   2647 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
   2648 					od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
   2649 				return -EINVAL;
   2650 			}
   2651 
   2652 			if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
   2653 				od_table->GfxclkFmin = input_clk;
   2654 				od8_settings->od_gfxclk_update = true;
   2655 			} else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
   2656 				od_table->GfxclkFmax = input_clk;
   2657 				od8_settings->od_gfxclk_update = true;
   2658 			}
   2659 		}
   2660 
   2661 		break;
   2662 
   2663 	case PP_OD_EDIT_MCLK_VDDC_TABLE:
   2664 		if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
   2665 			pr_info("Mclk max frequency overdrive not supported\n");
   2666 			return -EOPNOTSUPP;
   2667 		}
   2668 
   2669 		single_dpm_table = &(dpm_table->mem_table);
   2670 		ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
   2671 		if (ret) {
   2672 			pr_err("Attempt to get memory clk levels Failed!");
   2673 			return ret;
   2674 		}
   2675 
   2676 		for (i = 0; i < size; i += 2) {
   2677 			if (i + 2 > size) {
   2678 				pr_info("invalid number of input parameters %d\n",
   2679 					 size);
   2680 				return -EINVAL;
   2681 			}
   2682 
   2683 			input_index = input[i];
   2684 			input_clk = input[i + 1];
   2685 
   2686 			if (input_index != 1) {
   2687 				pr_info("Invalid index %d\n", input_index);
   2688 				pr_info("Support max Mclk frequency setting only which index by 1\n");
   2689 				return -EINVAL;
   2690 			}
   2691 
   2692 			if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
   2693 			    input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
   2694 				pr_info("clock freq %d is not within allowed range [%d - %d]\n",
   2695 					input_clk,
   2696 					clocks.data[0].clocks_in_khz / 1000,
   2697 					od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
   2698 				return -EINVAL;
   2699 			}
   2700 
   2701 			if (input_index == 1 && od_table->UclkFmax != input_clk) {
   2702 				od8_settings->od_gfxclk_update = true;
   2703 				od_table->UclkFmax = input_clk;
   2704 			}
   2705 		}
   2706 
   2707 		break;
   2708 
   2709 	case PP_OD_EDIT_VDDC_CURVE:
   2710 		if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
   2711 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
   2712 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
   2713 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
   2714 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
   2715 		      od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
   2716 			pr_info("Voltage curve calibrate not supported\n");
   2717 			return -EOPNOTSUPP;
   2718 		}
   2719 
   2720 		for (i = 0; i < size; i += 3) {
   2721 			if (i + 3 > size) {
   2722 				pr_info("invalid number of input parameters %d\n",
   2723 					size);
   2724 				return -EINVAL;
   2725 			}
   2726 
   2727 			input_index = input[i];
   2728 			input_clk = input[i + 1];
   2729 			input_vol = input[i + 2];
   2730 
   2731 			if (input_index > 2) {
   2732 				pr_info("Setting for point %d is not supported\n",
   2733 					input_index + 1);
   2734 				pr_info("Three supported points index by 0, 1, 2\n");
   2735 				return -EINVAL;
   2736 			}
   2737 
   2738 			od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
   2739 			if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
   2740 			    input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
   2741 				pr_info("clock freq %d is not within allowed range [%d - %d]\n",
   2742 					input_clk,
   2743 					od8_settings->od8_settings_array[od8_id].min_value,
   2744 					od8_settings->od8_settings_array[od8_id].max_value);
   2745 				return -EINVAL;
   2746 			}
   2747 
   2748 			od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
   2749 			if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
   2750 			    input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
   2751 				pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
   2752 					input_vol,
   2753 					od8_settings->od8_settings_array[od8_id].min_value,
   2754 					od8_settings->od8_settings_array[od8_id].max_value);
   2755 				return -EINVAL;
   2756 			}
   2757 
   2758 			switch (input_index) {
   2759 			case 0:
   2760 				od_table->GfxclkFreq1 = input_clk;
   2761 				od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
   2762 				break;
   2763 			case 1:
   2764 				od_table->GfxclkFreq2 = input_clk;
   2765 				od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
   2766 				break;
   2767 			case 2:
   2768 				od_table->GfxclkFreq3 = input_clk;
   2769 				od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
   2770 				break;
   2771 			}
   2772 		}
   2773 
   2774 		break;
   2775 
   2776 	case PP_OD_RESTORE_DEFAULT_TABLE:
   2777 		if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) {
   2778 			pr_err("Overdrive table was not initialized!\n");
   2779 			return -EINVAL;
   2780 		}
   2781 		memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
   2782 		break;
   2783 
   2784 	case PP_OD_COMMIT_DPM_TABLE:
   2785 		ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
   2786 		if (ret) {
   2787 			pr_err("Failed to import over drive table!\n");
   2788 			return ret;
   2789 		}
   2790 
   2791 		/* retrieve updated gfxclk table */
   2792 		if (od8_settings->od_gfxclk_update) {
   2793 			od8_settings->od_gfxclk_update = false;
   2794 			single_dpm_table = &(dpm_table->gfx_table);
   2795 
   2796 			if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
   2797 				ret = vega20_set_single_dpm_table(smu, single_dpm_table,
   2798 								  PPCLK_GFXCLK);
   2799 				if (ret) {
   2800 					pr_err("[Setoverdrive] failed to refresh dpm table!\n");
   2801 					return ret;
   2802 				}
   2803 			} else {
   2804 				single_dpm_table->count = 1;
   2805 				single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
   2806 			}
   2807 		}
   2808 
   2809 		break;
   2810 
   2811 	default:
   2812 		return -EINVAL;
   2813 	}
   2814 
   2815 	if (type == PP_OD_COMMIT_DPM_TABLE) {
   2816 		ret = smu_handle_task(smu, smu_dpm->dpm_level,
   2817 				      AMD_PP_TASK_READJUST_POWER_STATE,
   2818 				      false);
   2819 	}
   2820 
   2821 	return ret;
   2822 }
   2823 
   2824 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
   2825 {
   2826 	if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
   2827 		return 0;
   2828 
   2829 	if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
   2830 		return 0;
   2831 
   2832 	return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
   2833 }
   2834 
   2835 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
   2836 {
   2837 	if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
   2838 		return 0;
   2839 
   2840 	if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
   2841 		return 0;
   2842 
   2843 	return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
   2844 }
   2845 
   2846 static bool vega20_is_dpm_running(struct smu_context *smu)
   2847 {
   2848 	int ret __unused = 0;
   2849 	uint32_t feature_mask[2];
   2850 	unsigned long feature_enabled;
   2851 	ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
   2852 	feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
   2853 			   ((uint64_t)feature_mask[1] << 32));
   2854 	return !!(feature_enabled & SMC_DPM_FEATURE);
   2855 }
   2856 
   2857 static int vega20_set_thermal_fan_table(struct smu_context *smu)
   2858 {
   2859 	int ret;
   2860 	struct smu_table_context *table_context = &smu->smu_table;
   2861 	PPTable_t *pptable = table_context->driver_pptable;
   2862 
   2863 	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
   2864 			(uint32_t)pptable->FanTargetTemperature);
   2865 
   2866 	return ret;
   2867 }
   2868 
   2869 static int vega20_get_fan_speed_rpm(struct smu_context *smu,
   2870 				    uint32_t *speed)
   2871 {
   2872 	int ret;
   2873 
   2874 	ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
   2875 
   2876 	if (ret) {
   2877 		pr_err("Attempt to get current RPM from SMC Failed!\n");
   2878 		return ret;
   2879 	}
   2880 
   2881 	smu_read_smc_arg(smu, speed);
   2882 
   2883 	return 0;
   2884 }
   2885 
   2886 static int vega20_get_fan_speed_percent(struct smu_context *smu,
   2887 					uint32_t *speed)
   2888 {
   2889 	int ret = 0;
   2890 	uint32_t current_rpm = 0, percent = 0;
   2891 	PPTable_t *pptable = smu->smu_table.driver_pptable;
   2892 
   2893 	ret = vega20_get_fan_speed_rpm(smu, &current_rpm);
   2894 	if (ret)
   2895 		return ret;
   2896 
   2897 	percent = current_rpm * 100 / pptable->FanMaximumRpm;
   2898 	*speed = percent > 100 ? 100 : percent;
   2899 
   2900 	return 0;
   2901 }
   2902 
   2903 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
   2904 {
   2905 	uint32_t smu_version;
   2906 	int ret = 0;
   2907 	SmuMetrics_t metrics;
   2908 
   2909 	if (!value)
   2910 		return -EINVAL;
   2911 
   2912 	ret = vega20_get_metrics_table(smu, &metrics);
   2913 	if (ret)
   2914 		return ret;
   2915 
   2916 	ret = smu_get_smc_version(smu, NULL, &smu_version);
   2917 	if (ret)
   2918 		return ret;
   2919 
   2920 	/* For the 40.46 release, they changed the value name */
   2921 	if (smu_version == 0x282e00)
   2922 		*value = metrics.AverageSocketPower << 8;
   2923 	else
   2924 		*value = metrics.CurrSocketPower << 8;
   2925 
   2926 	return 0;
   2927 }
   2928 
   2929 static int vega20_get_current_activity_percent(struct smu_context *smu,
   2930 					       enum amd_pp_sensors sensor,
   2931 					       uint32_t *value)
   2932 {
   2933 	int ret = 0;
   2934 	SmuMetrics_t metrics;
   2935 
   2936 	if (!value)
   2937 		return -EINVAL;
   2938 
   2939 	ret = vega20_get_metrics_table(smu, &metrics);
   2940 	if (ret)
   2941 		return ret;
   2942 
   2943 	switch (sensor) {
   2944 	case AMDGPU_PP_SENSOR_GPU_LOAD:
   2945 		*value = metrics.AverageGfxActivity;
   2946 		break;
   2947 	case AMDGPU_PP_SENSOR_MEM_LOAD:
   2948 		*value = metrics.AverageUclkActivity;
   2949 		break;
   2950 	default:
   2951 		pr_err("Invalid sensor for retrieving clock activity\n");
   2952 		return -EINVAL;
   2953 	}
   2954 
   2955 	return 0;
   2956 }
   2957 
   2958 static int vega20_thermal_get_temperature(struct smu_context *smu,
   2959 					     enum amd_pp_sensors sensor,
   2960 					     uint32_t *value)
   2961 {
   2962 	struct amdgpu_device *adev = smu->adev;
   2963 	SmuMetrics_t metrics;
   2964 	uint32_t temp = 0;
   2965 	int ret = 0;
   2966 
   2967 	if (!value)
   2968 		return -EINVAL;
   2969 
   2970 	ret = vega20_get_metrics_table(smu, &metrics);
   2971 	if (ret)
   2972 		return ret;
   2973 
   2974 	switch (sensor) {
   2975 	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
   2976 		temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
   2977 		temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
   2978 				CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
   2979 
   2980 		temp = temp & 0x1ff;
   2981 		temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   2982 
   2983 		*value = temp;
   2984 		break;
   2985 	case AMDGPU_PP_SENSOR_EDGE_TEMP:
   2986 		*value = metrics.TemperatureEdge *
   2987 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   2988 		break;
   2989 	case AMDGPU_PP_SENSOR_MEM_TEMP:
   2990 		*value = metrics.TemperatureHBM *
   2991 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   2992 		break;
   2993 	default:
   2994 		pr_err("Invalid sensor for retrieving temp\n");
   2995 		return -EINVAL;
   2996 	}
   2997 
   2998 	return 0;
   2999 }
   3000 static int vega20_read_sensor(struct smu_context *smu,
   3001 				 enum amd_pp_sensors sensor,
   3002 				 void *data, uint32_t *size)
   3003 {
   3004 	int ret = 0;
   3005 	struct smu_table_context *table_context = &smu->smu_table;
   3006 	PPTable_t *pptable = table_context->driver_pptable;
   3007 
   3008 	if(!data || !size)
   3009 		return -EINVAL;
   3010 
   3011 	mutex_lock(&smu->sensor_lock);
   3012 	switch (sensor) {
   3013 	case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
   3014 		*(uint32_t *)data = pptable->FanMaximumRpm;
   3015 		*size = 4;
   3016 		break;
   3017 	case AMDGPU_PP_SENSOR_MEM_LOAD:
   3018 	case AMDGPU_PP_SENSOR_GPU_LOAD:
   3019 		ret = vega20_get_current_activity_percent(smu,
   3020 						sensor,
   3021 						(uint32_t *)data);
   3022 		*size = 4;
   3023 		break;
   3024 	case AMDGPU_PP_SENSOR_GPU_POWER:
   3025 		ret = vega20_get_gpu_power(smu, (uint32_t *)data);
   3026 		*size = 4;
   3027 		break;
   3028 	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
   3029 	case AMDGPU_PP_SENSOR_EDGE_TEMP:
   3030 	case AMDGPU_PP_SENSOR_MEM_TEMP:
   3031 		ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
   3032 		*size = 4;
   3033 		break;
   3034 	default:
   3035 		ret = smu_v11_0_read_sensor(smu, sensor, data, size);
   3036 	}
   3037 	mutex_unlock(&smu->sensor_lock);
   3038 
   3039 	return ret;
   3040 }
   3041 
   3042 static int vega20_set_watermarks_table(struct smu_context *smu,
   3043 				       void *watermarks, struct
   3044 				       dm_pp_wm_sets_with_clock_ranges_soc15
   3045 				       *clock_ranges)
   3046 {
   3047 	int i;
   3048 	Watermarks_t *table = watermarks;
   3049 
   3050 	if (!table || !clock_ranges)
   3051 		return -EINVAL;
   3052 
   3053 	if (clock_ranges->num_wm_dmif_sets > 4 ||
   3054 	    clock_ranges->num_wm_mcif_sets > 4)
   3055 		return -EINVAL;
   3056 
   3057 	for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
   3058 		table->WatermarkRow[1][i].MinClock =
   3059 			cpu_to_le16((uint16_t)
   3060 			(clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
   3061 			1000));
   3062 		table->WatermarkRow[1][i].MaxClock =
   3063 			cpu_to_le16((uint16_t)
   3064 			(clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
   3065 			1000));
   3066 		table->WatermarkRow[1][i].MinUclk =
   3067 			cpu_to_le16((uint16_t)
   3068 			(clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
   3069 			1000));
   3070 		table->WatermarkRow[1][i].MaxUclk =
   3071 			cpu_to_le16((uint16_t)
   3072 			(clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
   3073 			1000));
   3074 		table->WatermarkRow[1][i].WmSetting = (uint8_t)
   3075 				clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
   3076 	}
   3077 
   3078 	for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
   3079 		table->WatermarkRow[0][i].MinClock =
   3080 			cpu_to_le16((uint16_t)
   3081 			(clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
   3082 			1000));
   3083 		table->WatermarkRow[0][i].MaxClock =
   3084 			cpu_to_le16((uint16_t)
   3085 			(clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
   3086 			1000));
   3087 		table->WatermarkRow[0][i].MinUclk =
   3088 			cpu_to_le16((uint16_t)
   3089 			(clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
   3090 			1000));
   3091 		table->WatermarkRow[0][i].MaxUclk =
   3092 			cpu_to_le16((uint16_t)
   3093 			(clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
   3094 			1000));
   3095 		table->WatermarkRow[0][i].WmSetting = (uint8_t)
   3096 				clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
   3097 	}
   3098 
   3099 	return 0;
   3100 }
   3101 
   3102 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
   3103 						struct smu_temperature_range *range)
   3104 {
   3105 	struct smu_table_context *table_context = &smu->smu_table;
   3106 	const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
   3107 	PPTable_t *pptable = smu->smu_table.driver_pptable;
   3108 
   3109 	if (!range || !powerplay_table)
   3110 		return -EINVAL;
   3111 
   3112 	range->max = powerplay_table->usSoftwareShutdownTemp *
   3113 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3114 	range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
   3115 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3116 	range->hotspot_crit_max = pptable->ThotspotLimit *
   3117 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3118 	range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
   3119 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3120 	range->mem_crit_max = pptable->ThbmLimit *
   3121 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3122 	range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM) *
   3123 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3124 
   3125 
   3126 	return 0;
   3127 }
   3128 
   3129 static int vega20_set_df_cstate(struct smu_context *smu,
   3130 				enum pp_df_cstate state)
   3131 {
   3132 	uint32_t smu_version;
   3133 	int ret;
   3134 
   3135 	ret = smu_get_smc_version(smu, NULL, &smu_version);
   3136 	if (ret) {
   3137 		pr_err("Failed to get smu version!\n");
   3138 		return ret;
   3139 	}
   3140 
   3141 	/* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
   3142 	if (smu_version < 0x283200) {
   3143 		pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
   3144 		return -EINVAL;
   3145 	}
   3146 
   3147 	return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state);
   3148 }
   3149 
   3150 static int vega20_update_pcie_parameters(struct smu_context *smu,
   3151 				     uint32_t pcie_gen_cap,
   3152 				     uint32_t pcie_width_cap)
   3153 {
   3154 	PPTable_t *pptable = smu->smu_table.driver_pptable;
   3155 	int ret, i;
   3156 	uint32_t smu_pcie_arg;
   3157 
   3158 	for (i = 0; i < NUM_LINK_LEVELS; i++) {
   3159 		smu_pcie_arg = (i << 16) |
   3160 			((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
   3161 				(pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
   3162 					pptable->PcieLaneCount[i] : pcie_width_cap);
   3163 		ret = smu_send_smc_msg_with_param(smu,
   3164 					  SMU_MSG_OverridePcieParameters,
   3165 					  smu_pcie_arg);
   3166 	}
   3167 
   3168 	return ret;
   3169 }
   3170 
   3171 
   3172 static const struct pptable_funcs vega20_ppt_funcs = {
   3173 	.tables_init = vega20_tables_init,
   3174 	.alloc_dpm_context = vega20_allocate_dpm_context,
   3175 	.store_powerplay_table = vega20_store_powerplay_table,
   3176 	.check_powerplay_table = vega20_check_powerplay_table,
   3177 	.append_powerplay_table = vega20_append_powerplay_table,
   3178 	.get_smu_msg_index = vega20_get_smu_msg_index,
   3179 	.get_smu_clk_index = vega20_get_smu_clk_index,
   3180 	.get_smu_feature_index = vega20_get_smu_feature_index,
   3181 	.get_smu_table_index = vega20_get_smu_table_index,
   3182 	.get_smu_power_index = vega20_get_pwr_src_index,
   3183 	.get_workload_type = vega20_get_workload_type,
   3184 	.run_btc = vega20_run_btc_afll,
   3185 	.get_allowed_feature_mask = vega20_get_allowed_feature_mask,
   3186 	.get_current_power_state = vega20_get_current_power_state,
   3187 	.set_default_dpm_table = vega20_set_default_dpm_table,
   3188 	.set_power_state = NULL,
   3189 	.populate_umd_state_clk = vega20_populate_umd_state_clk,
   3190 	.print_clk_levels = vega20_print_clk_levels,
   3191 	.force_clk_levels = vega20_force_clk_levels,
   3192 	.get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
   3193 	.get_od_percentage = vega20_get_od_percentage,
   3194 	.get_power_profile_mode = vega20_get_power_profile_mode,
   3195 	.set_power_profile_mode = vega20_set_power_profile_mode,
   3196 	.set_performance_level = smu_v11_0_set_performance_level,
   3197 	.set_od_percentage = vega20_set_od_percentage,
   3198 	.set_default_od_settings = vega20_set_default_od_settings,
   3199 	.od_edit_dpm_table = vega20_odn_edit_dpm_table,
   3200 	.dpm_set_uvd_enable = vega20_dpm_set_uvd_enable,
   3201 	.dpm_set_vce_enable = vega20_dpm_set_vce_enable,
   3202 	.read_sensor = vega20_read_sensor,
   3203 	.pre_display_config_changed = vega20_pre_display_config_changed,
   3204 	.display_config_changed = vega20_display_config_changed,
   3205 	.apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
   3206 	.notify_smc_display_config = vega20_notify_smc_display_config,
   3207 	.force_dpm_limit_value = vega20_force_dpm_limit_value,
   3208 	.unforce_dpm_levels = vega20_unforce_dpm_levels,
   3209 	.get_profiling_clk_mask = vega20_get_profiling_clk_mask,
   3210 	.is_dpm_running = vega20_is_dpm_running,
   3211 	.set_thermal_fan_table = vega20_set_thermal_fan_table,
   3212 	.get_fan_speed_percent = vega20_get_fan_speed_percent,
   3213 	.get_fan_speed_rpm = vega20_get_fan_speed_rpm,
   3214 	.set_watermarks_table = vega20_set_watermarks_table,
   3215 	.get_thermal_temperature_range = vega20_get_thermal_temperature_range,
   3216 	.set_df_cstate = vega20_set_df_cstate,
   3217 	.update_pcie_parameters = vega20_update_pcie_parameters,
   3218 	.init_microcode = smu_v11_0_init_microcode,
   3219 	.load_microcode = smu_v11_0_load_microcode,
   3220 	.init_smc_tables = smu_v11_0_init_smc_tables,
   3221 	.fini_smc_tables = smu_v11_0_fini_smc_tables,
   3222 	.init_power = smu_v11_0_init_power,
   3223 	.fini_power = smu_v11_0_fini_power,
   3224 	.check_fw_status = smu_v11_0_check_fw_status,
   3225 	.setup_pptable = smu_v11_0_setup_pptable,
   3226 	.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
   3227 	.get_clk_info_from_vbios = smu_v11_0_get_clk_info_from_vbios,
   3228 	.check_pptable = smu_v11_0_check_pptable,
   3229 	.parse_pptable = smu_v11_0_parse_pptable,
   3230 	.populate_smc_tables = smu_v11_0_populate_smc_pptable,
   3231 	.check_fw_version = smu_v11_0_check_fw_version,
   3232 	.write_pptable = smu_v11_0_write_pptable,
   3233 	.set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep,
   3234 	.set_driver_table_location = smu_v11_0_set_driver_table_location,
   3235 	.set_tool_table_location = smu_v11_0_set_tool_table_location,
   3236 	.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
   3237 	.system_features_control = smu_v11_0_system_features_control,
   3238 	.send_smc_msg_with_param = smu_v11_0_send_msg_with_param,
   3239 	.read_smc_arg = smu_v11_0_read_arg,
   3240 	.init_display_count = smu_v11_0_init_display_count,
   3241 	.set_allowed_mask = smu_v11_0_set_allowed_mask,
   3242 	.get_enabled_mask = smu_v11_0_get_enabled_mask,
   3243 	.notify_display_change = smu_v11_0_notify_display_change,
   3244 	.set_power_limit = smu_v11_0_set_power_limit,
   3245 	.get_current_clk_freq = smu_v11_0_get_current_clk_freq,
   3246 	.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
   3247 	.start_thermal_control = smu_v11_0_start_thermal_control,
   3248 	.stop_thermal_control = smu_v11_0_stop_thermal_control,
   3249 	.set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
   3250 	.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
   3251 	.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
   3252 	.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
   3253 	.set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
   3254 	.set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
   3255 	.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
   3256 	.gfx_off_control = smu_v11_0_gfx_off_control,
   3257 	.register_irq_handler = smu_v11_0_register_irq_handler,
   3258 	.set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
   3259 	.get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
   3260 	.baco_is_support= smu_v11_0_baco_is_support,
   3261 	.baco_get_state = smu_v11_0_baco_get_state,
   3262 	.baco_set_state = smu_v11_0_baco_set_state,
   3263 	.baco_enter = smu_v11_0_baco_enter,
   3264 	.baco_exit = smu_v11_0_baco_exit,
   3265 	.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
   3266 	.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
   3267 	.override_pcie_parameters = smu_v11_0_override_pcie_parameters,
   3268 };
   3269 
   3270 void vega20_set_ppt_funcs(struct smu_context *smu)
   3271 {
   3272 	smu->ppt_funcs = &vega20_ppt_funcs;
   3273 }
   3274