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 od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
1300 if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
1301 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1302 table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1303 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1304 (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1305 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1306 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1308 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1310 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1311 od_table->GfxclkFmin;
1312 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1313 od_table->GfxclkFmax;
1316 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1317 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1318 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1319 (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1320 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1321 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1322 table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1323 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1325 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1327 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1329 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1331 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1333 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1336 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1337 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1338 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1339 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1340 od_table->GfxclkFreq1;
1341 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1342 od_table->GfxclkFreq2;
1343 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1344 od_table->GfxclkFreq3;
1346 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1347 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1348 od_table->GfxclkFreq1);
1350 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1351 od_table->GfxclkVolt1 =
1352 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1354 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1355 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1356 od_table->GfxclkFreq2);
1358 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1359 od_table->GfxclkVolt2 =
1360 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1362 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1363 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1364 od_table->GfxclkFreq3);
1366 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1367 od_table->GfxclkVolt3 =
1368 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1373 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1374 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1375 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1376 table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1377 (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1378 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1379 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1381 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1386 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1387 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1388 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1389 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1390 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1391 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1393 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1394 od_table->OverDrivePct;
1397 if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
1398 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1399 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1400 table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1401 (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1402 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1403 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1404 OD8_ACOUSTIC_LIMIT_SCLK;
1405 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1406 od_table->FanMaximumRpm;
1409 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1410 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1411 table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1412 (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1413 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1414 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1416 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1417 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1421 if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
1422 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1423 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1424 table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1425 (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1426 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1427 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1428 OD8_TEMPERATURE_FAN;
1429 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1430 od_table->FanTargetTemperature;
1433 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1434 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1435 table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1436 (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1437 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1438 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1439 OD8_TEMPERATURE_SYSTEM;
1440 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1441 od_table->MaxOpTemp;
1445 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1446 if (od8_settings->od8_settings_array[i].feature_id) {
1447 od8_settings->od8_settings_array[i].min_value =
1448 table_context->od_settings_min[i];
1449 od8_settings->od8_settings_array[i].max_value =
1450 table_context->od_settings_max[i];
1451 od8_settings->od8_settings_array[i].current_value =
1452 od8_settings->od8_settings_array[i].default_value;
1454 od8_settings->od8_settings_array[i].min_value = 0;
1455 od8_settings->od8_settings_array[i].max_value = 0;
1456 od8_settings->od8_settings_array[i].current_value = 0;
1463 static int vega20_get_od_percentage(struct smu_context *smu,
1464 enum pp_clock_type type)
1466 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1467 struct vega20_dpm_table *dpm_table = NULL;
1468 struct vega20_dpm_table *golden_table = NULL;
1469 struct vega20_single_dpm_table *single_dpm_table;
1470 struct vega20_single_dpm_table *golden_dpm_table;
1471 int value, golden_value;
1473 dpm_table = smu_dpm->dpm_context;
1474 golden_table = smu_dpm->golden_dpm_context;
1478 single_dpm_table = &(dpm_table->gfx_table);
1479 golden_dpm_table = &(golden_table->gfx_table);
1482 single_dpm_table = &(dpm_table->mem_table);
1483 golden_dpm_table = &(golden_table->mem_table);
1490 value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1491 golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1493 value -= golden_value;
1494 value = DIV_ROUND_UP(value * 100, golden_value);
1499 static int vega20_conv_profile_to_workload(struct smu_context *smu, int power_profile)
1501 int pplib_workload = 0;
1503 switch (power_profile) {
1504 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
1505 pplib_workload = WORKLOAD_DEFAULT_BIT;
1507 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
1508 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
1510 case PP_SMC_POWER_PROFILE_POWERSAVING:
1511 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
1513 case PP_SMC_POWER_PROFILE_VIDEO:
1514 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
1516 case PP_SMC_POWER_PROFILE_VR:
1517 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
1519 case PP_SMC_POWER_PROFILE_COMPUTE:
1520 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
1522 case PP_SMC_POWER_PROFILE_CUSTOM:
1523 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
1527 return pplib_workload;
1531 vega20_get_profiling_clk_mask(struct smu_context *smu,
1532 enum amd_dpm_forced_level level,
1533 uint32_t *sclk_mask,
1534 uint32_t *mclk_mask,
1537 struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1538 struct vega20_single_dpm_table *gfx_dpm_table;
1539 struct vega20_single_dpm_table *mem_dpm_table;
1540 struct vega20_single_dpm_table *soc_dpm_table;
1542 if (!smu->smu_dpm.dpm_context)
1545 gfx_dpm_table = &dpm_table->gfx_table;
1546 mem_dpm_table = &dpm_table->mem_table;
1547 soc_dpm_table = &dpm_table->soc_table;
1553 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1554 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1555 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1556 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1557 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
1558 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
1561 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1563 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1565 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1566 *sclk_mask = gfx_dpm_table->count - 1;
1567 *mclk_mask = mem_dpm_table->count - 1;
1568 *soc_mask = soc_dpm_table->count - 1;
1575 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
1576 struct vega20_single_dpm_table *dpm_table)
1579 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1580 if (!smu_dpm_ctx->dpm_context)
1583 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1584 if (dpm_table->count <= 0) {
1585 pr_err("[%s] Dpm table has no entry!", __func__);
1589 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
1590 pr_err("[%s] Dpm table has too many entries!", __func__);
1594 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1595 ret = smu_send_smc_msg_with_param(smu,
1596 SMU_MSG_SetHardMinByFreq,
1597 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
1599 pr_err("[%s] Set hard min uclk failed!", __func__);
1607 static int vega20_pre_display_config_changed(struct smu_context *smu)
1610 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1612 if (!smu->smu_dpm.dpm_context)
1615 smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
1616 ret = vega20_set_uclk_to_highest_dpm_level(smu,
1617 &dpm_table->mem_table);
1619 pr_err("Failed to set uclk to highest dpm level");
1623 static int vega20_display_config_changed(struct smu_context *smu)
1630 if (!smu->smu_dpm.dpm_context ||
1631 !smu->smu_table.tables ||
1632 !smu->smu_table.tables[TABLE_WATERMARKS].cpu_addr)
1635 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1636 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1637 ret = smu->funcs->write_watermarks_table(smu);
1639 pr_err("Failed to update WMTABLE!");
1642 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1645 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1646 smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1647 smu_feature_is_supported(smu, FEATURE_DPM_SOCCLK_BIT)) {
1648 smu_send_smc_msg_with_param(smu,
1649 SMU_MSG_NumOfDisplays,
1650 smu->display_config->num_display);
1656 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
1658 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1659 struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
1660 struct vega20_single_dpm_table *dpm_table;
1661 bool vblank_too_short = false;
1662 bool disable_mclk_switching;
1663 uint32_t i, latency;
1665 disable_mclk_switching = ((1 < smu->display_config->num_display) &&
1666 !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
1667 latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
1670 dpm_table = &(dpm_ctx->gfx_table);
1671 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1672 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1673 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1674 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1676 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
1677 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1678 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1681 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1682 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1683 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1686 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1687 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1688 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1692 dpm_table = &(dpm_ctx->mem_table);
1693 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1694 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1695 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1696 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1698 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
1699 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1700 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1703 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1704 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1705 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1708 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1709 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1710 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1713 /* honour DAL's UCLK Hardmin */
1714 if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
1715 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
1717 /* Hardmin is dependent on displayconfig */
1718 if (disable_mclk_switching) {
1719 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1720 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
1721 if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
1722 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
1723 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
1730 if (smu->display_config->nb_pstate_switch_disable)
1731 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1734 dpm_table = &(dpm_ctx->vclk_table);
1735 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1736 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1737 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1738 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1740 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1741 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1742 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1745 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1746 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1747 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1751 dpm_table = &(dpm_ctx->dclk_table);
1752 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1753 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1754 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1755 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1757 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1758 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1759 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1762 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1763 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1764 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1768 dpm_table = &(dpm_ctx->soc_table);
1769 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1770 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1771 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1772 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1774 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
1775 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1776 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1779 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1780 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1781 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1785 dpm_table = &(dpm_ctx->eclk_table);
1786 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1787 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1788 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1789 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1791 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
1792 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1793 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1796 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1797 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1798 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1804 vega20_notify_smc_dispaly_config(struct smu_context *smu)
1806 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1807 struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
1808 struct smu_clocks min_clocks = {0};
1809 struct pp_display_clock_request clock_req;
1812 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1813 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1814 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1816 if (smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT)) {
1817 clock_req.clock_type = amd_pp_dcef_clock;
1818 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1819 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
1820 if (smu_feature_is_supported(smu, FEATURE_DS_DCEFCLK_BIT)) {
1821 ret = smu_send_smc_msg_with_param(smu,
1822 SMU_MSG_SetMinDeepSleepDcefclk,
1823 min_clocks.dcef_clock_in_sr/100);
1825 pr_err("Attempt to set divider for DCEFCLK Failed!");
1830 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1834 if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1835 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
1836 ret = smu_send_smc_msg_with_param(smu,
1837 SMU_MSG_SetHardMinByFreq,
1838 (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
1840 pr_err("[%s] Set hard min uclk failed!", __func__);
1848 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
1852 for (i = 0; i < table->count; i++) {
1853 if (table->dpm_levels[i].enabled)
1856 if (i >= table->count) {
1858 table->dpm_levels[i].enabled = true;
1864 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
1869 pr_err("[%s] DPM Table does not exist!", __func__);
1872 if (table->count <= 0) {
1873 pr_err("[%s] DPM Table has no entry!", __func__);
1876 if (table->count > MAX_REGULAR_DPM_NUMBER) {
1877 pr_err("[%s] DPM Table has too many entries!", __func__);
1878 return MAX_REGULAR_DPM_NUMBER - 1;
1881 for (i = table->count - 1; i >= 0; i--) {
1882 if (table->dpm_levels[i].enabled)
1887 table->dpm_levels[i].enabled = true;
1893 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
1895 uint32_t soft_level;
1897 struct vega20_dpm_table *dpm_table =
1898 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1901 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1903 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1905 dpm_table->gfx_table.dpm_state.soft_min_level =
1906 dpm_table->gfx_table.dpm_state.soft_max_level =
1907 dpm_table->gfx_table.dpm_levels[soft_level].value;
1910 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1912 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1914 dpm_table->mem_table.dpm_state.soft_min_level =
1915 dpm_table->mem_table.dpm_state.soft_max_level =
1916 dpm_table->mem_table.dpm_levels[soft_level].value;
1919 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1921 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1923 dpm_table->soc_table.dpm_state.soft_min_level =
1924 dpm_table->soc_table.dpm_state.soft_max_level =
1925 dpm_table->soc_table.dpm_levels[soft_level].value;
1927 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
1929 pr_err("Failed to upload boot level to %s!\n",
1930 highest ? "highest" : "lowest");
1934 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
1936 pr_err("Failed to upload dpm max level to %s!\n!",
1937 highest ? "highest" : "lowest");
1944 static int vega20_unforce_dpm_levels(struct smu_context *smu)
1946 uint32_t soft_min_level, soft_max_level;
1948 struct vega20_dpm_table *dpm_table =
1949 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1951 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1952 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1953 dpm_table->gfx_table.dpm_state.soft_min_level =
1954 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1955 dpm_table->gfx_table.dpm_state.soft_max_level =
1956 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1958 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1959 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1960 dpm_table->mem_table.dpm_state.soft_min_level =
1961 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1962 dpm_table->mem_table.dpm_state.soft_max_level =
1963 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1965 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1966 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1967 dpm_table->soc_table.dpm_state.soft_min_level =
1968 dpm_table->soc_table.dpm_levels[soft_min_level].value;
1969 dpm_table->soc_table.dpm_state.soft_max_level =
1970 dpm_table->soc_table.dpm_levels[soft_max_level].value;
1972 ret = smu_upload_dpm_level(smu, false, 0xFFFFFFFF);
1974 pr_err("Failed to upload DPM Bootup Levels!");
1978 ret = smu_upload_dpm_level(smu, true, 0xFFFFFFFF);
1980 pr_err("Failed to upload DPM Max Levels!");
1987 static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
1989 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1990 if (!smu_dpm_ctx->dpm_context)
1993 if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
1994 mutex_lock(&(smu->mutex));
1995 smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
1996 mutex_unlock(&(smu->mutex));
1998 return smu_dpm_ctx->dpm_level;
2002 vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
2006 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2008 if (!smu_dpm_ctx->dpm_context)
2011 for (i = 0; i < smu->adev->num_ip_blocks; i++) {
2012 if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
2016 mutex_lock(&smu->mutex);
2018 smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
2019 ret = smu_handle_task(smu, level,
2020 AMD_PP_TASK_READJUST_POWER_STATE);
2022 mutex_unlock(&smu->mutex);
2027 static int vega20_update_specified_od8_value(struct smu_context *smu,
2031 struct smu_table_context *table_context = &smu->smu_table;
2032 OverDriveTable_t *od_table =
2033 (OverDriveTable_t *)(table_context->overdrive_table);
2034 struct vega20_od8_settings *od8_settings =
2035 (struct vega20_od8_settings *)table_context->od8_settings;
2038 case OD8_SETTING_GFXCLK_FMIN:
2039 od_table->GfxclkFmin = (uint16_t)value;
2042 case OD8_SETTING_GFXCLK_FMAX:
2043 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2044 value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2046 od_table->GfxclkFmax = (uint16_t)value;
2049 case OD8_SETTING_GFXCLK_FREQ1:
2050 od_table->GfxclkFreq1 = (uint16_t)value;
2053 case OD8_SETTING_GFXCLK_VOLTAGE1:
2054 od_table->GfxclkVolt1 = (uint16_t)value;
2057 case OD8_SETTING_GFXCLK_FREQ2:
2058 od_table->GfxclkFreq2 = (uint16_t)value;
2061 case OD8_SETTING_GFXCLK_VOLTAGE2:
2062 od_table->GfxclkVolt2 = (uint16_t)value;
2065 case OD8_SETTING_GFXCLK_FREQ3:
2066 od_table->GfxclkFreq3 = (uint16_t)value;
2069 case OD8_SETTING_GFXCLK_VOLTAGE3:
2070 od_table->GfxclkVolt3 = (uint16_t)value;
2073 case OD8_SETTING_UCLK_FMAX:
2074 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2075 value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2077 od_table->UclkFmax = (uint16_t)value;
2080 case OD8_SETTING_POWER_PERCENTAGE:
2081 od_table->OverDrivePct = (int16_t)value;
2084 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2085 od_table->FanMaximumRpm = (uint16_t)value;
2088 case OD8_SETTING_FAN_MIN_SPEED:
2089 od_table->FanMinimumPwm = (uint16_t)value;
2092 case OD8_SETTING_FAN_TARGET_TEMP:
2093 od_table->FanTargetTemperature = (uint16_t)value;
2096 case OD8_SETTING_OPERATING_TEMP_MAX:
2097 od_table->MaxOpTemp = (uint16_t)value;
2104 static int vega20_set_od_percentage(struct smu_context *smu,
2105 enum pp_clock_type type,
2108 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2109 struct vega20_dpm_table *dpm_table = NULL;
2110 struct vega20_dpm_table *golden_table = NULL;
2111 struct vega20_single_dpm_table *single_dpm_table;
2112 struct vega20_single_dpm_table *golden_dpm_table;
2113 uint32_t od_clk, index;
2115 int feature_enabled;
2118 mutex_lock(&(smu->mutex));
2120 dpm_table = smu_dpm->dpm_context;
2121 golden_table = smu_dpm->golden_dpm_context;
2125 single_dpm_table = &(dpm_table->gfx_table);
2126 golden_dpm_table = &(golden_table->gfx_table);
2127 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT);
2128 clk_id = PPCLK_GFXCLK;
2129 index = OD8_SETTING_GFXCLK_FMAX;
2132 single_dpm_table = &(dpm_table->mem_table);
2133 golden_dpm_table = &(golden_table->mem_table);
2134 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT);
2135 clk_id = PPCLK_UCLK;
2136 index = OD8_SETTING_UCLK_FMAX;
2146 od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2148 od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2150 ret = smu_update_od8_settings(smu, index, od_clk);
2152 pr_err("[Setoverdrive] failed to set od clk!\n");
2156 if (feature_enabled) {
2157 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2160 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2164 single_dpm_table->count = 1;
2165 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2168 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2169 AMD_PP_TASK_READJUST_POWER_STATE);
2172 mutex_unlock(&(smu->mutex));
2177 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2178 enum PP_OD_DPM_TABLE_COMMAND type,
2179 long *input, uint32_t size)
2181 struct smu_table_context *table_context = &smu->smu_table;
2182 OverDriveTable_t *od_table =
2183 (OverDriveTable_t *)(table_context->overdrive_table);
2184 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2185 struct vega20_dpm_table *dpm_table = NULL;
2186 struct vega20_single_dpm_table *single_dpm_table;
2187 struct vega20_od8_settings *od8_settings =
2188 (struct vega20_od8_settings *)table_context->od8_settings;
2189 struct pp_clock_levels_with_latency clocks;
2190 int32_t input_index, input_clk, input_vol, i;
2194 dpm_table = smu_dpm->dpm_context;
2197 pr_warn("NULL user input for clock and voltage\n");
2202 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2203 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2204 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2205 pr_info("Sclk min/max frequency overdrive not supported\n");
2209 for (i = 0; i < size; i += 2) {
2211 pr_info("invalid number of input parameters %d\n", size);
2215 input_index = input[i];
2216 input_clk = input[i + 1];
2218 if (input_index != 0 && input_index != 1) {
2219 pr_info("Invalid index %d\n", input_index);
2220 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2224 if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2225 input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2226 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2228 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2229 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2233 if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2234 od_table->GfxclkFmin = input_clk;
2235 table_context->od_gfxclk_update = true;
2236 } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2237 od_table->GfxclkFmax = input_clk;
2238 table_context->od_gfxclk_update = true;
2244 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2245 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2246 pr_info("Mclk max frequency overdrive not supported\n");
2250 single_dpm_table = &(dpm_table->mem_table);
2251 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2253 pr_err("Attempt to get memory clk levels Failed!");
2257 for (i = 0; i < size; i += 2) {
2259 pr_info("invalid number of input parameters %d\n",
2264 input_index = input[i];
2265 input_clk = input[i + 1];
2267 if (input_index != 1) {
2268 pr_info("Invalid index %d\n", input_index);
2269 pr_info("Support max Mclk frequency setting only which index by 1\n");
2273 if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2274 input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2275 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2277 clocks.data[0].clocks_in_khz / 1000,
2278 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2282 if (input_index == 1 && od_table->UclkFmax != input_clk) {
2283 table_context->od_gfxclk_update = true;
2284 od_table->UclkFmax = input_clk;
2290 case PP_OD_EDIT_VDDC_CURVE:
2291 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2292 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2293 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2294 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2295 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2296 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2297 pr_info("Voltage curve calibrate not supported\n");
2301 for (i = 0; i < size; i += 3) {
2303 pr_info("invalid number of input parameters %d\n",
2308 input_index = input[i];
2309 input_clk = input[i + 1];
2310 input_vol = input[i + 2];
2312 if (input_index > 2) {
2313 pr_info("Setting for point %d is not supported\n",
2315 pr_info("Three supported points index by 0, 1, 2\n");
2319 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2320 if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2321 input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2322 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2324 od8_settings->od8_settings_array[od8_id].min_value,
2325 od8_settings->od8_settings_array[od8_id].max_value);
2329 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2330 if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2331 input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2332 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2334 od8_settings->od8_settings_array[od8_id].min_value,
2335 od8_settings->od8_settings_array[od8_id].max_value);
2339 switch (input_index) {
2341 od_table->GfxclkFreq1 = input_clk;
2342 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2345 od_table->GfxclkFreq2 = input_clk;
2346 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2349 od_table->GfxclkFreq3 = input_clk;
2350 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2357 case PP_OD_RESTORE_DEFAULT_TABLE:
2358 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
2360 pr_err("Failed to export over drive table!\n");
2366 case PP_OD_COMMIT_DPM_TABLE:
2367 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
2369 pr_err("Failed to import over drive table!\n");
2373 /* retrieve updated gfxclk table */
2374 if (table_context->od_gfxclk_update) {
2375 table_context->od_gfxclk_update = false;
2376 single_dpm_table = &(dpm_table->gfx_table);
2378 if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
2379 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2382 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2386 single_dpm_table->count = 1;
2387 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2397 if (type == PP_OD_COMMIT_DPM_TABLE) {
2398 mutex_lock(&(smu->mutex));
2399 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2400 AMD_PP_TASK_READJUST_POWER_STATE);
2401 mutex_unlock(&(smu->mutex));
2407 static int vega20_get_enabled_smc_features(struct smu_context *smu,
2408 uint64_t *features_enabled)
2410 uint32_t feature_mask[2] = {0, 0};
2413 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2417 *features_enabled = ((((uint64_t)feature_mask[0] << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
2418 (((uint64_t)feature_mask[1] << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
2423 static int vega20_enable_smc_features(struct smu_context *smu,
2424 bool enable, uint64_t feature_mask)
2426 uint32_t smu_features_low, smu_features_high;
2429 smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
2430 smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
2433 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
2437 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
2442 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
2446 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
2456 static int vega20_get_ppfeature_status(struct smu_context *smu, char *buf)
2458 static const char *ppfeature_name[] = {
2493 static const char *output_title[] = {
2497 uint64_t features_enabled;
2502 ret = vega20_get_enabled_smc_features(smu, &features_enabled);
2506 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
2507 size += sprintf(buf + size, "%-19s %-22s %s\n",
2511 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
2512 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
2515 (features_enabled & (1ULL << i)) ? "Y" : "N");
2521 static int vega20_set_ppfeature_status(struct smu_context *smu, uint64_t new_ppfeature_masks)
2523 uint64_t features_enabled;
2524 uint64_t features_to_enable;
2525 uint64_t features_to_disable;
2528 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
2531 ret = vega20_get_enabled_smc_features(smu, &features_enabled);
2535 features_to_disable =
2536 features_enabled & ~new_ppfeature_masks;
2537 features_to_enable =
2538 ~features_enabled & new_ppfeature_masks;
2540 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
2541 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
2543 if (features_to_disable) {
2544 ret = vega20_enable_smc_features(smu, false, features_to_disable);
2549 if (features_to_enable) {
2550 ret = vega20_enable_smc_features(smu, true, features_to_enable);
2558 static const struct pptable_funcs vega20_ppt_funcs = {
2559 .alloc_dpm_context = vega20_allocate_dpm_context,
2560 .store_powerplay_table = vega20_store_powerplay_table,
2561 .check_powerplay_table = vega20_check_powerplay_table,
2562 .append_powerplay_table = vega20_append_powerplay_table,
2563 .get_smu_msg_index = vega20_get_smu_msg_index,
2564 .run_afll_btc = vega20_run_btc_afll,
2565 .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
2566 .get_current_power_state = vega20_get_current_power_state,
2567 .set_default_dpm_table = vega20_set_default_dpm_table,
2568 .set_power_state = NULL,
2569 .populate_umd_state_clk = vega20_populate_umd_state_clk,
2570 .print_clk_levels = vega20_print_clk_levels,
2571 .force_clk_levels = vega20_force_clk_levels,
2572 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
2573 .set_default_od8_settings = vega20_set_default_od8_setttings,
2574 .get_od_percentage = vega20_get_od_percentage,
2575 .conv_profile_to_workload = vega20_conv_profile_to_workload,
2576 .get_performance_level = vega20_get_performance_level,
2577 .force_performance_level = vega20_force_performance_level,
2578 .update_specified_od8_value = vega20_update_specified_od8_value,
2579 .set_od_percentage = vega20_set_od_percentage,
2580 .od_edit_dpm_table = vega20_odn_edit_dpm_table,
2581 .pre_display_config_changed = vega20_pre_display_config_changed,
2582 .display_config_changed = vega20_display_config_changed,
2583 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
2584 .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
2585 .force_dpm_limit_value = vega20_force_dpm_limit_value,
2586 .unforce_dpm_levels = vega20_unforce_dpm_levels,
2587 .upload_dpm_level = vega20_upload_dpm_level,
2588 .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
2589 .set_ppfeature_status = vega20_set_ppfeature_status,
2590 .get_ppfeature_status = vega20_get_ppfeature_status,
2593 void vega20_set_ppt_funcs(struct smu_context *smu)
2595 smu->ppt_funcs = &vega20_ppt_funcs;
2596 smu->smc_if_version = SMU11_DRIVER_IF_VERSION;