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) \
44 [SMU_MSG_##msg] = PPSMC_MSG_##msg
46 static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
48 MSG_MAP(GetSmuVersion),
49 MSG_MAP(GetDriverIfVersion),
50 MSG_MAP(SetAllowedFeaturesMaskLow),
51 MSG_MAP(SetAllowedFeaturesMaskHigh),
52 MSG_MAP(EnableAllSmuFeatures),
53 MSG_MAP(DisableAllSmuFeatures),
54 MSG_MAP(EnableSmuFeaturesLow),
55 MSG_MAP(EnableSmuFeaturesHigh),
56 MSG_MAP(DisableSmuFeaturesLow),
57 MSG_MAP(DisableSmuFeaturesHigh),
58 MSG_MAP(GetEnabledSmuFeaturesLow),
59 MSG_MAP(GetEnabledSmuFeaturesHigh),
60 MSG_MAP(SetWorkloadMask),
62 MSG_MAP(SetDriverDramAddrHigh),
63 MSG_MAP(SetDriverDramAddrLow),
64 MSG_MAP(SetToolsDramAddrHigh),
65 MSG_MAP(SetToolsDramAddrLow),
66 MSG_MAP(TransferTableSmu2Dram),
67 MSG_MAP(TransferTableDram2Smu),
68 MSG_MAP(UseDefaultPPTable),
69 MSG_MAP(UseBackupPPTable),
71 MSG_MAP(RequestI2CBus),
72 MSG_MAP(ReleaseI2CBus),
73 MSG_MAP(SetFloorSocVoltage),
75 MSG_MAP(StartBacoMonitor),
76 MSG_MAP(CancelBacoMonitor),
78 MSG_MAP(SetSoftMinByFreq),
79 MSG_MAP(SetSoftMaxByFreq),
80 MSG_MAP(SetHardMinByFreq),
81 MSG_MAP(SetHardMaxByFreq),
82 MSG_MAP(GetMinDpmFreq),
83 MSG_MAP(GetMaxDpmFreq),
84 MSG_MAP(GetDpmFreqByIndex),
85 MSG_MAP(GetDpmClockFreq),
86 MSG_MAP(GetSsVoltageByDpm),
87 MSG_MAP(SetMemoryChannelConfig),
88 MSG_MAP(SetGeminiMode),
89 MSG_MAP(SetGeminiApertureHigh),
90 MSG_MAP(SetGeminiApertureLow),
91 MSG_MAP(SetMinLinkDpmByIndex),
92 MSG_MAP(OverridePcieParameters),
93 MSG_MAP(OverDriveSetPercentage),
94 MSG_MAP(SetMinDeepSleepDcefclk),
95 MSG_MAP(ReenableAcDcInterrupt),
96 MSG_MAP(NotifyPowerSource),
97 MSG_MAP(SetUclkFastSwitch),
98 MSG_MAP(SetUclkDownHyst),
99 MSG_MAP(GetCurrentRpm),
100 MSG_MAP(SetVideoFps),
102 MSG_MAP(SetFanTemperatureTarget),
103 MSG_MAP(PrepareMp1ForUnload),
104 MSG_MAP(DramLogSetDramAddrHigh),
105 MSG_MAP(DramLogSetDramAddrLow),
106 MSG_MAP(DramLogSetDramSize),
107 MSG_MAP(SetFanMaxRpm),
108 MSG_MAP(SetFanMinPwm),
109 MSG_MAP(ConfigureGfxDidt),
110 MSG_MAP(NumOfDisplays),
111 MSG_MAP(RemoveMargins),
112 MSG_MAP(ReadSerialNumTop32),
113 MSG_MAP(ReadSerialNumBottom32),
114 MSG_MAP(SetSystemVirtualDramAddrHigh),
115 MSG_MAP(SetSystemVirtualDramAddrLow),
117 MSG_MAP(SetFclkGfxClkRatio),
118 MSG_MAP(AllowGfxOff),
119 MSG_MAP(DisallowGfxOff),
120 MSG_MAP(GetPptLimit),
121 MSG_MAP(GetDcModeMaxDpmFreq),
122 MSG_MAP(GetDebugData),
123 MSG_MAP(SetXgmiMode),
126 MSG_MAP(PrepareMp1ForReset),
127 MSG_MAP(PrepareMp1ForShutdown),
128 MSG_MAP(SetMGpuFanBoostLimitRpm),
129 MSG_MAP(GetAVFSVoltageByDpm),
132 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
136 if (index >= SMU_MSG_MAX_COUNT)
139 val = vega20_message_map[index];
140 if (val > PPSMC_Message_Count)
146 static int vega20_allocate_dpm_context(struct smu_context *smu)
148 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
150 if (smu_dpm->dpm_context)
153 smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
155 if (!smu_dpm->dpm_context)
158 if (smu_dpm->golden_dpm_context)
161 smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
163 if (!smu_dpm->golden_dpm_context)
166 smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
168 smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
170 if (!smu_dpm->dpm_current_power_state)
173 smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
175 if (!smu_dpm->dpm_request_power_state)
181 static int vega20_setup_od8_information(struct smu_context *smu)
183 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
184 struct smu_table_context *table_context = &smu->smu_table;
186 uint32_t od_feature_count, od_feature_array_size,
187 od_setting_count, od_setting_array_size;
189 if (!table_context->power_play_table)
192 powerplay_table = table_context->power_play_table;
194 if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
195 /* Setup correct ODFeatureCount, and store ODFeatureArray from
196 * powerplay table to od_feature_capabilities */
198 (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
199 ATOM_VEGA20_ODFEATURE_COUNT) ?
200 ATOM_VEGA20_ODFEATURE_COUNT :
201 le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
203 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
205 if (table_context->od_feature_capabilities)
208 table_context->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
209 od_feature_array_size,
211 if (!table_context->od_feature_capabilities)
214 /* Setup correct ODSettingCount, and store ODSettingArray from
215 * powerplay table to od_settings_max and od_setting_min */
217 (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
218 ATOM_VEGA20_ODSETTING_COUNT) ?
219 ATOM_VEGA20_ODSETTING_COUNT :
220 le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
222 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
224 if (table_context->od_settings_max)
227 table_context->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
228 od_setting_array_size,
231 if (!table_context->od_settings_max) {
232 kfree(table_context->od_feature_capabilities);
233 table_context->od_feature_capabilities = NULL;
237 if (table_context->od_settings_min)
240 table_context->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
241 od_setting_array_size,
244 if (!table_context->od_settings_min) {
245 kfree(table_context->od_feature_capabilities);
246 table_context->od_feature_capabilities = NULL;
247 kfree(table_context->od_settings_max);
248 table_context->od_settings_max = NULL;
256 static int vega20_store_powerplay_table(struct smu_context *smu)
258 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
259 struct smu_table_context *table_context = &smu->smu_table;
262 if (!table_context->power_play_table)
265 powerplay_table = table_context->power_play_table;
267 memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
270 table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
271 table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
272 table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
274 ret = vega20_setup_od8_information(smu);
279 static int vega20_append_powerplay_table(struct smu_context *smu)
281 struct smu_table_context *table_context = &smu->smu_table;
282 PPTable_t *smc_pptable = table_context->driver_pptable;
283 struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
286 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
289 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
290 (uint8_t **)&smc_dpm_table);
294 smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
295 smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
297 smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
298 smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
299 smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
300 smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
302 smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
303 smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
304 smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
306 smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
307 smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
308 smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
310 smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
311 smc_pptable->SocOffset = smc_dpm_table->socoffset;
312 smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
314 smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
315 smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
316 smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
318 smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
319 smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
320 smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
322 smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
323 smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
324 smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
325 smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
327 smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
328 smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
329 smc_pptable->Padding1 = smc_dpm_table->padding1;
330 smc_pptable->Padding2 = smc_dpm_table->padding2;
332 smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
333 smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
334 smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
336 smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
337 smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
338 smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
340 smc_pptable->UclkSpreadEnabled = 0;
341 smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
342 smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
344 smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
345 smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
346 smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
348 smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
349 smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
350 smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
352 for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
353 smc_pptable->I2cControllers[i].Enabled =
354 smc_dpm_table->i2ccontrollers[i].enabled;
355 smc_pptable->I2cControllers[i].SlaveAddress =
356 smc_dpm_table->i2ccontrollers[i].slaveaddress;
357 smc_pptable->I2cControllers[i].ControllerPort =
358 smc_dpm_table->i2ccontrollers[i].controllerport;
359 smc_pptable->I2cControllers[i].ThermalThrottler =
360 smc_dpm_table->i2ccontrollers[i].thermalthrottler;
361 smc_pptable->I2cControllers[i].I2cProtocol =
362 smc_dpm_table->i2ccontrollers[i].i2cprotocol;
363 smc_pptable->I2cControllers[i].I2cSpeed =
364 smc_dpm_table->i2ccontrollers[i].i2cspeed;
370 static int vega20_check_powerplay_table(struct smu_context *smu)
372 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
373 struct smu_table_context *table_context = &smu->smu_table;
375 powerplay_table = table_context->power_play_table;
377 if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
378 pr_err("Unsupported PPTable format!");
382 if (!powerplay_table->sHeader.structuresize) {
383 pr_err("Invalid PowerPlay Table!");
390 static int vega20_run_btc_afll(struct smu_context *smu)
392 return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
396 vega20_get_unallowed_feature_mask(struct smu_context *smu,
397 uint32_t *feature_mask, uint32_t num)
402 feature_mask[0] = 0xE0041C00;
403 feature_mask[1] = 0xFFFFFFFE; /* bit32~bit63 is Unsupported */
409 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
411 enum amd_pm_state_type pm_type;
412 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
414 if (!smu_dpm_ctx->dpm_context ||
415 !smu_dpm_ctx->dpm_current_power_state)
418 mutex_lock(&(smu->mutex));
419 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
420 case SMU_STATE_UI_LABEL_BATTERY:
421 pm_type = POWER_STATE_TYPE_BATTERY;
423 case SMU_STATE_UI_LABEL_BALLANCED:
424 pm_type = POWER_STATE_TYPE_BALANCED;
426 case SMU_STATE_UI_LABEL_PERFORMANCE:
427 pm_type = POWER_STATE_TYPE_PERFORMANCE;
430 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
431 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
433 pm_type = POWER_STATE_TYPE_DEFAULT;
436 mutex_unlock(&(smu->mutex));
442 vega20_set_single_dpm_table(struct smu_context *smu,
443 struct vega20_single_dpm_table *single_dpm_table,
447 uint32_t i, num_of_levels = 0, clk;
449 ret = smu_send_smc_msg_with_param(smu,
450 SMU_MSG_GetDpmFreqByIndex,
451 (clk_id << 16 | 0xFF));
453 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
457 smu_read_smc_arg(smu, &num_of_levels);
458 if (!num_of_levels) {
459 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
463 single_dpm_table->count = num_of_levels;
465 for (i = 0; i < num_of_levels; i++) {
466 ret = smu_send_smc_msg_with_param(smu,
467 SMU_MSG_GetDpmFreqByIndex,
470 pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
473 smu_read_smc_arg(smu, &clk);
475 pr_err("[GetDpmFreqByIndex] clk value is invalid!");
478 single_dpm_table->dpm_levels[i].value = clk;
479 single_dpm_table->dpm_levels[i].enabled = true;
484 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
486 dpm_state->soft_min_level = 0x0;
487 dpm_state->soft_max_level = 0xffff;
488 dpm_state->hard_min_level = 0x0;
489 dpm_state->hard_max_level = 0xffff;
492 static int vega20_set_default_dpm_table(struct smu_context *smu)
496 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
497 struct vega20_dpm_table *dpm_table = NULL;
498 struct vega20_single_dpm_table *single_dpm_table;
500 dpm_table = smu_dpm->dpm_context;
503 single_dpm_table = &(dpm_table->soc_table);
505 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
506 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
509 pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
513 single_dpm_table->count = 1;
514 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
516 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
519 single_dpm_table = &(dpm_table->gfx_table);
521 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
522 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
525 pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
529 single_dpm_table->count = 1;
530 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
532 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
535 single_dpm_table = &(dpm_table->mem_table);
537 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
538 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
541 pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
545 single_dpm_table->count = 1;
546 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
548 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
551 single_dpm_table = &(dpm_table->eclk_table);
553 if (smu_feature_is_enabled(smu, FEATURE_DPM_VCE_BIT)) {
554 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
556 pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
560 single_dpm_table->count = 1;
561 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
563 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
566 single_dpm_table = &(dpm_table->vclk_table);
568 if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
569 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
571 pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
575 single_dpm_table->count = 1;
576 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
578 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
581 single_dpm_table = &(dpm_table->dclk_table);
583 if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
584 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
586 pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
590 single_dpm_table->count = 1;
591 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
593 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
596 single_dpm_table = &(dpm_table->dcef_table);
598 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
599 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
602 pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
606 single_dpm_table->count = 1;
607 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
609 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
612 single_dpm_table = &(dpm_table->pixel_table);
614 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
615 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
618 pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
622 single_dpm_table->count = 0;
624 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
627 single_dpm_table = &(dpm_table->display_table);
629 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
630 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
633 pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
637 single_dpm_table->count = 0;
639 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
642 single_dpm_table = &(dpm_table->phy_table);
644 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
645 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
648 pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
652 single_dpm_table->count = 0;
654 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
657 single_dpm_table = &(dpm_table->fclk_table);
659 if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
660 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
663 pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
667 single_dpm_table->count = 0;
669 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
671 memcpy(smu_dpm->golden_dpm_context, dpm_table,
672 sizeof(struct vega20_dpm_table));
677 static int vega20_populate_umd_state_clk(struct smu_context *smu)
679 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
680 struct vega20_dpm_table *dpm_table = NULL;
681 struct vega20_single_dpm_table *gfx_table = NULL;
682 struct vega20_single_dpm_table *mem_table = NULL;
684 dpm_table = smu_dpm->dpm_context;
685 gfx_table = &(dpm_table->gfx_table);
686 mem_table = &(dpm_table->mem_table);
688 smu->pstate_sclk = gfx_table->dpm_levels[0].value;
689 smu->pstate_mclk = mem_table->dpm_levels[0].value;
691 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
692 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
693 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
694 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
697 smu->pstate_sclk = smu->pstate_sclk * 100;
698 smu->pstate_mclk = smu->pstate_mclk * 100;
703 static int vega20_get_clk_table(struct smu_context *smu,
704 struct pp_clock_levels_with_latency *clocks,
705 struct vega20_single_dpm_table *dpm_table)
709 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
710 clocks->num_levels = count;
712 for (i = 0; i < count; i++) {
713 clocks->data[i].clocks_in_khz =
714 dpm_table->dpm_levels[i].value * 1000;
715 clocks->data[i].latency_in_us = 0;
721 static int vega20_print_clk_levels(struct smu_context *smu,
722 enum pp_clock_type type, char *buf)
724 int i, now, size = 0;
726 uint32_t gen_speed, lane_width;
727 struct amdgpu_device *adev = smu->adev;
728 struct pp_clock_levels_with_latency clocks;
729 struct vega20_single_dpm_table *single_dpm_table;
730 struct smu_table_context *table_context = &smu->smu_table;
731 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
732 struct vega20_dpm_table *dpm_table = NULL;
733 struct vega20_od8_settings *od8_settings =
734 (struct vega20_od8_settings *)table_context->od8_settings;
735 OverDriveTable_t *od_table =
736 (OverDriveTable_t *)(table_context->overdrive_table);
737 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
739 dpm_table = smu_dpm->dpm_context;
743 ret = smu_get_current_clk_freq(smu, PPCLK_GFXCLK, &now);
745 pr_err("Attempt to get current gfx clk Failed!");
749 single_dpm_table = &(dpm_table->gfx_table);
750 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
752 pr_err("Attempt to get gfx clk levels Failed!");
756 for (i = 0; i < clocks.num_levels; i++)
757 size += sprintf(buf + size, "%d: %uMhz %s\n", i,
758 clocks.data[i].clocks_in_khz / 1000,
759 (clocks.data[i].clocks_in_khz == now * 10)
764 ret = smu_get_current_clk_freq(smu, PPCLK_UCLK, &now);
766 pr_err("Attempt to get current mclk Failed!");
770 single_dpm_table = &(dpm_table->mem_table);
771 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
773 pr_err("Attempt to get memory clk levels Failed!");
777 for (i = 0; i < clocks.num_levels; i++)
778 size += sprintf(buf + size, "%d: %uMhz %s\n",
779 i, clocks.data[i].clocks_in_khz / 1000,
780 (clocks.data[i].clocks_in_khz == now * 10)
785 ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, &now);
787 pr_err("Attempt to get current socclk Failed!");
791 single_dpm_table = &(dpm_table->soc_table);
792 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
794 pr_err("Attempt to get socclk levels Failed!");
798 for (i = 0; i < clocks.num_levels; i++)
799 size += sprintf(buf + size, "%d: %uMhz %s\n",
800 i, clocks.data[i].clocks_in_khz / 1000,
801 (clocks.data[i].clocks_in_khz == now * 10)
806 ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now);
808 pr_err("Attempt to get current fclk Failed!");
812 single_dpm_table = &(dpm_table->fclk_table);
813 for (i = 0; i < single_dpm_table->count; i++)
814 size += sprintf(buf + size, "%d: %uMhz %s\n",
815 i, single_dpm_table->dpm_levels[i].value,
816 (single_dpm_table->dpm_levels[i].value == now / 100)
821 ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, &now);
823 pr_err("Attempt to get current dcefclk Failed!");
827 single_dpm_table = &(dpm_table->dcef_table);
828 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
830 pr_err("Attempt to get dcefclk levels Failed!");
834 for (i = 0; i < clocks.num_levels; i++)
835 size += sprintf(buf + size, "%d: %uMhz %s\n",
836 i, clocks.data[i].clocks_in_khz / 1000,
837 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
841 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
842 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
843 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
844 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
845 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
846 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
847 for (i = 0; i < NUM_LINK_LEVELS; i++)
848 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
849 (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
850 (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
851 (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
852 (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
853 (pptable->PcieLaneCount[i] == 1) ? "x1" :
854 (pptable->PcieLaneCount[i] == 2) ? "x2" :
855 (pptable->PcieLaneCount[i] == 3) ? "x4" :
856 (pptable->PcieLaneCount[i] == 4) ? "x8" :
857 (pptable->PcieLaneCount[i] == 5) ? "x12" :
858 (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
859 pptable->LclkFreq[i],
860 (gen_speed == pptable->PcieGenSpeed[i]) &&
861 (lane_width == pptable->PcieLaneCount[i]) ?
866 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
867 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
868 size = sprintf(buf, "%s:\n", "OD_SCLK");
869 size += sprintf(buf + size, "0: %10uMhz\n",
870 od_table->GfxclkFmin);
871 size += sprintf(buf + size, "1: %10uMhz\n",
872 od_table->GfxclkFmax);
878 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
879 size = sprintf(buf, "%s:\n", "OD_MCLK");
880 size += sprintf(buf + size, "1: %10uMhz\n",
887 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
888 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
889 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
890 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
891 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
892 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
893 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
894 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
895 od_table->GfxclkFreq1,
896 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
897 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
898 od_table->GfxclkFreq2,
899 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
900 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
901 od_table->GfxclkFreq3,
902 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
908 size = sprintf(buf, "%s:\n", "OD_RANGE");
910 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
911 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
912 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
913 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
914 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
917 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
918 single_dpm_table = &(dpm_table->mem_table);
919 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
921 pr_err("Attempt to get memory clk levels Failed!");
925 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
926 clocks.data[0].clocks_in_khz / 1000,
927 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
930 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
931 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
932 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
933 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
934 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
935 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
936 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
937 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
938 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
939 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
940 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
941 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
942 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
943 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
944 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
945 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
946 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
947 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
948 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
949 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
950 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
951 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
952 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
953 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
964 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
965 uint32_t feature_mask)
967 struct vega20_dpm_table *dpm_table;
968 struct vega20_single_dpm_table *single_dpm_table;
972 dpm_table = smu->smu_dpm.dpm_context;
974 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT) &&
975 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
976 single_dpm_table = &(dpm_table->gfx_table);
977 freq = max ? single_dpm_table->dpm_state.soft_max_level :
978 single_dpm_table->dpm_state.soft_min_level;
979 ret = smu_send_smc_msg_with_param(smu,
980 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
981 (PPCLK_GFXCLK << 16) | (freq & 0xffff));
983 pr_err("Failed to set soft %s gfxclk !\n",
984 max ? "max" : "min");
989 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT) &&
990 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
991 single_dpm_table = &(dpm_table->mem_table);
992 freq = max ? single_dpm_table->dpm_state.soft_max_level :
993 single_dpm_table->dpm_state.soft_min_level;
994 ret = smu_send_smc_msg_with_param(smu,
995 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
996 (PPCLK_UCLK << 16) | (freq & 0xffff));
998 pr_err("Failed to set soft %s memclk !\n",
999 max ? "max" : "min");
1004 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT) &&
1005 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1006 single_dpm_table = &(dpm_table->soc_table);
1007 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1008 single_dpm_table->dpm_state.soft_min_level;
1009 ret = smu_send_smc_msg_with_param(smu,
1010 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1011 (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1013 pr_err("Failed to set soft %s socclk !\n",
1014 max ? "max" : "min");
1019 if (smu_feature_is_enabled(smu, FEATURE_DPM_FCLK_BIT) &&
1020 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1021 single_dpm_table = &(dpm_table->fclk_table);
1022 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1023 single_dpm_table->dpm_state.soft_min_level;
1024 ret = smu_send_smc_msg_with_param(smu,
1025 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1026 (PPCLK_FCLK << 16) | (freq & 0xffff));
1028 pr_err("Failed to set soft %s fclk !\n",
1029 max ? "max" : "min");
1034 if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1035 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1036 single_dpm_table = &(dpm_table->dcef_table);
1037 freq = single_dpm_table->dpm_state.hard_min_level;
1039 ret = smu_send_smc_msg_with_param(smu,
1040 SMU_MSG_SetHardMinByFreq,
1041 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1043 pr_err("Failed to set hard min dcefclk !\n");
1052 static int vega20_force_clk_levels(struct smu_context *smu,
1053 enum pp_clock_type type, uint32_t mask)
1055 struct vega20_dpm_table *dpm_table;
1056 struct vega20_single_dpm_table *single_dpm_table;
1057 uint32_t soft_min_level, soft_max_level, hard_min_level;
1058 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1061 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1062 pr_info("force clock level is for dpm manual mode only.\n");
1066 mutex_lock(&(smu->mutex));
1068 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1069 soft_max_level = mask ? (fls(mask) - 1) : 0;
1071 dpm_table = smu->smu_dpm.dpm_context;
1075 single_dpm_table = &(dpm_table->gfx_table);
1077 if (soft_max_level >= single_dpm_table->count) {
1078 pr_err("Clock level specified %d is over max allowed %d\n",
1079 soft_max_level, single_dpm_table->count - 1);
1084 single_dpm_table->dpm_state.soft_min_level =
1085 single_dpm_table->dpm_levels[soft_min_level].value;
1086 single_dpm_table->dpm_state.soft_max_level =
1087 single_dpm_table->dpm_levels[soft_max_level].value;
1089 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1091 pr_err("Failed to upload boot level to lowest!\n");
1095 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1097 pr_err("Failed to upload dpm max level to highest!\n");
1102 single_dpm_table = &(dpm_table->mem_table);
1104 if (soft_max_level >= single_dpm_table->count) {
1105 pr_err("Clock level specified %d is over max allowed %d\n",
1106 soft_max_level, single_dpm_table->count - 1);
1111 single_dpm_table->dpm_state.soft_min_level =
1112 single_dpm_table->dpm_levels[soft_min_level].value;
1113 single_dpm_table->dpm_state.soft_max_level =
1114 single_dpm_table->dpm_levels[soft_max_level].value;
1116 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1118 pr_err("Failed to upload boot level to lowest!\n");
1122 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1124 pr_err("Failed to upload dpm max level to highest!\n");
1129 single_dpm_table = &(dpm_table->soc_table);
1131 if (soft_max_level >= single_dpm_table->count) {
1132 pr_err("Clock level specified %d is over max allowed %d\n",
1133 soft_max_level, single_dpm_table->count - 1);
1138 single_dpm_table->dpm_state.soft_min_level =
1139 single_dpm_table->dpm_levels[soft_min_level].value;
1140 single_dpm_table->dpm_state.soft_max_level =
1141 single_dpm_table->dpm_levels[soft_max_level].value;
1143 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1145 pr_err("Failed to upload boot level to lowest!\n");
1149 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1151 pr_err("Failed to upload dpm max level to highest!\n");
1156 single_dpm_table = &(dpm_table->fclk_table);
1158 if (soft_max_level >= single_dpm_table->count) {
1159 pr_err("Clock level specified %d is over max allowed %d\n",
1160 soft_max_level, single_dpm_table->count - 1);
1165 single_dpm_table->dpm_state.soft_min_level =
1166 single_dpm_table->dpm_levels[soft_min_level].value;
1167 single_dpm_table->dpm_state.soft_max_level =
1168 single_dpm_table->dpm_levels[soft_max_level].value;
1170 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1172 pr_err("Failed to upload boot level to lowest!\n");
1176 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1178 pr_err("Failed to upload dpm max level to highest!\n");
1183 hard_min_level = soft_min_level;
1184 single_dpm_table = &(dpm_table->dcef_table);
1186 if (hard_min_level >= single_dpm_table->count) {
1187 pr_err("Clock level specified %d is over max allowed %d\n",
1188 hard_min_level, single_dpm_table->count - 1);
1193 single_dpm_table->dpm_state.hard_min_level =
1194 single_dpm_table->dpm_levels[hard_min_level].value;
1196 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1198 pr_err("Failed to upload boot level to lowest!\n");
1203 if (soft_min_level >= NUM_LINK_LEVELS ||
1204 soft_max_level >= NUM_LINK_LEVELS) {
1209 ret = smu_send_smc_msg_with_param(smu,
1210 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1212 pr_err("Failed to set min link dpm level!\n");
1220 mutex_unlock(&(smu->mutex));
1224 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1225 enum amd_pp_clock_type type,
1226 struct pp_clock_levels_with_latency *clocks)
1229 struct vega20_single_dpm_table *single_dpm_table;
1230 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1231 struct vega20_dpm_table *dpm_table = NULL;
1233 dpm_table = smu_dpm->dpm_context;
1235 mutex_lock(&smu->mutex);
1238 case amd_pp_sys_clock:
1239 single_dpm_table = &(dpm_table->gfx_table);
1240 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1242 case amd_pp_mem_clock:
1243 single_dpm_table = &(dpm_table->mem_table);
1244 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1246 case amd_pp_dcef_clock:
1247 single_dpm_table = &(dpm_table->dcef_table);
1248 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1250 case amd_pp_soc_clock:
1251 single_dpm_table = &(dpm_table->soc_table);
1252 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1258 mutex_unlock(&smu->mutex);
1262 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1268 ret = smu_send_smc_msg_with_param(smu,
1269 SMU_MSG_GetAVFSVoltageByDpm,
1270 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1272 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1276 smu_read_smc_arg(smu, voltage);
1277 *voltage = *voltage / VOLTAGE_SCALE;
1282 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1284 struct smu_table_context *table_context = &smu->smu_table;
1285 OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1286 struct vega20_od8_settings *od8_settings = NULL;
1287 PPTable_t *smc_pptable = table_context->driver_pptable;
1290 if (table_context->od8_settings)
1293 table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1295 if (!table_context->od8_settings)
1298 memset(table_context->od8_settings, 0, sizeof(struct vega20_od8_settings));
1299 od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
1301 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
1302 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1303 table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1304 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1305 (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1306 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1307 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1309 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1311 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1312 od_table->GfxclkFmin;
1313 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1314 od_table->GfxclkFmax;
1317 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1318 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1319 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1320 (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1321 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1322 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1323 table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1324 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1326 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1328 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1330 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1332 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1334 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1337 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1338 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1339 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1340 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1341 od_table->GfxclkFreq1;
1342 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1343 od_table->GfxclkFreq2;
1344 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1345 od_table->GfxclkFreq3;
1347 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1348 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1349 od_table->GfxclkFreq1);
1351 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1352 od_table->GfxclkVolt1 =
1353 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1355 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1356 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1357 od_table->GfxclkFreq2);
1359 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1360 od_table->GfxclkVolt2 =
1361 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1363 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1364 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1365 od_table->GfxclkFreq3);
1367 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1368 od_table->GfxclkVolt3 =
1369 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1374 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1375 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1376 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1377 table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1378 (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1379 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1380 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1382 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1387 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1388 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1389 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1390 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1391 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1392 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1394 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1395 od_table->OverDrivePct;
1398 if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
1399 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1400 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1401 table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1402 (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1403 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1404 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1405 OD8_ACOUSTIC_LIMIT_SCLK;
1406 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1407 od_table->FanMaximumRpm;
1410 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1411 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1412 table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1413 (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1414 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1415 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1417 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1418 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1422 if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
1423 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1424 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1425 table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1426 (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1427 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1428 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1429 OD8_TEMPERATURE_FAN;
1430 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1431 od_table->FanTargetTemperature;
1434 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1435 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1436 table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1437 (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1438 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1439 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1440 OD8_TEMPERATURE_SYSTEM;
1441 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1442 od_table->MaxOpTemp;
1446 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1447 if (od8_settings->od8_settings_array[i].feature_id) {
1448 od8_settings->od8_settings_array[i].min_value =
1449 table_context->od_settings_min[i];
1450 od8_settings->od8_settings_array[i].max_value =
1451 table_context->od_settings_max[i];
1452 od8_settings->od8_settings_array[i].current_value =
1453 od8_settings->od8_settings_array[i].default_value;
1455 od8_settings->od8_settings_array[i].min_value = 0;
1456 od8_settings->od8_settings_array[i].max_value = 0;
1457 od8_settings->od8_settings_array[i].current_value = 0;
1464 static int vega20_get_od_percentage(struct smu_context *smu,
1465 enum pp_clock_type type)
1467 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1468 struct vega20_dpm_table *dpm_table = NULL;
1469 struct vega20_dpm_table *golden_table = NULL;
1470 struct vega20_single_dpm_table *single_dpm_table;
1471 struct vega20_single_dpm_table *golden_dpm_table;
1472 int value, golden_value;
1474 dpm_table = smu_dpm->dpm_context;
1475 golden_table = smu_dpm->golden_dpm_context;
1479 single_dpm_table = &(dpm_table->gfx_table);
1480 golden_dpm_table = &(golden_table->gfx_table);
1483 single_dpm_table = &(dpm_table->mem_table);
1484 golden_dpm_table = &(golden_table->mem_table);
1491 value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1492 golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1494 value -= golden_value;
1495 value = DIV_ROUND_UP(value * 100, golden_value);
1501 vega20_get_profiling_clk_mask(struct smu_context *smu,
1502 enum amd_dpm_forced_level level,
1503 uint32_t *sclk_mask,
1504 uint32_t *mclk_mask,
1507 struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1508 struct vega20_single_dpm_table *gfx_dpm_table;
1509 struct vega20_single_dpm_table *mem_dpm_table;
1510 struct vega20_single_dpm_table *soc_dpm_table;
1512 if (!smu->smu_dpm.dpm_context)
1515 gfx_dpm_table = &dpm_table->gfx_table;
1516 mem_dpm_table = &dpm_table->mem_table;
1517 soc_dpm_table = &dpm_table->soc_table;
1523 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1524 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1525 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1526 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1527 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
1528 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
1531 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1533 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1535 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1536 *sclk_mask = gfx_dpm_table->count - 1;
1537 *mclk_mask = mem_dpm_table->count - 1;
1538 *soc_mask = soc_dpm_table->count - 1;
1545 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
1546 struct vega20_single_dpm_table *dpm_table)
1549 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1550 if (!smu_dpm_ctx->dpm_context)
1553 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1554 if (dpm_table->count <= 0) {
1555 pr_err("[%s] Dpm table has no entry!", __func__);
1559 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
1560 pr_err("[%s] Dpm table has too many entries!", __func__);
1564 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1565 ret = smu_send_smc_msg_with_param(smu,
1566 SMU_MSG_SetHardMinByFreq,
1567 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
1569 pr_err("[%s] Set hard min uclk failed!", __func__);
1577 static int vega20_pre_display_config_changed(struct smu_context *smu)
1580 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1582 if (!smu->smu_dpm.dpm_context)
1585 smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
1586 ret = vega20_set_uclk_to_highest_dpm_level(smu,
1587 &dpm_table->mem_table);
1589 pr_err("Failed to set uclk to highest dpm level");
1593 static int vega20_display_config_changed(struct smu_context *smu)
1600 if (!smu->smu_dpm.dpm_context ||
1601 !smu->smu_table.tables ||
1602 !smu->smu_table.tables[TABLE_WATERMARKS].cpu_addr)
1605 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1606 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1607 ret = smu->funcs->write_watermarks_table(smu);
1609 pr_err("Failed to update WMTABLE!");
1612 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1615 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1616 smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1617 smu_feature_is_supported(smu, FEATURE_DPM_SOCCLK_BIT)) {
1618 smu_send_smc_msg_with_param(smu,
1619 SMU_MSG_NumOfDisplays,
1620 smu->display_config->num_display);
1626 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
1628 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1629 struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
1630 struct vega20_single_dpm_table *dpm_table;
1631 bool vblank_too_short = false;
1632 bool disable_mclk_switching;
1633 uint32_t i, latency;
1635 disable_mclk_switching = ((1 < smu->display_config->num_display) &&
1636 !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
1637 latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
1640 dpm_table = &(dpm_ctx->gfx_table);
1641 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1642 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1643 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1644 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1646 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
1647 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1648 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1651 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1652 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1653 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1656 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1657 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1658 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1662 dpm_table = &(dpm_ctx->mem_table);
1663 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1664 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1665 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1666 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1668 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
1669 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1670 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1673 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1674 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1675 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1678 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1679 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1680 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1683 /* honour DAL's UCLK Hardmin */
1684 if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
1685 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
1687 /* Hardmin is dependent on displayconfig */
1688 if (disable_mclk_switching) {
1689 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1690 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
1691 if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
1692 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
1693 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
1700 if (smu->display_config->nb_pstate_switch_disable)
1701 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1704 dpm_table = &(dpm_ctx->vclk_table);
1705 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1706 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1707 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1708 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1710 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1711 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1712 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1715 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1716 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1717 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1721 dpm_table = &(dpm_ctx->dclk_table);
1722 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1723 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1724 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1725 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1727 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1728 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1729 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1732 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1733 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1734 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1738 dpm_table = &(dpm_ctx->soc_table);
1739 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1740 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1741 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1742 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1744 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
1745 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1746 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1749 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1750 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1751 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1755 dpm_table = &(dpm_ctx->eclk_table);
1756 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1757 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1758 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1759 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1761 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
1762 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1763 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1766 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1767 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1768 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1774 vega20_notify_smc_dispaly_config(struct smu_context *smu)
1776 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1777 struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
1778 struct smu_clocks min_clocks = {0};
1779 struct pp_display_clock_request clock_req;
1782 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1783 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1784 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1786 if (smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT)) {
1787 clock_req.clock_type = amd_pp_dcef_clock;
1788 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1789 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
1790 if (smu_feature_is_supported(smu, FEATURE_DS_DCEFCLK_BIT)) {
1791 ret = smu_send_smc_msg_with_param(smu,
1792 SMU_MSG_SetMinDeepSleepDcefclk,
1793 min_clocks.dcef_clock_in_sr/100);
1795 pr_err("Attempt to set divider for DCEFCLK Failed!");
1800 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1804 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1805 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
1806 ret = smu_send_smc_msg_with_param(smu,
1807 SMU_MSG_SetHardMinByFreq,
1808 (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
1810 pr_err("[%s] Set hard min uclk failed!", __func__);
1818 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
1822 for (i = 0; i < table->count; i++) {
1823 if (table->dpm_levels[i].enabled)
1826 if (i >= table->count) {
1828 table->dpm_levels[i].enabled = true;
1834 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
1839 pr_err("[%s] DPM Table does not exist!", __func__);
1842 if (table->count <= 0) {
1843 pr_err("[%s] DPM Table has no entry!", __func__);
1846 if (table->count > MAX_REGULAR_DPM_NUMBER) {
1847 pr_err("[%s] DPM Table has too many entries!", __func__);
1848 return MAX_REGULAR_DPM_NUMBER - 1;
1851 for (i = table->count - 1; i >= 0; i--) {
1852 if (table->dpm_levels[i].enabled)
1857 table->dpm_levels[i].enabled = true;
1863 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
1865 uint32_t soft_level;
1867 struct vega20_dpm_table *dpm_table =
1868 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1871 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1873 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1875 dpm_table->gfx_table.dpm_state.soft_min_level =
1876 dpm_table->gfx_table.dpm_state.soft_max_level =
1877 dpm_table->gfx_table.dpm_levels[soft_level].value;
1880 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1882 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1884 dpm_table->mem_table.dpm_state.soft_min_level =
1885 dpm_table->mem_table.dpm_state.soft_max_level =
1886 dpm_table->mem_table.dpm_levels[soft_level].value;
1889 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1891 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1893 dpm_table->soc_table.dpm_state.soft_min_level =
1894 dpm_table->soc_table.dpm_state.soft_max_level =
1895 dpm_table->soc_table.dpm_levels[soft_level].value;
1897 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
1899 pr_err("Failed to upload boot level to %s!\n",
1900 highest ? "highest" : "lowest");
1904 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
1906 pr_err("Failed to upload dpm max level to %s!\n!",
1907 highest ? "highest" : "lowest");
1914 static int vega20_unforce_dpm_levels(struct smu_context *smu)
1916 uint32_t soft_min_level, soft_max_level;
1918 struct vega20_dpm_table *dpm_table =
1919 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1921 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1922 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1923 dpm_table->gfx_table.dpm_state.soft_min_level =
1924 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1925 dpm_table->gfx_table.dpm_state.soft_max_level =
1926 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1928 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1929 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1930 dpm_table->mem_table.dpm_state.soft_min_level =
1931 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1932 dpm_table->mem_table.dpm_state.soft_max_level =
1933 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1935 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1936 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1937 dpm_table->soc_table.dpm_state.soft_min_level =
1938 dpm_table->soc_table.dpm_levels[soft_min_level].value;
1939 dpm_table->soc_table.dpm_state.soft_max_level =
1940 dpm_table->soc_table.dpm_levels[soft_max_level].value;
1942 ret = smu_upload_dpm_level(smu, false, 0xFFFFFFFF);
1944 pr_err("Failed to upload DPM Bootup Levels!");
1948 ret = smu_upload_dpm_level(smu, true, 0xFFFFFFFF);
1950 pr_err("Failed to upload DPM Max Levels!");
1957 static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
1959 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1960 if (!smu_dpm_ctx->dpm_context)
1963 if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
1964 mutex_lock(&(smu->mutex));
1965 smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
1966 mutex_unlock(&(smu->mutex));
1968 return smu_dpm_ctx->dpm_level;
1972 vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1976 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1978 if (!smu_dpm_ctx->dpm_context)
1981 for (i = 0; i < smu->adev->num_ip_blocks; i++) {
1982 if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
1986 mutex_lock(&smu->mutex);
1988 smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
1989 ret = smu_handle_task(smu, level,
1990 AMD_PP_TASK_READJUST_POWER_STATE);
1992 mutex_unlock(&smu->mutex);
1997 static int vega20_update_specified_od8_value(struct smu_context *smu,
2001 struct smu_table_context *table_context = &smu->smu_table;
2002 OverDriveTable_t *od_table =
2003 (OverDriveTable_t *)(table_context->overdrive_table);
2004 struct vega20_od8_settings *od8_settings =
2005 (struct vega20_od8_settings *)table_context->od8_settings;
2008 case OD8_SETTING_GFXCLK_FMIN:
2009 od_table->GfxclkFmin = (uint16_t)value;
2012 case OD8_SETTING_GFXCLK_FMAX:
2013 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2014 value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2016 od_table->GfxclkFmax = (uint16_t)value;
2019 case OD8_SETTING_GFXCLK_FREQ1:
2020 od_table->GfxclkFreq1 = (uint16_t)value;
2023 case OD8_SETTING_GFXCLK_VOLTAGE1:
2024 od_table->GfxclkVolt1 = (uint16_t)value;
2027 case OD8_SETTING_GFXCLK_FREQ2:
2028 od_table->GfxclkFreq2 = (uint16_t)value;
2031 case OD8_SETTING_GFXCLK_VOLTAGE2:
2032 od_table->GfxclkVolt2 = (uint16_t)value;
2035 case OD8_SETTING_GFXCLK_FREQ3:
2036 od_table->GfxclkFreq3 = (uint16_t)value;
2039 case OD8_SETTING_GFXCLK_VOLTAGE3:
2040 od_table->GfxclkVolt3 = (uint16_t)value;
2043 case OD8_SETTING_UCLK_FMAX:
2044 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2045 value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2047 od_table->UclkFmax = (uint16_t)value;
2050 case OD8_SETTING_POWER_PERCENTAGE:
2051 od_table->OverDrivePct = (int16_t)value;
2054 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2055 od_table->FanMaximumRpm = (uint16_t)value;
2058 case OD8_SETTING_FAN_MIN_SPEED:
2059 od_table->FanMinimumPwm = (uint16_t)value;
2062 case OD8_SETTING_FAN_TARGET_TEMP:
2063 od_table->FanTargetTemperature = (uint16_t)value;
2066 case OD8_SETTING_OPERATING_TEMP_MAX:
2067 od_table->MaxOpTemp = (uint16_t)value;
2074 static int vega20_set_od_percentage(struct smu_context *smu,
2075 enum pp_clock_type type,
2078 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2079 struct vega20_dpm_table *dpm_table = NULL;
2080 struct vega20_dpm_table *golden_table = NULL;
2081 struct vega20_single_dpm_table *single_dpm_table;
2082 struct vega20_single_dpm_table *golden_dpm_table;
2083 uint32_t od_clk, index;
2085 int feature_enabled;
2088 mutex_lock(&(smu->mutex));
2090 dpm_table = smu_dpm->dpm_context;
2091 golden_table = smu_dpm->golden_dpm_context;
2095 single_dpm_table = &(dpm_table->gfx_table);
2096 golden_dpm_table = &(golden_table->gfx_table);
2097 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT);
2098 clk_id = PPCLK_GFXCLK;
2099 index = OD8_SETTING_GFXCLK_FMAX;
2102 single_dpm_table = &(dpm_table->mem_table);
2103 golden_dpm_table = &(golden_table->mem_table);
2104 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT);
2105 clk_id = PPCLK_UCLK;
2106 index = OD8_SETTING_UCLK_FMAX;
2116 od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2118 od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2120 ret = smu_update_od8_settings(smu, index, od_clk);
2122 pr_err("[Setoverdrive] failed to set od clk!\n");
2126 if (feature_enabled) {
2127 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2130 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2134 single_dpm_table->count = 1;
2135 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2138 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2139 AMD_PP_TASK_READJUST_POWER_STATE);
2142 mutex_unlock(&(smu->mutex));
2147 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2148 enum PP_OD_DPM_TABLE_COMMAND type,
2149 long *input, uint32_t size)
2151 struct smu_table_context *table_context = &smu->smu_table;
2152 OverDriveTable_t *od_table =
2153 (OverDriveTable_t *)(table_context->overdrive_table);
2154 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2155 struct vega20_dpm_table *dpm_table = NULL;
2156 struct vega20_single_dpm_table *single_dpm_table;
2157 struct vega20_od8_settings *od8_settings =
2158 (struct vega20_od8_settings *)table_context->od8_settings;
2159 struct pp_clock_levels_with_latency clocks;
2160 int32_t input_index, input_clk, input_vol, i;
2164 dpm_table = smu_dpm->dpm_context;
2167 pr_warn("NULL user input for clock and voltage\n");
2172 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2173 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2174 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2175 pr_info("Sclk min/max frequency overdrive not supported\n");
2179 for (i = 0; i < size; i += 2) {
2181 pr_info("invalid number of input parameters %d\n", size);
2185 input_index = input[i];
2186 input_clk = input[i + 1];
2188 if (input_index != 0 && input_index != 1) {
2189 pr_info("Invalid index %d\n", input_index);
2190 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2194 if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2195 input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2196 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2198 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2199 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2203 if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2204 od_table->GfxclkFmin = input_clk;
2205 table_context->od_gfxclk_update = true;
2206 } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2207 od_table->GfxclkFmax = input_clk;
2208 table_context->od_gfxclk_update = true;
2214 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2215 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2216 pr_info("Mclk max frequency overdrive not supported\n");
2220 single_dpm_table = &(dpm_table->mem_table);
2221 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2223 pr_err("Attempt to get memory clk levels Failed!");
2227 for (i = 0; i < size; i += 2) {
2229 pr_info("invalid number of input parameters %d\n",
2234 input_index = input[i];
2235 input_clk = input[i + 1];
2237 if (input_index != 1) {
2238 pr_info("Invalid index %d\n", input_index);
2239 pr_info("Support max Mclk frequency setting only which index by 1\n");
2243 if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2244 input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2245 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2247 clocks.data[0].clocks_in_khz / 1000,
2248 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2252 if (input_index == 1 && od_table->UclkFmax != input_clk) {
2253 table_context->od_gfxclk_update = true;
2254 od_table->UclkFmax = input_clk;
2260 case PP_OD_EDIT_VDDC_CURVE:
2261 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2262 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2263 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2264 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2265 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2266 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2267 pr_info("Voltage curve calibrate not supported\n");
2271 for (i = 0; i < size; i += 3) {
2273 pr_info("invalid number of input parameters %d\n",
2278 input_index = input[i];
2279 input_clk = input[i + 1];
2280 input_vol = input[i + 2];
2282 if (input_index > 2) {
2283 pr_info("Setting for point %d is not supported\n",
2285 pr_info("Three supported points index by 0, 1, 2\n");
2289 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2290 if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2291 input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2292 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2294 od8_settings->od8_settings_array[od8_id].min_value,
2295 od8_settings->od8_settings_array[od8_id].max_value);
2299 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2300 if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2301 input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2302 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2304 od8_settings->od8_settings_array[od8_id].min_value,
2305 od8_settings->od8_settings_array[od8_id].max_value);
2309 switch (input_index) {
2311 od_table->GfxclkFreq1 = input_clk;
2312 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2315 od_table->GfxclkFreq2 = input_clk;
2316 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2319 od_table->GfxclkFreq3 = input_clk;
2320 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2327 case PP_OD_RESTORE_DEFAULT_TABLE:
2328 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
2330 pr_err("Failed to export over drive table!\n");
2336 case PP_OD_COMMIT_DPM_TABLE:
2337 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
2339 pr_err("Failed to import over drive table!\n");
2343 /* retrieve updated gfxclk table */
2344 if (table_context->od_gfxclk_update) {
2345 table_context->od_gfxclk_update = false;
2346 single_dpm_table = &(dpm_table->gfx_table);
2348 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
2349 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2352 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2356 single_dpm_table->count = 1;
2357 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2367 if (type == PP_OD_COMMIT_DPM_TABLE) {
2368 mutex_lock(&(smu->mutex));
2369 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2370 AMD_PP_TASK_READJUST_POWER_STATE);
2371 mutex_unlock(&(smu->mutex));
2377 static const struct pptable_funcs vega20_ppt_funcs = {
2378 .alloc_dpm_context = vega20_allocate_dpm_context,
2379 .store_powerplay_table = vega20_store_powerplay_table,
2380 .check_powerplay_table = vega20_check_powerplay_table,
2381 .append_powerplay_table = vega20_append_powerplay_table,
2382 .get_smu_msg_index = vega20_get_smu_msg_index,
2383 .run_afll_btc = vega20_run_btc_afll,
2384 .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
2385 .get_current_power_state = vega20_get_current_power_state,
2386 .set_default_dpm_table = vega20_set_default_dpm_table,
2387 .set_power_state = NULL,
2388 .populate_umd_state_clk = vega20_populate_umd_state_clk,
2389 .print_clk_levels = vega20_print_clk_levels,
2390 .force_clk_levels = vega20_force_clk_levels,
2391 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
2392 .set_default_od8_settings = vega20_set_default_od8_setttings,
2393 .get_od_percentage = vega20_get_od_percentage,
2394 .get_performance_level = vega20_get_performance_level,
2395 .force_performance_level = vega20_force_performance_level,
2396 .update_specified_od8_value = vega20_update_specified_od8_value,
2397 .set_od_percentage = vega20_set_od_percentage,
2398 .od_edit_dpm_table = vega20_odn_edit_dpm_table,
2399 .pre_display_config_changed = vega20_pre_display_config_changed,
2400 .display_config_changed = vega20_display_config_changed,
2401 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
2402 .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
2403 .force_dpm_limit_value = vega20_force_dpm_limit_value,
2404 .unforce_dpm_levels = vega20_unforce_dpm_levels,
2405 .upload_dpm_level = vega20_upload_dpm_level,
2406 .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
2409 void vega20_set_ppt_funcs(struct smu_context *smu)
2411 smu->ppt_funcs = &vega20_ppt_funcs;
2412 smu->smc_if_version = SMU11_DRIVER_IF_VERSION;