2 * Copyright 2019 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <linux/firmware.h>
27 #include "amdgpu_smu.h"
28 #include "atomfirmware.h"
29 #include "amdgpu_atomfirmware.h"
30 #include "smu_v11_0.h"
31 #include "smu11_driver_if.h"
32 #include "soc15_common.h"
34 #include "power_state.h"
35 #include "vega20_ppt.h"
36 #include "vega20_pptable.h"
37 #include "vega20_ppsmc.h"
38 #include "nbio/nbio_7_4_sh_mask.h"
40 #define smnPCIE_LC_SPEED_CNTL 0x11140290
41 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
43 #define MSG_MAP(msg, index) \
44 [SMU_MSG_##msg] = index
46 static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
47 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage),
48 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion),
49 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion),
50 MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow),
51 MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh),
52 MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures),
53 MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures),
54 MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow),
55 MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh),
56 MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow),
57 MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh),
58 MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow),
59 MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh),
60 MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask),
61 MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit),
62 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh),
63 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow),
64 MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh),
65 MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow),
66 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram),
67 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu),
68 MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable),
69 MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable),
70 MSG_MAP(RunBtc, PPSMC_MSG_RunBtc),
71 MSG_MAP(RequestI2CBus, PPSMC_MSG_RequestI2CBus),
72 MSG_MAP(ReleaseI2CBus, PPSMC_MSG_ReleaseI2CBus),
73 MSG_MAP(SetFloorSocVoltage, PPSMC_MSG_SetFloorSocVoltage),
74 MSG_MAP(SoftReset, PPSMC_MSG_SoftReset),
75 MSG_MAP(StartBacoMonitor, PPSMC_MSG_StartBacoMonitor),
76 MSG_MAP(CancelBacoMonitor, PPSMC_MSG_CancelBacoMonitor),
77 MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco),
78 MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq),
79 MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq),
80 MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq),
81 MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq),
82 MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq),
83 MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq),
84 MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex),
85 MSG_MAP(GetDpmClockFreq, PPSMC_MSG_GetDpmClockFreq),
86 MSG_MAP(GetSsVoltageByDpm, PPSMC_MSG_GetSsVoltageByDpm),
87 MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig),
88 MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode),
89 MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh),
90 MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow),
91 MSG_MAP(SetMinLinkDpmByIndex, PPSMC_MSG_SetMinLinkDpmByIndex),
92 MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters),
93 MSG_MAP(OverDriveSetPercentage, PPSMC_MSG_OverDriveSetPercentage),
94 MSG_MAP(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk),
95 MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt),
96 MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource),
97 MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch),
98 MSG_MAP(SetUclkDownHyst, PPSMC_MSG_SetUclkDownHyst),
99 MSG_MAP(GetCurrentRpm, PPSMC_MSG_GetCurrentRpm),
100 MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps),
101 MSG_MAP(SetTjMax, PPSMC_MSG_SetTjMax),
102 MSG_MAP(SetFanTemperatureTarget, PPSMC_MSG_SetFanTemperatureTarget),
103 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload),
104 MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh),
105 MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow),
106 MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize),
107 MSG_MAP(SetFanMaxRpm, PPSMC_MSG_SetFanMaxRpm),
108 MSG_MAP(SetFanMinPwm, PPSMC_MSG_SetFanMinPwm),
109 MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt),
110 MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays),
111 MSG_MAP(RemoveMargins, PPSMC_MSG_RemoveMargins),
112 MSG_MAP(ReadSerialNumTop32, PPSMC_MSG_ReadSerialNumTop32),
113 MSG_MAP(ReadSerialNumBottom32, PPSMC_MSG_ReadSerialNumBottom32),
114 MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh),
115 MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow),
116 MSG_MAP(WaflTest, PPSMC_MSG_WaflTest),
117 MSG_MAP(SetFclkGfxClkRatio, PPSMC_MSG_SetFclkGfxClkRatio),
118 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff),
119 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff),
120 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit),
121 MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq),
122 MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData),
123 MSG_MAP(SetXgmiMode, PPSMC_MSG_SetXgmiMode),
124 MSG_MAP(RunAfllBtc, PPSMC_MSG_RunAfllBtc),
125 MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco),
126 MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset),
127 MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown),
128 MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm),
129 MSG_MAP(GetAVFSVoltageByDpm, PPSMC_MSG_GetAVFSVoltageByDpm),
132 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
135 if (index > SMU_MSG_MAX_COUNT)
138 val = vega20_message_map[index];
139 if (val > PPSMC_Message_Count)
145 static int vega20_allocate_dpm_context(struct smu_context *smu)
147 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
149 if (smu_dpm->dpm_context)
152 smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
154 if (!smu_dpm->dpm_context)
157 if (smu_dpm->golden_dpm_context)
160 smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
162 if (!smu_dpm->golden_dpm_context)
165 smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
167 smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
169 if (!smu_dpm->dpm_current_power_state)
172 smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
174 if (!smu_dpm->dpm_request_power_state)
180 static int vega20_setup_od8_information(struct smu_context *smu)
182 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
183 struct smu_table_context *table_context = &smu->smu_table;
185 uint32_t od_feature_count, od_feature_array_size,
186 od_setting_count, od_setting_array_size;
188 if (!table_context->power_play_table)
191 powerplay_table = table_context->power_play_table;
193 if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
194 /* Setup correct ODFeatureCount, and store ODFeatureArray from
195 * powerplay table to od_feature_capabilities */
197 (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
198 ATOM_VEGA20_ODFEATURE_COUNT) ?
199 ATOM_VEGA20_ODFEATURE_COUNT :
200 le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
202 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
204 if (table_context->od_feature_capabilities)
207 table_context->od_feature_capabilities = kzalloc(od_feature_array_size, GFP_KERNEL);
208 if (!table_context->od_feature_capabilities)
211 memcpy(table_context->od_feature_capabilities,
212 &powerplay_table->OverDrive8Table.ODFeatureCapabilities,
213 od_feature_array_size);
215 /* Setup correct ODSettingCount, and store ODSettingArray from
216 * powerplay table to od_settings_max and od_setting_min */
218 (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
219 ATOM_VEGA20_ODSETTING_COUNT) ?
220 ATOM_VEGA20_ODSETTING_COUNT :
221 le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
223 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
225 if (table_context->od_settings_max)
228 table_context->od_settings_max = kzalloc(od_setting_array_size, GFP_KERNEL);
230 if (!table_context->od_settings_max) {
231 kfree(table_context->od_feature_capabilities);
232 table_context->od_feature_capabilities = NULL;
236 memcpy(table_context->od_settings_max,
237 &powerplay_table->OverDrive8Table.ODSettingsMax,
238 od_setting_array_size);
240 if (table_context->od_settings_min)
243 table_context->od_settings_min = kzalloc(od_setting_array_size, GFP_KERNEL);
245 if (!table_context->od_settings_min) {
246 kfree(table_context->od_feature_capabilities);
247 table_context->od_feature_capabilities = NULL;
248 kfree(table_context->od_settings_max);
249 table_context->od_settings_max = NULL;
253 memcpy(table_context->od_settings_min,
254 &powerplay_table->OverDrive8Table.ODSettingsMin,
255 od_setting_array_size);
261 static int vega20_store_powerplay_table(struct smu_context *smu)
263 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
264 struct smu_table_context *table_context = &smu->smu_table;
267 if (!table_context->power_play_table)
270 powerplay_table = table_context->power_play_table;
272 memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
275 table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
276 table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
277 table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
279 ret = vega20_setup_od8_information(smu);
284 static int vega20_append_powerplay_table(struct smu_context *smu)
286 struct smu_table_context *table_context = &smu->smu_table;
287 PPTable_t *smc_pptable = table_context->driver_pptable;
288 struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
291 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
294 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
295 (uint8_t **)&smc_dpm_table);
299 smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
300 smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
302 smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
303 smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
304 smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
305 smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
307 smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
308 smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
309 smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
311 smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
312 smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
313 smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
315 smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
316 smc_pptable->SocOffset = smc_dpm_table->socoffset;
317 smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
319 smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
320 smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
321 smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
323 smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
324 smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
325 smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
327 smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
328 smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
329 smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
330 smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
332 smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
333 smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
334 smc_pptable->Padding1 = smc_dpm_table->padding1;
335 smc_pptable->Padding2 = smc_dpm_table->padding2;
337 smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
338 smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
339 smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
341 smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
342 smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
343 smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
345 smc_pptable->UclkSpreadEnabled = 0;
346 smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
347 smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
349 smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
350 smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
351 smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
353 smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
354 smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
355 smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
357 for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
358 smc_pptable->I2cControllers[i].Enabled =
359 smc_dpm_table->i2ccontrollers[i].enabled;
360 smc_pptable->I2cControllers[i].SlaveAddress =
361 smc_dpm_table->i2ccontrollers[i].slaveaddress;
362 smc_pptable->I2cControllers[i].ControllerPort =
363 smc_dpm_table->i2ccontrollers[i].controllerport;
364 smc_pptable->I2cControllers[i].ThermalThrottler =
365 smc_dpm_table->i2ccontrollers[i].thermalthrottler;
366 smc_pptable->I2cControllers[i].I2cProtocol =
367 smc_dpm_table->i2ccontrollers[i].i2cprotocol;
368 smc_pptable->I2cControllers[i].I2cSpeed =
369 smc_dpm_table->i2ccontrollers[i].i2cspeed;
375 static int vega20_check_powerplay_table(struct smu_context *smu)
377 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
378 struct smu_table_context *table_context = &smu->smu_table;
380 powerplay_table = table_context->power_play_table;
382 if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
383 pr_err("Unsupported PPTable format!");
387 if (!powerplay_table->sHeader.structuresize) {
388 pr_err("Invalid PowerPlay Table!");
395 static int vega20_run_btc_afll(struct smu_context *smu)
397 return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
401 vega20_get_unallowed_feature_mask(struct smu_context *smu,
402 uint32_t *feature_mask, uint32_t num)
407 feature_mask[0] = 0xE0041C00;
408 feature_mask[1] = 0xFFFFFFFE; /* bit32~bit63 is Unsupported */
414 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
416 enum amd_pm_state_type pm_type;
417 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
419 if (!smu_dpm_ctx->dpm_context ||
420 !smu_dpm_ctx->dpm_current_power_state)
423 mutex_lock(&(smu->mutex));
424 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
425 case SMU_STATE_UI_LABEL_BATTERY:
426 pm_type = POWER_STATE_TYPE_BATTERY;
428 case SMU_STATE_UI_LABEL_BALLANCED:
429 pm_type = POWER_STATE_TYPE_BALANCED;
431 case SMU_STATE_UI_LABEL_PERFORMANCE:
432 pm_type = POWER_STATE_TYPE_PERFORMANCE;
435 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
436 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
438 pm_type = POWER_STATE_TYPE_DEFAULT;
441 mutex_unlock(&(smu->mutex));
447 vega20_set_single_dpm_table(struct smu_context *smu,
448 struct vega20_single_dpm_table *single_dpm_table,
452 uint32_t i, num_of_levels, clk;
454 ret = smu_send_smc_msg_with_param(smu,
455 SMU_MSG_GetDpmFreqByIndex,
456 (clk_id << 16 | 0xFF));
458 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
462 smu_read_smc_arg(smu, &num_of_levels);
463 if (!num_of_levels) {
464 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
468 single_dpm_table->count = num_of_levels;
470 for (i = 0; i < num_of_levels; i++) {
471 ret = smu_send_smc_msg_with_param(smu,
472 SMU_MSG_GetDpmFreqByIndex,
475 pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
478 smu_read_smc_arg(smu, &clk);
480 pr_err("[GetDpmFreqByIndex] clk value is invalid!");
483 single_dpm_table->dpm_levels[i].value = clk;
484 single_dpm_table->dpm_levels[i].enabled = true;
489 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
491 dpm_state->soft_min_level = 0x0;
492 dpm_state->soft_max_level = 0xffff;
493 dpm_state->hard_min_level = 0x0;
494 dpm_state->hard_max_level = 0xffff;
497 static int vega20_set_default_dpm_table(struct smu_context *smu)
501 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
502 struct vega20_dpm_table *dpm_table = NULL;
503 struct vega20_single_dpm_table *single_dpm_table;
505 dpm_table = smu_dpm->dpm_context;
508 single_dpm_table = &(dpm_table->soc_table);
510 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
511 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
514 pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
518 single_dpm_table->count = 1;
519 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
521 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
524 single_dpm_table = &(dpm_table->gfx_table);
526 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
527 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
530 pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
534 single_dpm_table->count = 1;
535 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
537 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
540 single_dpm_table = &(dpm_table->mem_table);
542 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
543 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
546 pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
550 single_dpm_table->count = 1;
551 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
553 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
556 single_dpm_table = &(dpm_table->eclk_table);
558 if (smu_feature_is_enabled(smu, FEATURE_DPM_VCE_BIT)) {
559 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
561 pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
565 single_dpm_table->count = 1;
566 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
568 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
571 single_dpm_table = &(dpm_table->vclk_table);
573 if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
574 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
576 pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
580 single_dpm_table->count = 1;
581 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
583 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
586 single_dpm_table = &(dpm_table->dclk_table);
588 if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
589 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
591 pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
595 single_dpm_table->count = 1;
596 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
598 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
601 single_dpm_table = &(dpm_table->dcef_table);
603 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
604 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
607 pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
611 single_dpm_table->count = 1;
612 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
614 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
617 single_dpm_table = &(dpm_table->pixel_table);
619 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
620 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
623 pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
627 single_dpm_table->count = 0;
629 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
632 single_dpm_table = &(dpm_table->display_table);
634 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
635 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
638 pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
642 single_dpm_table->count = 0;
644 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
647 single_dpm_table = &(dpm_table->phy_table);
649 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
650 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
653 pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
657 single_dpm_table->count = 0;
659 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
662 single_dpm_table = &(dpm_table->fclk_table);
664 if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
665 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
668 pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
672 single_dpm_table->count = 0;
674 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
676 memcpy(smu_dpm->golden_dpm_context, dpm_table,
677 sizeof(struct vega20_dpm_table));
682 static int vega20_populate_umd_state_clk(struct smu_context *smu)
684 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
685 struct vega20_dpm_table *dpm_table = NULL;
686 struct vega20_single_dpm_table *gfx_table = NULL;
687 struct vega20_single_dpm_table *mem_table = NULL;
689 dpm_table = smu_dpm->dpm_context;
690 gfx_table = &(dpm_table->gfx_table);
691 mem_table = &(dpm_table->mem_table);
693 smu->pstate_sclk = gfx_table->dpm_levels[0].value;
694 smu->pstate_mclk = mem_table->dpm_levels[0].value;
696 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
697 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
698 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
699 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
702 smu->pstate_sclk = smu->pstate_sclk * 100;
703 smu->pstate_mclk = smu->pstate_mclk * 100;
708 static int vega20_get_clk_table(struct smu_context *smu,
709 struct pp_clock_levels_with_latency *clocks,
710 struct vega20_single_dpm_table *dpm_table)
714 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
715 clocks->num_levels = count;
717 for (i = 0; i < count; i++) {
718 clocks->data[i].clocks_in_khz =
719 dpm_table->dpm_levels[i].value * 1000;
720 clocks->data[i].latency_in_us = 0;
726 static int vega20_print_clk_levels(struct smu_context *smu,
727 enum pp_clock_type type, char *buf)
729 int i, now, size = 0;
731 uint32_t gen_speed, lane_width;
732 struct amdgpu_device *adev = smu->adev;
733 struct pp_clock_levels_with_latency clocks;
734 struct vega20_single_dpm_table *single_dpm_table;
735 struct smu_table_context *table_context = &smu->smu_table;
736 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
737 struct vega20_dpm_table *dpm_table = NULL;
738 struct vega20_od8_settings *od8_settings =
739 (struct vega20_od8_settings *)table_context->od8_settings;
740 OverDriveTable_t *od_table =
741 (OverDriveTable_t *)(table_context->overdrive_table);
742 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
744 dpm_table = smu_dpm->dpm_context;
748 ret = smu_get_current_clk_freq(smu, PPCLK_GFXCLK, &now);
750 pr_err("Attempt to get current gfx clk Failed!");
754 single_dpm_table = &(dpm_table->gfx_table);
755 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
757 pr_err("Attempt to get gfx clk levels Failed!");
761 for (i = 0; i < clocks.num_levels; i++)
762 size += sprintf(buf + size, "%d: %uMhz %s\n", i,
763 clocks.data[i].clocks_in_khz / 1000,
764 (clocks.data[i].clocks_in_khz == now * 10)
769 ret = smu_get_current_clk_freq(smu, PPCLK_UCLK, &now);
771 pr_err("Attempt to get current mclk Failed!");
775 single_dpm_table = &(dpm_table->mem_table);
776 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
778 pr_err("Attempt to get memory clk levels Failed!");
782 for (i = 0; i < clocks.num_levels; i++)
783 size += sprintf(buf + size, "%d: %uMhz %s\n",
784 i, clocks.data[i].clocks_in_khz / 1000,
785 (clocks.data[i].clocks_in_khz == now * 10)
790 ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, &now);
792 pr_err("Attempt to get current socclk Failed!");
796 single_dpm_table = &(dpm_table->soc_table);
797 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
799 pr_err("Attempt to get socclk levels Failed!");
803 for (i = 0; i < clocks.num_levels; i++)
804 size += sprintf(buf + size, "%d: %uMhz %s\n",
805 i, clocks.data[i].clocks_in_khz / 1000,
806 (clocks.data[i].clocks_in_khz == now * 10)
811 ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now);
813 pr_err("Attempt to get current fclk Failed!");
817 single_dpm_table = &(dpm_table->fclk_table);
818 for (i = 0; i < single_dpm_table->count; i++)
819 size += sprintf(buf + size, "%d: %uMhz %s\n",
820 i, single_dpm_table->dpm_levels[i].value,
821 (single_dpm_table->dpm_levels[i].value == now / 100)
826 ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, &now);
828 pr_err("Attempt to get current dcefclk Failed!");
832 single_dpm_table = &(dpm_table->dcef_table);
833 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
835 pr_err("Attempt to get dcefclk levels Failed!");
839 for (i = 0; i < clocks.num_levels; i++)
840 size += sprintf(buf + size, "%d: %uMhz %s\n",
841 i, clocks.data[i].clocks_in_khz / 1000,
842 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
846 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
847 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
848 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
849 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
850 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
851 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
852 for (i = 0; i < NUM_LINK_LEVELS; i++)
853 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
854 (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
855 (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
856 (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
857 (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
858 (pptable->PcieLaneCount[i] == 1) ? "x1" :
859 (pptable->PcieLaneCount[i] == 2) ? "x2" :
860 (pptable->PcieLaneCount[i] == 3) ? "x4" :
861 (pptable->PcieLaneCount[i] == 4) ? "x8" :
862 (pptable->PcieLaneCount[i] == 5) ? "x12" :
863 (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
864 pptable->LclkFreq[i],
865 (gen_speed == pptable->PcieGenSpeed[i]) &&
866 (lane_width == pptable->PcieLaneCount[i]) ?
871 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
872 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
873 size = sprintf(buf, "%s:\n", "OD_SCLK");
874 size += sprintf(buf + size, "0: %10uMhz\n",
875 od_table->GfxclkFmin);
876 size += sprintf(buf + size, "1: %10uMhz\n",
877 od_table->GfxclkFmax);
883 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
884 size = sprintf(buf, "%s:\n", "OD_MCLK");
885 size += sprintf(buf + size, "1: %10uMhz\n",
892 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
893 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
894 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
895 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
896 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
897 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
898 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
899 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
900 od_table->GfxclkFreq1,
901 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
902 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
903 od_table->GfxclkFreq2,
904 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
905 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
906 od_table->GfxclkFreq3,
907 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
913 size = sprintf(buf, "%s:\n", "OD_RANGE");
915 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
916 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
917 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
918 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
919 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
922 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
923 single_dpm_table = &(dpm_table->mem_table);
924 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
926 pr_err("Attempt to get memory clk levels Failed!");
930 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
931 clocks.data[0].clocks_in_khz / 1000,
932 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
935 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
936 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
937 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
938 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
939 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
940 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
941 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
942 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
943 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
944 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
945 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
946 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
947 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
948 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
949 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
950 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
951 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
952 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
953 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
954 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
955 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
956 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
957 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
958 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
969 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
970 uint32_t feature_mask)
972 struct vega20_dpm_table *dpm_table;
973 struct vega20_single_dpm_table *single_dpm_table;
977 dpm_table = smu->smu_dpm.dpm_context;
979 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT) &&
980 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
981 single_dpm_table = &(dpm_table->gfx_table);
982 freq = max ? single_dpm_table->dpm_state.soft_max_level :
983 single_dpm_table->dpm_state.soft_min_level;
984 ret = smu_send_smc_msg_with_param(smu,
985 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
986 (PPCLK_GFXCLK << 16) | (freq & 0xffff));
988 pr_err("Failed to set soft %s gfxclk !\n",
989 max ? "max" : "min");
994 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT) &&
995 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
996 single_dpm_table = &(dpm_table->mem_table);
997 freq = max ? single_dpm_table->dpm_state.soft_max_level :
998 single_dpm_table->dpm_state.soft_min_level;
999 ret = smu_send_smc_msg_with_param(smu,
1000 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1001 (PPCLK_UCLK << 16) | (freq & 0xffff));
1003 pr_err("Failed to set soft %s memclk !\n",
1004 max ? "max" : "min");
1009 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT) &&
1010 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1011 single_dpm_table = &(dpm_table->soc_table);
1012 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1013 single_dpm_table->dpm_state.soft_min_level;
1014 ret = smu_send_smc_msg_with_param(smu,
1015 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1016 (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1018 pr_err("Failed to set soft %s socclk !\n",
1019 max ? "max" : "min");
1024 if (smu_feature_is_enabled(smu, FEATURE_DPM_FCLK_BIT) &&
1025 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1026 single_dpm_table = &(dpm_table->fclk_table);
1027 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1028 single_dpm_table->dpm_state.soft_min_level;
1029 ret = smu_send_smc_msg_with_param(smu,
1030 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1031 (PPCLK_FCLK << 16) | (freq & 0xffff));
1033 pr_err("Failed to set soft %s fclk !\n",
1034 max ? "max" : "min");
1039 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1040 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1041 single_dpm_table = &(dpm_table->dcef_table);
1042 freq = single_dpm_table->dpm_state.hard_min_level;
1044 ret = smu_send_smc_msg_with_param(smu,
1045 SMU_MSG_SetHardMinByFreq,
1046 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1048 pr_err("Failed to set hard min dcefclk !\n");
1057 static int vega20_force_clk_levels(struct smu_context *smu,
1058 enum pp_clock_type type, uint32_t mask)
1060 struct vega20_dpm_table *dpm_table;
1061 struct vega20_single_dpm_table *single_dpm_table;
1062 uint32_t soft_min_level, soft_max_level, hard_min_level;
1063 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1066 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1067 pr_info("force clock level is for dpm manual mode only.\n");
1071 mutex_lock(&(smu->mutex));
1073 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1074 soft_max_level = mask ? (fls(mask) - 1) : 0;
1076 dpm_table = smu->smu_dpm.dpm_context;
1080 single_dpm_table = &(dpm_table->gfx_table);
1082 if (soft_max_level >= single_dpm_table->count) {
1083 pr_err("Clock level specified %d is over max allowed %d\n",
1084 soft_max_level, single_dpm_table->count - 1);
1089 single_dpm_table->dpm_state.soft_min_level =
1090 single_dpm_table->dpm_levels[soft_min_level].value;
1091 single_dpm_table->dpm_state.soft_max_level =
1092 single_dpm_table->dpm_levels[soft_max_level].value;
1094 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1096 pr_err("Failed to upload boot level to lowest!\n");
1100 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1102 pr_err("Failed to upload dpm max level to highest!\n");
1107 single_dpm_table = &(dpm_table->mem_table);
1109 if (soft_max_level >= single_dpm_table->count) {
1110 pr_err("Clock level specified %d is over max allowed %d\n",
1111 soft_max_level, single_dpm_table->count - 1);
1116 single_dpm_table->dpm_state.soft_min_level =
1117 single_dpm_table->dpm_levels[soft_min_level].value;
1118 single_dpm_table->dpm_state.soft_max_level =
1119 single_dpm_table->dpm_levels[soft_max_level].value;
1121 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1123 pr_err("Failed to upload boot level to lowest!\n");
1127 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1129 pr_err("Failed to upload dpm max level to highest!\n");
1134 single_dpm_table = &(dpm_table->soc_table);
1136 if (soft_max_level >= single_dpm_table->count) {
1137 pr_err("Clock level specified %d is over max allowed %d\n",
1138 soft_max_level, single_dpm_table->count - 1);
1143 single_dpm_table->dpm_state.soft_min_level =
1144 single_dpm_table->dpm_levels[soft_min_level].value;
1145 single_dpm_table->dpm_state.soft_max_level =
1146 single_dpm_table->dpm_levels[soft_max_level].value;
1148 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1150 pr_err("Failed to upload boot level to lowest!\n");
1154 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1156 pr_err("Failed to upload dpm max level to highest!\n");
1161 single_dpm_table = &(dpm_table->fclk_table);
1163 if (soft_max_level >= single_dpm_table->count) {
1164 pr_err("Clock level specified %d is over max allowed %d\n",
1165 soft_max_level, single_dpm_table->count - 1);
1170 single_dpm_table->dpm_state.soft_min_level =
1171 single_dpm_table->dpm_levels[soft_min_level].value;
1172 single_dpm_table->dpm_state.soft_max_level =
1173 single_dpm_table->dpm_levels[soft_max_level].value;
1175 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1177 pr_err("Failed to upload boot level to lowest!\n");
1181 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1183 pr_err("Failed to upload dpm max level to highest!\n");
1188 hard_min_level = soft_min_level;
1189 single_dpm_table = &(dpm_table->dcef_table);
1191 if (hard_min_level >= single_dpm_table->count) {
1192 pr_err("Clock level specified %d is over max allowed %d\n",
1193 hard_min_level, single_dpm_table->count - 1);
1198 single_dpm_table->dpm_state.hard_min_level =
1199 single_dpm_table->dpm_levels[hard_min_level].value;
1201 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1203 pr_err("Failed to upload boot level to lowest!\n");
1208 if (soft_min_level >= NUM_LINK_LEVELS ||
1209 soft_max_level >= NUM_LINK_LEVELS)
1212 ret = smu_send_smc_msg_with_param(smu,
1213 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1215 pr_err("Failed to set min link dpm level!\n");
1223 mutex_unlock(&(smu->mutex));
1227 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1228 enum amd_pp_clock_type type,
1229 struct pp_clock_levels_with_latency *clocks)
1232 struct vega20_single_dpm_table *single_dpm_table;
1233 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1234 struct vega20_dpm_table *dpm_table = NULL;
1236 dpm_table = smu_dpm->dpm_context;
1238 mutex_lock(&smu->mutex);
1241 case amd_pp_sys_clock:
1242 single_dpm_table = &(dpm_table->gfx_table);
1243 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1245 case amd_pp_mem_clock:
1246 single_dpm_table = &(dpm_table->mem_table);
1247 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1249 case amd_pp_dcef_clock:
1250 single_dpm_table = &(dpm_table->dcef_table);
1251 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1253 case amd_pp_soc_clock:
1254 single_dpm_table = &(dpm_table->soc_table);
1255 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1261 mutex_unlock(&smu->mutex);
1265 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1271 ret = smu_send_smc_msg_with_param(smu,
1272 SMU_MSG_GetAVFSVoltageByDpm,
1273 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1275 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1279 smu_read_smc_arg(smu, voltage);
1280 *voltage = *voltage / VOLTAGE_SCALE;
1285 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1287 struct smu_table_context *table_context = &smu->smu_table;
1288 OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1289 struct vega20_od8_settings *od8_settings = NULL;
1290 PPTable_t *smc_pptable = table_context->driver_pptable;
1293 if (table_context->od8_settings)
1296 table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1298 if (!table_context->od8_settings)
1301 memset(table_context->od8_settings, 0, sizeof(struct vega20_od8_settings));
1302 od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
1304 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
1305 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1306 table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1307 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1308 (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1309 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1310 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1312 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1314 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1315 od_table->GfxclkFmin;
1316 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1317 od_table->GfxclkFmax;
1320 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1321 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1322 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1323 (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1324 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1325 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1326 table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1327 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1329 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1331 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1333 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1335 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1337 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1340 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1341 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1342 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1343 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1344 od_table->GfxclkFreq1;
1345 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1346 od_table->GfxclkFreq2;
1347 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1348 od_table->GfxclkFreq3;
1350 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1351 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1352 od_table->GfxclkFreq1);
1354 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1355 od_table->GfxclkVolt1 =
1356 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1358 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1359 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1360 od_table->GfxclkFreq2);
1362 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1363 od_table->GfxclkVolt2 =
1364 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1366 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1367 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1368 od_table->GfxclkFreq3);
1370 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1371 od_table->GfxclkVolt3 =
1372 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1377 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1378 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1379 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1380 table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1381 (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1382 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1383 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1385 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1390 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1391 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1392 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1393 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1394 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1395 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1397 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1398 od_table->OverDrivePct;
1401 if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
1402 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1403 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1404 table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1405 (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1406 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1407 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1408 OD8_ACOUSTIC_LIMIT_SCLK;
1409 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1410 od_table->FanMaximumRpm;
1413 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1414 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1415 table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1416 (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1417 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1418 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1420 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1421 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1425 if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
1426 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1427 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1428 table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1429 (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1430 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1431 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1432 OD8_TEMPERATURE_FAN;
1433 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1434 od_table->FanTargetTemperature;
1437 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1438 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1439 table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1440 (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1441 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1442 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1443 OD8_TEMPERATURE_SYSTEM;
1444 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1445 od_table->MaxOpTemp;
1449 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1450 if (od8_settings->od8_settings_array[i].feature_id) {
1451 od8_settings->od8_settings_array[i].min_value =
1452 table_context->od_settings_min[i];
1453 od8_settings->od8_settings_array[i].max_value =
1454 table_context->od_settings_max[i];
1455 od8_settings->od8_settings_array[i].current_value =
1456 od8_settings->od8_settings_array[i].default_value;
1458 od8_settings->od8_settings_array[i].min_value = 0;
1459 od8_settings->od8_settings_array[i].max_value = 0;
1460 od8_settings->od8_settings_array[i].current_value = 0;
1467 static int vega20_get_od_percentage(struct smu_context *smu,
1468 enum pp_clock_type type)
1470 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1471 struct vega20_dpm_table *dpm_table = NULL;
1472 struct vega20_dpm_table *golden_table = NULL;
1473 struct vega20_single_dpm_table *single_dpm_table;
1474 struct vega20_single_dpm_table *golden_dpm_table;
1475 int value, golden_value;
1477 dpm_table = smu_dpm->dpm_context;
1478 golden_table = smu_dpm->golden_dpm_context;
1482 single_dpm_table = &(dpm_table->gfx_table);
1483 golden_dpm_table = &(golden_table->gfx_table);
1486 single_dpm_table = &(dpm_table->mem_table);
1487 golden_dpm_table = &(golden_table->mem_table);
1494 value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1495 golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1497 value -= golden_value;
1498 value = DIV_ROUND_UP(value * 100, golden_value);
1504 vega20_get_profiling_clk_mask(struct smu_context *smu,
1505 enum amd_dpm_forced_level level,
1506 uint32_t *sclk_mask,
1507 uint32_t *mclk_mask,
1510 struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1511 struct vega20_single_dpm_table *gfx_dpm_table;
1512 struct vega20_single_dpm_table *mem_dpm_table;
1513 struct vega20_single_dpm_table *soc_dpm_table;
1515 if (!smu->smu_dpm.dpm_context)
1518 gfx_dpm_table = &dpm_table->gfx_table;
1519 mem_dpm_table = &dpm_table->mem_table;
1520 soc_dpm_table = &dpm_table->soc_table;
1526 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1527 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1528 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1529 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1530 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
1531 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
1534 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1536 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1538 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1539 *sclk_mask = gfx_dpm_table->count - 1;
1540 *mclk_mask = mem_dpm_table->count - 1;
1541 *soc_mask = soc_dpm_table->count - 1;
1548 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
1549 struct vega20_single_dpm_table *dpm_table)
1552 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1553 if (!smu_dpm_ctx->dpm_context)
1556 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1557 if (dpm_table->count <= 0) {
1558 pr_err("[%s] Dpm table has no entry!", __func__);
1562 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
1563 pr_err("[%s] Dpm table has too many entries!", __func__);
1567 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1568 ret = smu_send_smc_msg_with_param(smu,
1569 SMU_MSG_SetHardMinByFreq,
1570 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
1572 pr_err("[%s] Set hard min uclk failed!", __func__);
1580 static int vega20_pre_display_config_changed(struct smu_context *smu)
1583 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1585 if (!smu->smu_dpm.dpm_context)
1588 smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
1589 ret = vega20_set_uclk_to_highest_dpm_level(smu,
1590 &dpm_table->mem_table);
1592 pr_err("Failed to set uclk to highest dpm level");
1596 static int vega20_display_config_changed(struct smu_context *smu)
1603 if (!smu->smu_dpm.dpm_context ||
1604 !smu->smu_table.tables ||
1605 !smu->smu_table.tables[TABLE_WATERMARKS].cpu_addr)
1608 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1609 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1610 ret = smu->funcs->write_watermarks_table(smu);
1612 pr_err("Failed to update WMTABLE!");
1615 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1618 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1619 smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1620 smu_feature_is_supported(smu, FEATURE_DPM_SOCCLK_BIT)) {
1621 smu_send_smc_msg_with_param(smu,
1622 SMU_MSG_NumOfDisplays,
1623 smu->display_config->num_display);
1629 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
1631 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1632 struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
1633 struct vega20_single_dpm_table *dpm_table;
1634 bool vblank_too_short = false;
1635 bool disable_mclk_switching;
1636 uint32_t i, latency;
1638 disable_mclk_switching = ((1 < smu->display_config->num_display) &&
1639 !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
1640 latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
1643 dpm_table = &(dpm_ctx->gfx_table);
1644 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1645 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1646 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1647 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1649 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
1650 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1651 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1654 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1655 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1656 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1659 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1660 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1661 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1665 dpm_table = &(dpm_ctx->mem_table);
1666 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1667 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1668 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1669 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1671 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
1672 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1673 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1676 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1677 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1678 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1681 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1682 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1683 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1686 /* honour DAL's UCLK Hardmin */
1687 if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
1688 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
1690 /* Hardmin is dependent on displayconfig */
1691 if (disable_mclk_switching) {
1692 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1693 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
1694 if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
1695 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
1696 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
1703 if (smu->display_config->nb_pstate_switch_disable)
1704 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1707 dpm_table = &(dpm_ctx->vclk_table);
1708 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1709 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1710 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1711 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1713 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1714 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1715 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1718 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1719 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1720 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1724 dpm_table = &(dpm_ctx->dclk_table);
1725 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1726 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1727 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1728 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1730 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1731 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1732 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1735 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1736 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1737 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1741 dpm_table = &(dpm_ctx->soc_table);
1742 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1743 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1744 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1745 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1747 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
1748 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1749 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1752 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1753 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1754 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1758 dpm_table = &(dpm_ctx->eclk_table);
1759 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1760 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1761 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1762 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1764 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
1765 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1766 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1769 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1770 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1771 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1777 vega20_notify_smc_dispaly_config(struct smu_context *smu)
1779 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1780 struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
1781 struct smu_clocks min_clocks = {0};
1782 struct pp_display_clock_request clock_req;
1785 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1786 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1787 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1789 if (smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT)) {
1790 clock_req.clock_type = amd_pp_dcef_clock;
1791 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1792 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
1793 if (smu_feature_is_supported(smu, FEATURE_DS_DCEFCLK_BIT)) {
1794 ret = smu_send_smc_msg_with_param(smu,
1795 SMU_MSG_SetMinDeepSleepDcefclk,
1796 min_clocks.dcef_clock_in_sr/100);
1798 pr_err("Attempt to set divider for DCEFCLK Failed!");
1803 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1807 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1808 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
1809 ret = smu_send_smc_msg_with_param(smu,
1810 SMU_MSG_SetHardMinByFreq,
1811 (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
1813 pr_err("[%s] Set hard min uclk failed!", __func__);
1821 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
1825 for (i = 0; i < table->count; i++) {
1826 if (table->dpm_levels[i].enabled)
1829 if (i >= table->count) {
1831 table->dpm_levels[i].enabled = true;
1837 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
1842 pr_err("[%s] DPM Table does not exist!", __func__);
1845 if (table->count <= 0) {
1846 pr_err("[%s] DPM Table has no entry!", __func__);
1849 if (table->count > MAX_REGULAR_DPM_NUMBER) {
1850 pr_err("[%s] DPM Table has too many entries!", __func__);
1851 return MAX_REGULAR_DPM_NUMBER - 1;
1854 for (i = table->count - 1; i >= 0; i--) {
1855 if (table->dpm_levels[i].enabled)
1860 table->dpm_levels[i].enabled = true;
1866 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
1868 uint32_t soft_level;
1870 struct vega20_dpm_table *dpm_table =
1871 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1874 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1876 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1878 dpm_table->gfx_table.dpm_state.soft_min_level =
1879 dpm_table->gfx_table.dpm_state.soft_max_level =
1880 dpm_table->gfx_table.dpm_levels[soft_level].value;
1883 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1885 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1887 dpm_table->mem_table.dpm_state.soft_min_level =
1888 dpm_table->mem_table.dpm_state.soft_max_level =
1889 dpm_table->mem_table.dpm_levels[soft_level].value;
1892 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1894 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1896 dpm_table->soc_table.dpm_state.soft_min_level =
1897 dpm_table->soc_table.dpm_state.soft_max_level =
1898 dpm_table->soc_table.dpm_levels[soft_level].value;
1900 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
1902 pr_err("Failed to upload boot level to %s!\n",
1903 highest ? "highest" : "lowest");
1907 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
1909 pr_err("Failed to upload dpm max level to %s!\n!",
1910 highest ? "highest" : "lowest");
1917 static int vega20_unforce_dpm_levels(struct smu_context *smu)
1919 uint32_t soft_min_level, soft_max_level;
1921 struct vega20_dpm_table *dpm_table =
1922 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1924 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1925 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1926 dpm_table->gfx_table.dpm_state.soft_min_level =
1927 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1928 dpm_table->gfx_table.dpm_state.soft_max_level =
1929 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1931 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1932 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1933 dpm_table->mem_table.dpm_state.soft_min_level =
1934 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1935 dpm_table->mem_table.dpm_state.soft_max_level =
1936 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1938 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1939 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1940 dpm_table->soc_table.dpm_state.soft_min_level =
1941 dpm_table->soc_table.dpm_levels[soft_min_level].value;
1942 dpm_table->soc_table.dpm_state.soft_max_level =
1943 dpm_table->soc_table.dpm_levels[soft_max_level].value;
1945 ret = smu_upload_dpm_level(smu, false, 0xFFFFFFFF);
1947 pr_err("Failed to upload DPM Bootup Levels!");
1951 ret = smu_upload_dpm_level(smu, true, 0xFFFFFFFF);
1953 pr_err("Failed to upload DPM Max Levels!");
1960 static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
1962 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1963 if (!smu_dpm_ctx->dpm_context)
1966 if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
1967 mutex_lock(&(smu->mutex));
1968 smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
1969 mutex_unlock(&(smu->mutex));
1971 return smu_dpm_ctx->dpm_level;
1975 vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1979 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1981 if (!smu_dpm_ctx->dpm_context)
1984 for (i = 0; i < smu->adev->num_ip_blocks; i++) {
1985 if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
1989 mutex_lock(&smu->mutex);
1991 smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
1992 ret = smu_handle_task(smu, level,
1993 AMD_PP_TASK_READJUST_POWER_STATE);
1995 mutex_unlock(&smu->mutex);
2000 static int vega20_update_specified_od8_value(struct smu_context *smu,
2004 struct smu_table_context *table_context = &smu->smu_table;
2005 OverDriveTable_t *od_table =
2006 (OverDriveTable_t *)(table_context->overdrive_table);
2007 struct vega20_od8_settings *od8_settings =
2008 (struct vega20_od8_settings *)table_context->od8_settings;
2011 case OD8_SETTING_GFXCLK_FMIN:
2012 od_table->GfxclkFmin = (uint16_t)value;
2015 case OD8_SETTING_GFXCLK_FMAX:
2016 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2017 value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2019 od_table->GfxclkFmax = (uint16_t)value;
2022 case OD8_SETTING_GFXCLK_FREQ1:
2023 od_table->GfxclkFreq1 = (uint16_t)value;
2026 case OD8_SETTING_GFXCLK_VOLTAGE1:
2027 od_table->GfxclkVolt1 = (uint16_t)value;
2030 case OD8_SETTING_GFXCLK_FREQ2:
2031 od_table->GfxclkFreq2 = (uint16_t)value;
2034 case OD8_SETTING_GFXCLK_VOLTAGE2:
2035 od_table->GfxclkVolt2 = (uint16_t)value;
2038 case OD8_SETTING_GFXCLK_FREQ3:
2039 od_table->GfxclkFreq3 = (uint16_t)value;
2042 case OD8_SETTING_GFXCLK_VOLTAGE3:
2043 od_table->GfxclkVolt3 = (uint16_t)value;
2046 case OD8_SETTING_UCLK_FMAX:
2047 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2048 value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2050 od_table->UclkFmax = (uint16_t)value;
2053 case OD8_SETTING_POWER_PERCENTAGE:
2054 od_table->OverDrivePct = (int16_t)value;
2057 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2058 od_table->FanMaximumRpm = (uint16_t)value;
2061 case OD8_SETTING_FAN_MIN_SPEED:
2062 od_table->FanMinimumPwm = (uint16_t)value;
2065 case OD8_SETTING_FAN_TARGET_TEMP:
2066 od_table->FanTargetTemperature = (uint16_t)value;
2069 case OD8_SETTING_OPERATING_TEMP_MAX:
2070 od_table->MaxOpTemp = (uint16_t)value;
2077 static int vega20_set_od_percentage(struct smu_context *smu,
2078 enum pp_clock_type type,
2081 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2082 struct vega20_dpm_table *dpm_table = NULL;
2083 struct vega20_dpm_table *golden_table = NULL;
2084 struct vega20_single_dpm_table *single_dpm_table;
2085 struct vega20_single_dpm_table *golden_dpm_table;
2086 uint32_t od_clk, index;
2088 int feature_enabled;
2091 mutex_lock(&(smu->mutex));
2093 dpm_table = smu_dpm->dpm_context;
2094 golden_table = smu_dpm->golden_dpm_context;
2098 single_dpm_table = &(dpm_table->gfx_table);
2099 golden_dpm_table = &(golden_table->gfx_table);
2100 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT);
2101 clk_id = PPCLK_GFXCLK;
2102 index = OD8_SETTING_GFXCLK_FMAX;
2105 single_dpm_table = &(dpm_table->mem_table);
2106 golden_dpm_table = &(golden_table->mem_table);
2107 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT);
2108 clk_id = PPCLK_UCLK;
2109 index = OD8_SETTING_UCLK_FMAX;
2119 od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2121 od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2123 ret = smu_update_od8_settings(smu, index, od_clk);
2125 pr_err("[Setoverdrive] failed to set od clk!\n");
2129 if (feature_enabled) {
2130 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2133 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2137 single_dpm_table->count = 1;
2138 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2141 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2142 AMD_PP_TASK_READJUST_POWER_STATE);
2145 mutex_unlock(&(smu->mutex));
2150 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2151 enum PP_OD_DPM_TABLE_COMMAND type,
2152 long *input, uint32_t size)
2154 struct smu_table_context *table_context = &smu->smu_table;
2155 OverDriveTable_t *od_table =
2156 (OverDriveTable_t *)(table_context->overdrive_table);
2157 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2158 struct vega20_dpm_table *dpm_table = NULL;
2159 struct vega20_single_dpm_table *single_dpm_table;
2160 struct vega20_od8_settings *od8_settings =
2161 (struct vega20_od8_settings *)table_context->od8_settings;
2162 struct pp_clock_levels_with_latency clocks;
2163 int32_t input_index, input_clk, input_vol, i;
2167 dpm_table = smu_dpm->dpm_context;
2170 pr_warn("NULL user input for clock and voltage\n");
2175 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2176 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2177 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2178 pr_info("Sclk min/max frequency overdrive not supported\n");
2182 for (i = 0; i < size; i += 2) {
2184 pr_info("invalid number of input parameters %d\n", size);
2188 input_index = input[i];
2189 input_clk = input[i + 1];
2191 if (input_index != 0 && input_index != 1) {
2192 pr_info("Invalid index %d\n", input_index);
2193 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2197 if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2198 input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2199 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2201 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2202 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2206 if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2207 od_table->GfxclkFmin = input_clk;
2208 table_context->od_gfxclk_update = true;
2209 } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2210 od_table->GfxclkFmax = input_clk;
2211 table_context->od_gfxclk_update = true;
2217 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2218 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2219 pr_info("Mclk max frequency overdrive not supported\n");
2223 single_dpm_table = &(dpm_table->mem_table);
2224 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2226 pr_err("Attempt to get memory clk levels Failed!");
2230 for (i = 0; i < size; i += 2) {
2232 pr_info("invalid number of input parameters %d\n",
2237 input_index = input[i];
2238 input_clk = input[i + 1];
2240 if (input_index != 1) {
2241 pr_info("Invalid index %d\n", input_index);
2242 pr_info("Support max Mclk frequency setting only which index by 1\n");
2246 if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2247 input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2248 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2250 clocks.data[0].clocks_in_khz / 1000,
2251 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2255 if (input_index == 1 && od_table->UclkFmax != input_clk) {
2256 table_context->od_gfxclk_update = true;
2257 od_table->UclkFmax = input_clk;
2263 case PP_OD_EDIT_VDDC_CURVE:
2264 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2265 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2266 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2267 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2268 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2269 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2270 pr_info("Voltage curve calibrate not supported\n");
2274 for (i = 0; i < size; i += 3) {
2276 pr_info("invalid number of input parameters %d\n",
2281 input_index = input[i];
2282 input_clk = input[i + 1];
2283 input_vol = input[i + 2];
2285 if (input_index > 2) {
2286 pr_info("Setting for point %d is not supported\n",
2288 pr_info("Three supported points index by 0, 1, 2\n");
2292 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2293 if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2294 input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2295 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2297 od8_settings->od8_settings_array[od8_id].min_value,
2298 od8_settings->od8_settings_array[od8_id].max_value);
2302 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2303 if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2304 input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2305 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2307 od8_settings->od8_settings_array[od8_id].min_value,
2308 od8_settings->od8_settings_array[od8_id].max_value);
2312 switch (input_index) {
2314 od_table->GfxclkFreq1 = input_clk;
2315 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2318 od_table->GfxclkFreq2 = input_clk;
2319 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2322 od_table->GfxclkFreq3 = input_clk;
2323 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2330 case PP_OD_RESTORE_DEFAULT_TABLE:
2331 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
2333 pr_err("Failed to export over drive table!\n");
2339 case PP_OD_COMMIT_DPM_TABLE:
2340 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
2342 pr_err("Failed to import over drive table!\n");
2346 /* retrieve updated gfxclk table */
2347 if (table_context->od_gfxclk_update) {
2348 table_context->od_gfxclk_update = false;
2349 single_dpm_table = &(dpm_table->gfx_table);
2351 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
2352 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2355 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2359 single_dpm_table->count = 1;
2360 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2370 if (type == PP_OD_COMMIT_DPM_TABLE) {
2371 mutex_lock(&(smu->mutex));
2372 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2373 AMD_PP_TASK_READJUST_POWER_STATE);
2374 mutex_unlock(&(smu->mutex));
2380 static const struct pptable_funcs vega20_ppt_funcs = {
2381 .alloc_dpm_context = vega20_allocate_dpm_context,
2382 .store_powerplay_table = vega20_store_powerplay_table,
2383 .check_powerplay_table = vega20_check_powerplay_table,
2384 .append_powerplay_table = vega20_append_powerplay_table,
2385 .get_smu_msg_index = vega20_get_smu_msg_index,
2386 .run_afll_btc = vega20_run_btc_afll,
2387 .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
2388 .get_current_power_state = vega20_get_current_power_state,
2389 .set_default_dpm_table = vega20_set_default_dpm_table,
2390 .set_power_state = NULL,
2391 .populate_umd_state_clk = vega20_populate_umd_state_clk,
2392 .print_clk_levels = vega20_print_clk_levels,
2393 .force_clk_levels = vega20_force_clk_levels,
2394 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
2395 .set_default_od8_settings = vega20_set_default_od8_setttings,
2396 .get_od_percentage = vega20_get_od_percentage,
2397 .get_performance_level = vega20_get_performance_level,
2398 .force_performance_level = vega20_force_performance_level,
2399 .update_specified_od8_value = vega20_update_specified_od8_value,
2400 .set_od_percentage = vega20_set_od_percentage,
2401 .od_edit_dpm_table = vega20_odn_edit_dpm_table,
2402 .pre_display_config_changed = vega20_pre_display_config_changed,
2403 .display_config_changed = vega20_display_config_changed,
2404 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
2405 .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
2406 .force_dpm_limit_value = vega20_force_dpm_limit_value,
2407 .unforce_dpm_levels = vega20_unforce_dpm_levels,
2408 .upload_dpm_level = vega20_upload_dpm_level,
2409 .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
2412 void vega20_set_ppt_funcs(struct smu_context *smu)
2414 smu->ppt_funcs = &vega20_ppt_funcs;