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"
39 #include "asic_reg/thm/thm_11_0_2_offset.h"
40 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
42 #define smnPCIE_LC_SPEED_CNTL 0x11140290
43 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
45 #define CTF_OFFSET_EDGE 5
46 #define CTF_OFFSET_HOTSPOT 5
47 #define CTF_OFFSET_HBM 5
49 #define MSG_MAP(msg) \
50 [SMU_MSG_##msg] = PPSMC_MSG_##msg
52 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
53 FEATURE_DPM_GFXCLK_MASK | \
54 FEATURE_DPM_UCLK_MASK | \
55 FEATURE_DPM_SOCCLK_MASK | \
56 FEATURE_DPM_UVD_MASK | \
57 FEATURE_DPM_VCE_MASK | \
58 FEATURE_DPM_MP0CLK_MASK | \
59 FEATURE_DPM_LINK_MASK | \
60 FEATURE_DPM_DCEFCLK_MASK)
62 static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
64 MSG_MAP(GetSmuVersion),
65 MSG_MAP(GetDriverIfVersion),
66 MSG_MAP(SetAllowedFeaturesMaskLow),
67 MSG_MAP(SetAllowedFeaturesMaskHigh),
68 MSG_MAP(EnableAllSmuFeatures),
69 MSG_MAP(DisableAllSmuFeatures),
70 MSG_MAP(EnableSmuFeaturesLow),
71 MSG_MAP(EnableSmuFeaturesHigh),
72 MSG_MAP(DisableSmuFeaturesLow),
73 MSG_MAP(DisableSmuFeaturesHigh),
74 MSG_MAP(GetEnabledSmuFeaturesLow),
75 MSG_MAP(GetEnabledSmuFeaturesHigh),
76 MSG_MAP(SetWorkloadMask),
78 MSG_MAP(SetDriverDramAddrHigh),
79 MSG_MAP(SetDriverDramAddrLow),
80 MSG_MAP(SetToolsDramAddrHigh),
81 MSG_MAP(SetToolsDramAddrLow),
82 MSG_MAP(TransferTableSmu2Dram),
83 MSG_MAP(TransferTableDram2Smu),
84 MSG_MAP(UseDefaultPPTable),
85 MSG_MAP(UseBackupPPTable),
87 MSG_MAP(RequestI2CBus),
88 MSG_MAP(ReleaseI2CBus),
89 MSG_MAP(SetFloorSocVoltage),
91 MSG_MAP(StartBacoMonitor),
92 MSG_MAP(CancelBacoMonitor),
94 MSG_MAP(SetSoftMinByFreq),
95 MSG_MAP(SetSoftMaxByFreq),
96 MSG_MAP(SetHardMinByFreq),
97 MSG_MAP(SetHardMaxByFreq),
98 MSG_MAP(GetMinDpmFreq),
99 MSG_MAP(GetMaxDpmFreq),
100 MSG_MAP(GetDpmFreqByIndex),
101 MSG_MAP(GetDpmClockFreq),
102 MSG_MAP(GetSsVoltageByDpm),
103 MSG_MAP(SetMemoryChannelConfig),
104 MSG_MAP(SetGeminiMode),
105 MSG_MAP(SetGeminiApertureHigh),
106 MSG_MAP(SetGeminiApertureLow),
107 MSG_MAP(SetMinLinkDpmByIndex),
108 MSG_MAP(OverridePcieParameters),
109 MSG_MAP(OverDriveSetPercentage),
110 MSG_MAP(SetMinDeepSleepDcefclk),
111 MSG_MAP(ReenableAcDcInterrupt),
112 MSG_MAP(NotifyPowerSource),
113 MSG_MAP(SetUclkFastSwitch),
114 MSG_MAP(SetUclkDownHyst),
115 MSG_MAP(GetCurrentRpm),
116 MSG_MAP(SetVideoFps),
118 MSG_MAP(SetFanTemperatureTarget),
119 MSG_MAP(PrepareMp1ForUnload),
120 MSG_MAP(DramLogSetDramAddrHigh),
121 MSG_MAP(DramLogSetDramAddrLow),
122 MSG_MAP(DramLogSetDramSize),
123 MSG_MAP(SetFanMaxRpm),
124 MSG_MAP(SetFanMinPwm),
125 MSG_MAP(ConfigureGfxDidt),
126 MSG_MAP(NumOfDisplays),
127 MSG_MAP(RemoveMargins),
128 MSG_MAP(ReadSerialNumTop32),
129 MSG_MAP(ReadSerialNumBottom32),
130 MSG_MAP(SetSystemVirtualDramAddrHigh),
131 MSG_MAP(SetSystemVirtualDramAddrLow),
133 MSG_MAP(SetFclkGfxClkRatio),
134 MSG_MAP(AllowGfxOff),
135 MSG_MAP(DisallowGfxOff),
136 MSG_MAP(GetPptLimit),
137 MSG_MAP(GetDcModeMaxDpmFreq),
138 MSG_MAP(GetDebugData),
139 MSG_MAP(SetXgmiMode),
142 MSG_MAP(PrepareMp1ForReset),
143 MSG_MAP(PrepareMp1ForShutdown),
144 MSG_MAP(SetMGpuFanBoostLimitRpm),
145 MSG_MAP(GetAVFSVoltageByDpm),
148 static int vega20_clk_map[SMU_CLK_COUNT] = {
149 CLK_MAP(GFXCLK, PPCLK_GFXCLK),
150 CLK_MAP(VCLK, PPCLK_VCLK),
151 CLK_MAP(DCLK, PPCLK_DCLK),
152 CLK_MAP(ECLK, PPCLK_ECLK),
153 CLK_MAP(SOCCLK, PPCLK_SOCCLK),
154 CLK_MAP(UCLK, PPCLK_UCLK),
155 CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
156 CLK_MAP(DISPCLK, PPCLK_DISPCLK),
157 CLK_MAP(PIXCLK, PPCLK_PIXCLK),
158 CLK_MAP(PHYCLK, PPCLK_PHYCLK),
159 CLK_MAP(FCLK, PPCLK_FCLK),
162 static int vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
163 FEA_MAP(DPM_PREFETCHER),
172 FEA_MAP(DPM_DCEFCLK),
179 FEA_MAP(GFX_PER_CU_CG),
186 FEA_MAP(LED_DISPLAY),
187 FEA_MAP(FAN_CONTROL),
198 static int vega20_table_map[SMU_TABLE_COUNT] = {
202 TAB_MAP(AVFS_PSM_DEBUG),
203 TAB_MAP(AVFS_FUSE_OVERRIDE),
204 TAB_MAP(PMSTATUSLOG),
205 TAB_MAP(SMU_METRICS),
206 TAB_MAP(DRIVER_SMU_CONFIG),
207 TAB_MAP(ACTIVITY_MONITOR_COEFF),
211 static int vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
216 static int vega20_workload_map[] = {
217 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_DEFAULT_BIT),
218 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
219 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
220 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
221 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
222 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT),
223 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
226 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
229 if (index >= SMU_TABLE_COUNT)
232 val = vega20_table_map[index];
233 if (val >= TABLE_COUNT)
239 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
242 if (index >= SMU_POWER_SOURCE_COUNT)
245 val = vega20_pwr_src_map[index];
246 if (val >= POWER_SOURCE_COUNT)
252 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
255 if (index >= SMU_FEATURE_COUNT)
258 val = vega20_feature_mask_map[index];
265 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
268 if (index >= SMU_CLK_COUNT)
271 val = vega20_clk_map[index];
272 if (val >= PPCLK_COUNT)
278 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
282 if (index >= SMU_MSG_MAX_COUNT)
285 val = vega20_message_map[index];
286 if (val > PPSMC_Message_Count)
292 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
295 if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
298 val = vega20_workload_map[profile];
303 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
305 struct smu_table_context *smu_table = &smu->smu_table;
307 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
308 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
309 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
310 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
311 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
312 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
313 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
314 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
315 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
316 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
317 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
318 sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
319 AMDGPU_GEM_DOMAIN_VRAM);
321 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
322 if (smu_table->metrics_table)
324 smu_table->metrics_time = 0;
329 static int vega20_allocate_dpm_context(struct smu_context *smu)
331 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
333 if (smu_dpm->dpm_context)
336 smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
338 if (!smu_dpm->dpm_context)
341 if (smu_dpm->golden_dpm_context)
344 smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
346 if (!smu_dpm->golden_dpm_context)
349 smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
351 smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
353 if (!smu_dpm->dpm_current_power_state)
356 smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
358 if (!smu_dpm->dpm_request_power_state)
364 static int vega20_setup_od8_information(struct smu_context *smu)
366 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
367 struct smu_table_context *table_context = &smu->smu_table;
369 uint32_t od_feature_count, od_feature_array_size,
370 od_setting_count, od_setting_array_size;
372 if (!table_context->power_play_table)
375 powerplay_table = table_context->power_play_table;
377 if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
378 /* Setup correct ODFeatureCount, and store ODFeatureArray from
379 * powerplay table to od_feature_capabilities */
381 (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
382 ATOM_VEGA20_ODFEATURE_COUNT) ?
383 ATOM_VEGA20_ODFEATURE_COUNT :
384 le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
386 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
388 if (table_context->od_feature_capabilities)
391 table_context->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
392 od_feature_array_size,
394 if (!table_context->od_feature_capabilities)
397 /* Setup correct ODSettingCount, and store ODSettingArray from
398 * powerplay table to od_settings_max and od_setting_min */
400 (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
401 ATOM_VEGA20_ODSETTING_COUNT) ?
402 ATOM_VEGA20_ODSETTING_COUNT :
403 le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
405 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
407 if (table_context->od_settings_max)
410 table_context->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
411 od_setting_array_size,
414 if (!table_context->od_settings_max) {
415 kfree(table_context->od_feature_capabilities);
416 table_context->od_feature_capabilities = NULL;
420 if (table_context->od_settings_min)
423 table_context->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
424 od_setting_array_size,
427 if (!table_context->od_settings_min) {
428 kfree(table_context->od_feature_capabilities);
429 table_context->od_feature_capabilities = NULL;
430 kfree(table_context->od_settings_max);
431 table_context->od_settings_max = NULL;
439 static int vega20_store_powerplay_table(struct smu_context *smu)
441 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
442 struct smu_table_context *table_context = &smu->smu_table;
445 if (!table_context->power_play_table)
448 powerplay_table = table_context->power_play_table;
450 memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
453 table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
454 table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
455 table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
457 ret = vega20_setup_od8_information(smu);
462 static int vega20_append_powerplay_table(struct smu_context *smu)
464 struct smu_table_context *table_context = &smu->smu_table;
465 PPTable_t *smc_pptable = table_context->driver_pptable;
466 struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
469 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
472 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
473 (uint8_t **)&smc_dpm_table);
477 smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
478 smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
480 smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
481 smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
482 smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
483 smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
485 smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
486 smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
487 smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
489 smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
490 smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
491 smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
493 smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
494 smc_pptable->SocOffset = smc_dpm_table->socoffset;
495 smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
497 smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
498 smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
499 smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
501 smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
502 smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
503 smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
505 smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
506 smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
507 smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
508 smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
510 smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
511 smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
512 smc_pptable->Padding1 = smc_dpm_table->padding1;
513 smc_pptable->Padding2 = smc_dpm_table->padding2;
515 smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
516 smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
517 smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
519 smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
520 smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
521 smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
523 smc_pptable->UclkSpreadEnabled = 0;
524 smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
525 smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
527 smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
528 smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
529 smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
531 smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
532 smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
533 smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
535 for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
536 smc_pptable->I2cControllers[i].Enabled =
537 smc_dpm_table->i2ccontrollers[i].enabled;
538 smc_pptable->I2cControllers[i].SlaveAddress =
539 smc_dpm_table->i2ccontrollers[i].slaveaddress;
540 smc_pptable->I2cControllers[i].ControllerPort =
541 smc_dpm_table->i2ccontrollers[i].controllerport;
542 smc_pptable->I2cControllers[i].ThermalThrottler =
543 smc_dpm_table->i2ccontrollers[i].thermalthrottler;
544 smc_pptable->I2cControllers[i].I2cProtocol =
545 smc_dpm_table->i2ccontrollers[i].i2cprotocol;
546 smc_pptable->I2cControllers[i].I2cSpeed =
547 smc_dpm_table->i2ccontrollers[i].i2cspeed;
553 static int vega20_check_powerplay_table(struct smu_context *smu)
555 ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
556 struct smu_table_context *table_context = &smu->smu_table;
558 powerplay_table = table_context->power_play_table;
560 if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
561 pr_err("Unsupported PPTable format!");
565 if (!powerplay_table->sHeader.structuresize) {
566 pr_err("Invalid PowerPlay Table!");
573 static int vega20_run_btc_afll(struct smu_context *smu)
575 return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
578 #define FEATURE_MASK(feature) (1UL << feature)
580 vega20_get_allowed_feature_mask(struct smu_context *smu,
581 uint32_t *feature_mask, uint32_t num)
586 memset(feature_mask, 0, sizeof(uint32_t) * num);
588 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
589 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
590 | FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
591 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
592 | FEATURE_MASK(FEATURE_DPM_UVD_BIT)
593 | FEATURE_MASK(FEATURE_DPM_VCE_BIT)
594 | FEATURE_MASK(FEATURE_ULV_BIT)
595 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
596 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
597 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
598 | FEATURE_MASK(FEATURE_PPT_BIT)
599 | FEATURE_MASK(FEATURE_TDC_BIT)
600 | FEATURE_MASK(FEATURE_THERMAL_BIT)
601 | FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT)
602 | FEATURE_MASK(FEATURE_RM_BIT)
603 | FEATURE_MASK(FEATURE_ACDC_BIT)
604 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
605 | FEATURE_MASK(FEATURE_VR1HOT_BIT)
606 | FEATURE_MASK(FEATURE_FW_CTF_BIT)
607 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
608 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
609 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
610 | FEATURE_MASK(FEATURE_GFXOFF_BIT)
611 | FEATURE_MASK(FEATURE_CG_BIT)
612 | FEATURE_MASK(FEATURE_DPM_FCLK_BIT)
613 | FEATURE_MASK(FEATURE_XGMI_BIT);
618 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
620 enum amd_pm_state_type pm_type;
621 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
623 if (!smu_dpm_ctx->dpm_context ||
624 !smu_dpm_ctx->dpm_current_power_state)
627 mutex_lock(&(smu->mutex));
628 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
629 case SMU_STATE_UI_LABEL_BATTERY:
630 pm_type = POWER_STATE_TYPE_BATTERY;
632 case SMU_STATE_UI_LABEL_BALLANCED:
633 pm_type = POWER_STATE_TYPE_BALANCED;
635 case SMU_STATE_UI_LABEL_PERFORMANCE:
636 pm_type = POWER_STATE_TYPE_PERFORMANCE;
639 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
640 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
642 pm_type = POWER_STATE_TYPE_DEFAULT;
645 mutex_unlock(&(smu->mutex));
651 vega20_set_single_dpm_table(struct smu_context *smu,
652 struct vega20_single_dpm_table *single_dpm_table,
656 uint32_t i, num_of_levels = 0, clk;
658 ret = smu_send_smc_msg_with_param(smu,
659 SMU_MSG_GetDpmFreqByIndex,
660 (clk_id << 16 | 0xFF));
662 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
666 smu_read_smc_arg(smu, &num_of_levels);
667 if (!num_of_levels) {
668 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
672 single_dpm_table->count = num_of_levels;
674 for (i = 0; i < num_of_levels; i++) {
675 ret = smu_send_smc_msg_with_param(smu,
676 SMU_MSG_GetDpmFreqByIndex,
679 pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
682 smu_read_smc_arg(smu, &clk);
684 pr_err("[GetDpmFreqByIndex] clk value is invalid!");
687 single_dpm_table->dpm_levels[i].value = clk;
688 single_dpm_table->dpm_levels[i].enabled = true;
693 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
695 dpm_state->soft_min_level = 0x0;
696 dpm_state->soft_max_level = 0xffff;
697 dpm_state->hard_min_level = 0x0;
698 dpm_state->hard_max_level = 0xffff;
701 static int vega20_set_default_dpm_table(struct smu_context *smu)
705 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
706 struct vega20_dpm_table *dpm_table = NULL;
707 struct vega20_single_dpm_table *single_dpm_table;
709 dpm_table = smu_dpm->dpm_context;
712 single_dpm_table = &(dpm_table->soc_table);
714 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
715 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
718 pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
722 single_dpm_table->count = 1;
723 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
725 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
728 single_dpm_table = &(dpm_table->gfx_table);
730 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
731 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
734 pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
738 single_dpm_table->count = 1;
739 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
741 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
744 single_dpm_table = &(dpm_table->mem_table);
746 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
747 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
750 pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
754 single_dpm_table->count = 1;
755 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
757 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
760 single_dpm_table = &(dpm_table->eclk_table);
762 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) {
763 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
765 pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
769 single_dpm_table->count = 1;
770 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
772 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
775 single_dpm_table = &(dpm_table->vclk_table);
777 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
778 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
780 pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
784 single_dpm_table->count = 1;
785 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
787 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
790 single_dpm_table = &(dpm_table->dclk_table);
792 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
793 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
795 pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
799 single_dpm_table->count = 1;
800 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
802 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
805 single_dpm_table = &(dpm_table->dcef_table);
807 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
808 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
811 pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
815 single_dpm_table->count = 1;
816 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
818 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
821 single_dpm_table = &(dpm_table->pixel_table);
823 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
824 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
827 pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
831 single_dpm_table->count = 0;
833 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
836 single_dpm_table = &(dpm_table->display_table);
838 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
839 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
842 pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
846 single_dpm_table->count = 0;
848 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
851 single_dpm_table = &(dpm_table->phy_table);
853 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
854 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
857 pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
861 single_dpm_table->count = 0;
863 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
866 single_dpm_table = &(dpm_table->fclk_table);
868 if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
869 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
872 pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
876 single_dpm_table->count = 0;
878 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
880 memcpy(smu_dpm->golden_dpm_context, dpm_table,
881 sizeof(struct vega20_dpm_table));
886 static int vega20_populate_umd_state_clk(struct smu_context *smu)
888 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
889 struct vega20_dpm_table *dpm_table = NULL;
890 struct vega20_single_dpm_table *gfx_table = NULL;
891 struct vega20_single_dpm_table *mem_table = NULL;
893 dpm_table = smu_dpm->dpm_context;
894 gfx_table = &(dpm_table->gfx_table);
895 mem_table = &(dpm_table->mem_table);
897 smu->pstate_sclk = gfx_table->dpm_levels[0].value;
898 smu->pstate_mclk = mem_table->dpm_levels[0].value;
900 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
901 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
902 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
903 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
906 smu->pstate_sclk = smu->pstate_sclk * 100;
907 smu->pstate_mclk = smu->pstate_mclk * 100;
912 static int vega20_get_clk_table(struct smu_context *smu,
913 struct pp_clock_levels_with_latency *clocks,
914 struct vega20_single_dpm_table *dpm_table)
918 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
919 clocks->num_levels = count;
921 for (i = 0; i < count; i++) {
922 clocks->data[i].clocks_in_khz =
923 dpm_table->dpm_levels[i].value * 1000;
924 clocks->data[i].latency_in_us = 0;
930 static int vega20_print_clk_levels(struct smu_context *smu,
931 enum smu_clk_type type, char *buf)
933 int i, now, size = 0;
935 uint32_t gen_speed, lane_width;
936 struct amdgpu_device *adev = smu->adev;
937 struct pp_clock_levels_with_latency clocks;
938 struct vega20_single_dpm_table *single_dpm_table;
939 struct smu_table_context *table_context = &smu->smu_table;
940 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
941 struct vega20_dpm_table *dpm_table = NULL;
942 struct vega20_od8_settings *od8_settings =
943 (struct vega20_od8_settings *)table_context->od8_settings;
944 OverDriveTable_t *od_table =
945 (OverDriveTable_t *)(table_context->overdrive_table);
946 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
948 dpm_table = smu_dpm->dpm_context;
952 ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now);
954 pr_err("Attempt to get current gfx clk Failed!");
958 single_dpm_table = &(dpm_table->gfx_table);
959 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
961 pr_err("Attempt to get gfx clk levels Failed!");
965 for (i = 0; i < clocks.num_levels; i++)
966 size += sprintf(buf + size, "%d: %uMhz %s\n", i,
967 clocks.data[i].clocks_in_khz / 1000,
968 (clocks.data[i].clocks_in_khz == now * 10)
973 ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now);
975 pr_err("Attempt to get current mclk Failed!");
979 single_dpm_table = &(dpm_table->mem_table);
980 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
982 pr_err("Attempt to get memory clk levels Failed!");
986 for (i = 0; i < clocks.num_levels; i++)
987 size += sprintf(buf + size, "%d: %uMhz %s\n",
988 i, clocks.data[i].clocks_in_khz / 1000,
989 (clocks.data[i].clocks_in_khz == now * 10)
994 ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, &now);
996 pr_err("Attempt to get current socclk Failed!");
1000 single_dpm_table = &(dpm_table->soc_table);
1001 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1003 pr_err("Attempt to get socclk levels Failed!");
1007 for (i = 0; i < clocks.num_levels; i++)
1008 size += sprintf(buf + size, "%d: %uMhz %s\n",
1009 i, clocks.data[i].clocks_in_khz / 1000,
1010 (clocks.data[i].clocks_in_khz == now * 10)
1015 ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now);
1017 pr_err("Attempt to get current fclk Failed!");
1021 single_dpm_table = &(dpm_table->fclk_table);
1022 for (i = 0; i < single_dpm_table->count; i++)
1023 size += sprintf(buf + size, "%d: %uMhz %s\n",
1024 i, single_dpm_table->dpm_levels[i].value,
1025 (single_dpm_table->dpm_levels[i].value == now / 100)
1030 ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, &now);
1032 pr_err("Attempt to get current dcefclk Failed!");
1036 single_dpm_table = &(dpm_table->dcef_table);
1037 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1039 pr_err("Attempt to get dcefclk levels Failed!");
1043 for (i = 0; i < clocks.num_levels; i++)
1044 size += sprintf(buf + size, "%d: %uMhz %s\n",
1045 i, clocks.data[i].clocks_in_khz / 1000,
1046 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
1050 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
1051 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
1052 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
1053 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
1054 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
1055 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
1056 for (i = 0; i < NUM_LINK_LEVELS; i++)
1057 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
1058 (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
1059 (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
1060 (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
1061 (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
1062 (pptable->PcieLaneCount[i] == 1) ? "x1" :
1063 (pptable->PcieLaneCount[i] == 2) ? "x2" :
1064 (pptable->PcieLaneCount[i] == 3) ? "x4" :
1065 (pptable->PcieLaneCount[i] == 4) ? "x8" :
1066 (pptable->PcieLaneCount[i] == 5) ? "x12" :
1067 (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
1068 pptable->LclkFreq[i],
1069 (gen_speed == pptable->PcieGenSpeed[i]) &&
1070 (lane_width == pptable->PcieLaneCount[i]) ?
1075 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1076 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1077 size = sprintf(buf, "%s:\n", "OD_SCLK");
1078 size += sprintf(buf + size, "0: %10uMhz\n",
1079 od_table->GfxclkFmin);
1080 size += sprintf(buf + size, "1: %10uMhz\n",
1081 od_table->GfxclkFmax);
1087 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1088 size = sprintf(buf, "%s:\n", "OD_MCLK");
1089 size += sprintf(buf + size, "1: %10uMhz\n",
1090 od_table->UclkFmax);
1095 case SMU_OD_VDDC_CURVE:
1096 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1097 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1098 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1099 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1100 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1101 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1102 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
1103 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
1104 od_table->GfxclkFreq1,
1105 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
1106 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
1107 od_table->GfxclkFreq2,
1108 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
1109 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
1110 od_table->GfxclkFreq3,
1111 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
1117 size = sprintf(buf, "%s:\n", "OD_RANGE");
1119 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1120 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1121 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
1122 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
1123 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
1126 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1127 single_dpm_table = &(dpm_table->mem_table);
1128 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1130 pr_err("Attempt to get memory clk levels Failed!");
1134 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
1135 clocks.data[0].clocks_in_khz / 1000,
1136 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
1139 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1140 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1141 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1142 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1143 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1144 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1145 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1146 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
1147 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
1148 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1149 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
1150 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
1151 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1152 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
1153 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
1154 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1155 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
1156 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
1157 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1158 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
1159 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
1160 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1161 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
1162 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
1173 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
1174 uint32_t feature_mask)
1176 struct vega20_dpm_table *dpm_table;
1177 struct vega20_single_dpm_table *single_dpm_table;
1181 dpm_table = smu->smu_dpm.dpm_context;
1183 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
1184 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1185 single_dpm_table = &(dpm_table->gfx_table);
1186 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1187 single_dpm_table->dpm_state.soft_min_level;
1188 ret = smu_send_smc_msg_with_param(smu,
1189 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1190 (PPCLK_GFXCLK << 16) | (freq & 0xffff));
1192 pr_err("Failed to set soft %s gfxclk !\n",
1193 max ? "max" : "min");
1198 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
1199 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1200 single_dpm_table = &(dpm_table->mem_table);
1201 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1202 single_dpm_table->dpm_state.soft_min_level;
1203 ret = smu_send_smc_msg_with_param(smu,
1204 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1205 (PPCLK_UCLK << 16) | (freq & 0xffff));
1207 pr_err("Failed to set soft %s memclk !\n",
1208 max ? "max" : "min");
1213 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
1214 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1215 single_dpm_table = &(dpm_table->soc_table);
1216 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1217 single_dpm_table->dpm_state.soft_min_level;
1218 ret = smu_send_smc_msg_with_param(smu,
1219 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1220 (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1222 pr_err("Failed to set soft %s socclk !\n",
1223 max ? "max" : "min");
1228 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) &&
1229 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1230 single_dpm_table = &(dpm_table->fclk_table);
1231 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1232 single_dpm_table->dpm_state.soft_min_level;
1233 ret = smu_send_smc_msg_with_param(smu,
1234 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1235 (PPCLK_FCLK << 16) | (freq & 0xffff));
1237 pr_err("Failed to set soft %s fclk !\n",
1238 max ? "max" : "min");
1243 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
1244 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1245 single_dpm_table = &(dpm_table->dcef_table);
1246 freq = single_dpm_table->dpm_state.hard_min_level;
1248 ret = smu_send_smc_msg_with_param(smu,
1249 SMU_MSG_SetHardMinByFreq,
1250 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1252 pr_err("Failed to set hard min dcefclk !\n");
1261 static int vega20_force_clk_levels(struct smu_context *smu,
1262 enum smu_clk_type clk_type, uint32_t mask)
1264 struct vega20_dpm_table *dpm_table;
1265 struct vega20_single_dpm_table *single_dpm_table;
1266 uint32_t soft_min_level, soft_max_level, hard_min_level;
1267 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1270 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1271 pr_info("force clock level is for dpm manual mode only.\n");
1275 mutex_lock(&(smu->mutex));
1277 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1278 soft_max_level = mask ? (fls(mask) - 1) : 0;
1280 dpm_table = smu->smu_dpm.dpm_context;
1284 single_dpm_table = &(dpm_table->gfx_table);
1286 if (soft_max_level >= single_dpm_table->count) {
1287 pr_err("Clock level specified %d is over max allowed %d\n",
1288 soft_max_level, single_dpm_table->count - 1);
1293 single_dpm_table->dpm_state.soft_min_level =
1294 single_dpm_table->dpm_levels[soft_min_level].value;
1295 single_dpm_table->dpm_state.soft_max_level =
1296 single_dpm_table->dpm_levels[soft_max_level].value;
1298 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1300 pr_err("Failed to upload boot level to lowest!\n");
1304 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1306 pr_err("Failed to upload dpm max level to highest!\n");
1311 single_dpm_table = &(dpm_table->mem_table);
1313 if (soft_max_level >= single_dpm_table->count) {
1314 pr_err("Clock level specified %d is over max allowed %d\n",
1315 soft_max_level, single_dpm_table->count - 1);
1320 single_dpm_table->dpm_state.soft_min_level =
1321 single_dpm_table->dpm_levels[soft_min_level].value;
1322 single_dpm_table->dpm_state.soft_max_level =
1323 single_dpm_table->dpm_levels[soft_max_level].value;
1325 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1327 pr_err("Failed to upload boot level to lowest!\n");
1331 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1333 pr_err("Failed to upload dpm max level to highest!\n");
1338 single_dpm_table = &(dpm_table->soc_table);
1340 if (soft_max_level >= single_dpm_table->count) {
1341 pr_err("Clock level specified %d is over max allowed %d\n",
1342 soft_max_level, single_dpm_table->count - 1);
1347 single_dpm_table->dpm_state.soft_min_level =
1348 single_dpm_table->dpm_levels[soft_min_level].value;
1349 single_dpm_table->dpm_state.soft_max_level =
1350 single_dpm_table->dpm_levels[soft_max_level].value;
1352 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1354 pr_err("Failed to upload boot level to lowest!\n");
1358 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1360 pr_err("Failed to upload dpm max level to highest!\n");
1365 single_dpm_table = &(dpm_table->fclk_table);
1367 if (soft_max_level >= single_dpm_table->count) {
1368 pr_err("Clock level specified %d is over max allowed %d\n",
1369 soft_max_level, single_dpm_table->count - 1);
1374 single_dpm_table->dpm_state.soft_min_level =
1375 single_dpm_table->dpm_levels[soft_min_level].value;
1376 single_dpm_table->dpm_state.soft_max_level =
1377 single_dpm_table->dpm_levels[soft_max_level].value;
1379 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1381 pr_err("Failed to upload boot level to lowest!\n");
1385 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1387 pr_err("Failed to upload dpm max level to highest!\n");
1392 hard_min_level = soft_min_level;
1393 single_dpm_table = &(dpm_table->dcef_table);
1395 if (hard_min_level >= single_dpm_table->count) {
1396 pr_err("Clock level specified %d is over max allowed %d\n",
1397 hard_min_level, single_dpm_table->count - 1);
1402 single_dpm_table->dpm_state.hard_min_level =
1403 single_dpm_table->dpm_levels[hard_min_level].value;
1405 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1407 pr_err("Failed to upload boot level to lowest!\n");
1412 if (soft_min_level >= NUM_LINK_LEVELS ||
1413 soft_max_level >= NUM_LINK_LEVELS) {
1418 ret = smu_send_smc_msg_with_param(smu,
1419 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1421 pr_err("Failed to set min link dpm level!\n");
1429 mutex_unlock(&(smu->mutex));
1433 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1434 enum smu_clk_type clk_type,
1435 struct pp_clock_levels_with_latency *clocks)
1438 struct vega20_single_dpm_table *single_dpm_table;
1439 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1440 struct vega20_dpm_table *dpm_table = NULL;
1442 dpm_table = smu_dpm->dpm_context;
1444 mutex_lock(&smu->mutex);
1448 single_dpm_table = &(dpm_table->gfx_table);
1449 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1452 single_dpm_table = &(dpm_table->mem_table);
1453 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1456 single_dpm_table = &(dpm_table->dcef_table);
1457 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1460 single_dpm_table = &(dpm_table->soc_table);
1461 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1467 mutex_unlock(&smu->mutex);
1471 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1477 ret = smu_send_smc_msg_with_param(smu,
1478 SMU_MSG_GetAVFSVoltageByDpm,
1479 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1481 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1485 smu_read_smc_arg(smu, voltage);
1486 *voltage = *voltage / VOLTAGE_SCALE;
1491 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1493 struct smu_table_context *table_context = &smu->smu_table;
1494 OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1495 struct vega20_od8_settings *od8_settings = NULL;
1496 PPTable_t *smc_pptable = table_context->driver_pptable;
1499 if (table_context->od8_settings)
1502 table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1504 if (!table_context->od8_settings)
1507 od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
1509 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
1510 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1511 table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1512 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1513 (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1514 table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1515 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1517 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1519 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1520 od_table->GfxclkFmin;
1521 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1522 od_table->GfxclkFmax;
1525 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1526 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1527 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1528 (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1529 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1530 (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1531 table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1532 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1534 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1536 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1538 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1540 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1542 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1545 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1546 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1547 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1548 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1549 od_table->GfxclkFreq1;
1550 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1551 od_table->GfxclkFreq2;
1552 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1553 od_table->GfxclkFreq3;
1555 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1556 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1557 od_table->GfxclkFreq1);
1559 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1560 od_table->GfxclkVolt1 =
1561 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1563 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1564 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1565 od_table->GfxclkFreq2);
1567 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1568 od_table->GfxclkVolt2 =
1569 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1571 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1572 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1573 od_table->GfxclkFreq3);
1575 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1576 od_table->GfxclkVolt3 =
1577 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1582 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1583 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1584 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1585 table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1586 (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1587 table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1588 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1590 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1595 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1596 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1597 table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1598 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1599 table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1600 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1602 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1603 od_table->OverDrivePct;
1606 if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) {
1607 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1608 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1609 table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1610 (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1611 table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1612 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1613 OD8_ACOUSTIC_LIMIT_SCLK;
1614 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1615 od_table->FanMaximumRpm;
1618 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1619 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1620 table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1621 (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1622 table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1623 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1625 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1626 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1630 if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) {
1631 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1632 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1633 table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1634 (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1635 table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1636 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1637 OD8_TEMPERATURE_FAN;
1638 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1639 od_table->FanTargetTemperature;
1642 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1643 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1644 table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1645 (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1646 table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1647 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1648 OD8_TEMPERATURE_SYSTEM;
1649 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1650 od_table->MaxOpTemp;
1654 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1655 if (od8_settings->od8_settings_array[i].feature_id) {
1656 od8_settings->od8_settings_array[i].min_value =
1657 table_context->od_settings_min[i];
1658 od8_settings->od8_settings_array[i].max_value =
1659 table_context->od_settings_max[i];
1660 od8_settings->od8_settings_array[i].current_value =
1661 od8_settings->od8_settings_array[i].default_value;
1663 od8_settings->od8_settings_array[i].min_value = 0;
1664 od8_settings->od8_settings_array[i].max_value = 0;
1665 od8_settings->od8_settings_array[i].current_value = 0;
1672 static int vega20_get_metrics_table(struct smu_context *smu,
1673 SmuMetrics_t *metrics_table)
1675 struct smu_table_context *smu_table= &smu->smu_table;
1678 if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
1679 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS,
1680 (void *)smu_table->metrics_table, false);
1682 pr_info("Failed to export SMU metrics table!\n");
1685 smu_table->metrics_time = jiffies;
1688 memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
1693 static int vega20_set_default_od_settings(struct smu_context *smu,
1696 struct smu_table_context *table_context = &smu->smu_table;
1700 if (table_context->overdrive_table)
1703 table_context->overdrive_table = kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL);
1705 if (!table_context->overdrive_table)
1708 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
1709 table_context->overdrive_table, false);
1711 pr_err("Failed to export over drive table!\n");
1715 ret = vega20_set_default_od8_setttings(smu);
1720 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
1721 table_context->overdrive_table, true);
1723 pr_err("Failed to import over drive table!\n");
1730 static int vega20_get_od_percentage(struct smu_context *smu,
1731 enum smu_clk_type clk_type)
1733 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1734 struct vega20_dpm_table *dpm_table = NULL;
1735 struct vega20_dpm_table *golden_table = NULL;
1736 struct vega20_single_dpm_table *single_dpm_table;
1737 struct vega20_single_dpm_table *golden_dpm_table;
1738 int value, golden_value;
1740 dpm_table = smu_dpm->dpm_context;
1741 golden_table = smu_dpm->golden_dpm_context;
1745 single_dpm_table = &(dpm_table->gfx_table);
1746 golden_dpm_table = &(golden_table->gfx_table);
1749 single_dpm_table = &(dpm_table->mem_table);
1750 golden_dpm_table = &(golden_table->mem_table);
1757 value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1758 golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1760 value -= golden_value;
1761 value = DIV_ROUND_UP(value * 100, golden_value);
1766 static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
1768 DpmActivityMonitorCoeffInt_t activity_monitor;
1769 uint32_t i, size = 0;
1770 uint16_t workload_type = 0;
1771 static const char *profile_name[] = {
1779 static const char *title[] = {
1780 "PROFILE_INDEX(NAME)",
1784 "MinActiveFreqType",
1789 "PD_Data_error_coeff",
1790 "PD_Data_error_rate_coeff"};
1793 if (!smu->pm_enabled || !buf)
1796 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1797 title[0], title[1], title[2], title[3], title[4], title[5],
1798 title[6], title[7], title[8], title[9], title[10]);
1800 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1801 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1802 workload_type = smu_workload_get_type(smu, i);
1803 result = smu_update_table(smu,
1804 TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16,
1805 (void *)(&activity_monitor), false);
1807 pr_err("[%s] Failed to get activity monitor!", __func__);
1811 size += sprintf(buf + size, "%2d %14s%s:\n",
1812 i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1814 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1818 activity_monitor.Gfx_FPS,
1819 activity_monitor.Gfx_UseRlcBusy,
1820 activity_monitor.Gfx_MinActiveFreqType,
1821 activity_monitor.Gfx_MinActiveFreq,
1822 activity_monitor.Gfx_BoosterFreqType,
1823 activity_monitor.Gfx_BoosterFreq,
1824 activity_monitor.Gfx_PD_Data_limit_c,
1825 activity_monitor.Gfx_PD_Data_error_coeff,
1826 activity_monitor.Gfx_PD_Data_error_rate_coeff);
1828 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1832 activity_monitor.Soc_FPS,
1833 activity_monitor.Soc_UseRlcBusy,
1834 activity_monitor.Soc_MinActiveFreqType,
1835 activity_monitor.Soc_MinActiveFreq,
1836 activity_monitor.Soc_BoosterFreqType,
1837 activity_monitor.Soc_BoosterFreq,
1838 activity_monitor.Soc_PD_Data_limit_c,
1839 activity_monitor.Soc_PD_Data_error_coeff,
1840 activity_monitor.Soc_PD_Data_error_rate_coeff);
1842 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1846 activity_monitor.Mem_FPS,
1847 activity_monitor.Mem_UseRlcBusy,
1848 activity_monitor.Mem_MinActiveFreqType,
1849 activity_monitor.Mem_MinActiveFreq,
1850 activity_monitor.Mem_BoosterFreqType,
1851 activity_monitor.Mem_BoosterFreq,
1852 activity_monitor.Mem_PD_Data_limit_c,
1853 activity_monitor.Mem_PD_Data_error_coeff,
1854 activity_monitor.Mem_PD_Data_error_rate_coeff);
1856 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1860 activity_monitor.Fclk_FPS,
1861 activity_monitor.Fclk_UseRlcBusy,
1862 activity_monitor.Fclk_MinActiveFreqType,
1863 activity_monitor.Fclk_MinActiveFreq,
1864 activity_monitor.Fclk_BoosterFreqType,
1865 activity_monitor.Fclk_BoosterFreq,
1866 activity_monitor.Fclk_PD_Data_limit_c,
1867 activity_monitor.Fclk_PD_Data_error_coeff,
1868 activity_monitor.Fclk_PD_Data_error_rate_coeff);
1874 static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1876 DpmActivityMonitorCoeffInt_t activity_monitor;
1877 int workload_type = 0, ret = 0;
1879 smu->power_profile_mode = input[size];
1881 if (!smu->pm_enabled)
1883 if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1884 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1888 if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1889 ret = smu_update_table(smu,
1890 TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
1891 (void *)(&activity_monitor), false);
1893 pr_err("[%s] Failed to get activity monitor!", __func__);
1898 case 0: /* Gfxclk */
1899 activity_monitor.Gfx_FPS = input[1];
1900 activity_monitor.Gfx_UseRlcBusy = input[2];
1901 activity_monitor.Gfx_MinActiveFreqType = input[3];
1902 activity_monitor.Gfx_MinActiveFreq = input[4];
1903 activity_monitor.Gfx_BoosterFreqType = input[5];
1904 activity_monitor.Gfx_BoosterFreq = input[6];
1905 activity_monitor.Gfx_PD_Data_limit_c = input[7];
1906 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1907 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1909 case 1: /* Socclk */
1910 activity_monitor.Soc_FPS = input[1];
1911 activity_monitor.Soc_UseRlcBusy = input[2];
1912 activity_monitor.Soc_MinActiveFreqType = input[3];
1913 activity_monitor.Soc_MinActiveFreq = input[4];
1914 activity_monitor.Soc_BoosterFreqType = input[5];
1915 activity_monitor.Soc_BoosterFreq = input[6];
1916 activity_monitor.Soc_PD_Data_limit_c = input[7];
1917 activity_monitor.Soc_PD_Data_error_coeff = input[8];
1918 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1921 activity_monitor.Mem_FPS = input[1];
1922 activity_monitor.Mem_UseRlcBusy = input[2];
1923 activity_monitor.Mem_MinActiveFreqType = input[3];
1924 activity_monitor.Mem_MinActiveFreq = input[4];
1925 activity_monitor.Mem_BoosterFreqType = input[5];
1926 activity_monitor.Mem_BoosterFreq = input[6];
1927 activity_monitor.Mem_PD_Data_limit_c = input[7];
1928 activity_monitor.Mem_PD_Data_error_coeff = input[8];
1929 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1932 activity_monitor.Fclk_FPS = input[1];
1933 activity_monitor.Fclk_UseRlcBusy = input[2];
1934 activity_monitor.Fclk_MinActiveFreqType = input[3];
1935 activity_monitor.Fclk_MinActiveFreq = input[4];
1936 activity_monitor.Fclk_BoosterFreqType = input[5];
1937 activity_monitor.Fclk_BoosterFreq = input[6];
1938 activity_monitor.Fclk_PD_Data_limit_c = input[7];
1939 activity_monitor.Fclk_PD_Data_error_coeff = input[8];
1940 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
1944 ret = smu_update_table(smu,
1945 TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
1946 (void *)(&activity_monitor), true);
1948 pr_err("[%s] Failed to set activity monitor!", __func__);
1953 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1954 workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1955 smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1956 1 << workload_type);
1962 vega20_get_profiling_clk_mask(struct smu_context *smu,
1963 enum amd_dpm_forced_level level,
1964 uint32_t *sclk_mask,
1965 uint32_t *mclk_mask,
1968 struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1969 struct vega20_single_dpm_table *gfx_dpm_table;
1970 struct vega20_single_dpm_table *mem_dpm_table;
1971 struct vega20_single_dpm_table *soc_dpm_table;
1973 if (!smu->smu_dpm.dpm_context)
1976 gfx_dpm_table = &dpm_table->gfx_table;
1977 mem_dpm_table = &dpm_table->mem_table;
1978 soc_dpm_table = &dpm_table->soc_table;
1984 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1985 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1986 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1987 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1988 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
1989 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
1992 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1994 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1996 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1997 *sclk_mask = gfx_dpm_table->count - 1;
1998 *mclk_mask = mem_dpm_table->count - 1;
1999 *soc_mask = soc_dpm_table->count - 1;
2006 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
2007 struct vega20_single_dpm_table *dpm_table)
2010 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2011 if (!smu_dpm_ctx->dpm_context)
2014 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2015 if (dpm_table->count <= 0) {
2016 pr_err("[%s] Dpm table has no entry!", __func__);
2020 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
2021 pr_err("[%s] Dpm table has too many entries!", __func__);
2025 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2026 ret = smu_send_smc_msg_with_param(smu,
2027 SMU_MSG_SetHardMinByFreq,
2028 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
2030 pr_err("[%s] Set hard min uclk failed!", __func__);
2038 static int vega20_pre_display_config_changed(struct smu_context *smu)
2041 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2043 if (!smu->smu_dpm.dpm_context)
2046 smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
2047 ret = vega20_set_uclk_to_highest_dpm_level(smu,
2048 &dpm_table->mem_table);
2050 pr_err("Failed to set uclk to highest dpm level");
2054 static int vega20_display_config_changed(struct smu_context *smu)
2058 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2059 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
2060 ret = smu_write_watermarks_table(smu);
2062 pr_err("Failed to update WMTABLE!");
2065 smu->watermarks_bitmap |= WATERMARKS_LOADED;
2068 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2069 smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
2070 smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
2071 smu_send_smc_msg_with_param(smu,
2072 SMU_MSG_NumOfDisplays,
2073 smu->display_config->num_display);
2079 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
2081 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2082 struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
2083 struct vega20_single_dpm_table *dpm_table;
2084 bool vblank_too_short = false;
2085 bool disable_mclk_switching;
2086 uint32_t i, latency;
2088 disable_mclk_switching = ((1 < smu->display_config->num_display) &&
2089 !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
2090 latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
2093 dpm_table = &(dpm_ctx->gfx_table);
2094 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2095 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2096 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2097 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2099 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
2100 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2101 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2104 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2105 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2106 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2109 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2110 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2111 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2115 dpm_table = &(dpm_ctx->mem_table);
2116 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2117 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2118 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2119 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2121 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
2122 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2123 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2126 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2127 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2128 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2131 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2132 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2133 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2136 /* honour DAL's UCLK Hardmin */
2137 if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
2138 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
2140 /* Hardmin is dependent on displayconfig */
2141 if (disable_mclk_switching) {
2142 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2143 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
2144 if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
2145 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
2146 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
2153 if (smu->display_config->nb_pstate_switch_disable)
2154 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2157 dpm_table = &(dpm_ctx->vclk_table);
2158 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2159 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2160 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2161 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2163 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2164 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2165 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2168 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2169 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2170 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2174 dpm_table = &(dpm_ctx->dclk_table);
2175 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2176 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2177 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2178 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2180 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2181 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2182 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2185 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2186 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2187 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2191 dpm_table = &(dpm_ctx->soc_table);
2192 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2193 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2194 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2195 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2197 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
2198 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2199 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2202 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2203 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2204 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2208 dpm_table = &(dpm_ctx->eclk_table);
2209 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2210 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2211 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2212 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2214 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
2215 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2216 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2219 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2220 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2221 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2227 vega20_notify_smc_dispaly_config(struct smu_context *smu)
2229 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2230 struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
2231 struct smu_clocks min_clocks = {0};
2232 struct pp_display_clock_request clock_req;
2235 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
2236 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
2237 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
2239 if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
2240 clock_req.clock_type = amd_pp_dcef_clock;
2241 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
2242 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
2243 if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
2244 ret = smu_send_smc_msg_with_param(smu,
2245 SMU_MSG_SetMinDeepSleepDcefclk,
2246 min_clocks.dcef_clock_in_sr/100);
2248 pr_err("Attempt to set divider for DCEFCLK Failed!");
2253 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2257 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2258 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
2259 ret = smu_send_smc_msg_with_param(smu,
2260 SMU_MSG_SetHardMinByFreq,
2261 (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
2263 pr_err("[%s] Set hard min uclk failed!", __func__);
2271 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
2275 for (i = 0; i < table->count; i++) {
2276 if (table->dpm_levels[i].enabled)
2279 if (i >= table->count) {
2281 table->dpm_levels[i].enabled = true;
2287 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
2292 pr_err("[%s] DPM Table does not exist!", __func__);
2295 if (table->count <= 0) {
2296 pr_err("[%s] DPM Table has no entry!", __func__);
2299 if (table->count > MAX_REGULAR_DPM_NUMBER) {
2300 pr_err("[%s] DPM Table has too many entries!", __func__);
2301 return MAX_REGULAR_DPM_NUMBER - 1;
2304 for (i = table->count - 1; i >= 0; i--) {
2305 if (table->dpm_levels[i].enabled)
2310 table->dpm_levels[i].enabled = true;
2316 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
2318 uint32_t soft_level;
2320 struct vega20_dpm_table *dpm_table =
2321 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2324 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2326 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2328 dpm_table->gfx_table.dpm_state.soft_min_level =
2329 dpm_table->gfx_table.dpm_state.soft_max_level =
2330 dpm_table->gfx_table.dpm_levels[soft_level].value;
2333 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2335 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2337 dpm_table->mem_table.dpm_state.soft_min_level =
2338 dpm_table->mem_table.dpm_state.soft_max_level =
2339 dpm_table->mem_table.dpm_levels[soft_level].value;
2342 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2344 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2346 dpm_table->soc_table.dpm_state.soft_min_level =
2347 dpm_table->soc_table.dpm_state.soft_max_level =
2348 dpm_table->soc_table.dpm_levels[soft_level].value;
2350 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2352 pr_err("Failed to upload boot level to %s!\n",
2353 highest ? "highest" : "lowest");
2357 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2359 pr_err("Failed to upload dpm max level to %s!\n!",
2360 highest ? "highest" : "lowest");
2367 static int vega20_unforce_dpm_levels(struct smu_context *smu)
2369 uint32_t soft_min_level, soft_max_level;
2371 struct vega20_dpm_table *dpm_table =
2372 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2374 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2375 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2376 dpm_table->gfx_table.dpm_state.soft_min_level =
2377 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2378 dpm_table->gfx_table.dpm_state.soft_max_level =
2379 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2381 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2382 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2383 dpm_table->mem_table.dpm_state.soft_min_level =
2384 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2385 dpm_table->mem_table.dpm_state.soft_max_level =
2386 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2388 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2389 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2390 dpm_table->soc_table.dpm_state.soft_min_level =
2391 dpm_table->soc_table.dpm_levels[soft_min_level].value;
2392 dpm_table->soc_table.dpm_state.soft_max_level =
2393 dpm_table->soc_table.dpm_levels[soft_max_level].value;
2395 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2397 pr_err("Failed to upload DPM Bootup Levels!");
2401 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2403 pr_err("Failed to upload DPM Max Levels!");
2410 static int vega20_update_specified_od8_value(struct smu_context *smu,
2414 struct smu_table_context *table_context = &smu->smu_table;
2415 OverDriveTable_t *od_table =
2416 (OverDriveTable_t *)(table_context->overdrive_table);
2417 struct vega20_od8_settings *od8_settings =
2418 (struct vega20_od8_settings *)table_context->od8_settings;
2421 case OD8_SETTING_GFXCLK_FMIN:
2422 od_table->GfxclkFmin = (uint16_t)value;
2425 case OD8_SETTING_GFXCLK_FMAX:
2426 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2427 value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2429 od_table->GfxclkFmax = (uint16_t)value;
2432 case OD8_SETTING_GFXCLK_FREQ1:
2433 od_table->GfxclkFreq1 = (uint16_t)value;
2436 case OD8_SETTING_GFXCLK_VOLTAGE1:
2437 od_table->GfxclkVolt1 = (uint16_t)value;
2440 case OD8_SETTING_GFXCLK_FREQ2:
2441 od_table->GfxclkFreq2 = (uint16_t)value;
2444 case OD8_SETTING_GFXCLK_VOLTAGE2:
2445 od_table->GfxclkVolt2 = (uint16_t)value;
2448 case OD8_SETTING_GFXCLK_FREQ3:
2449 od_table->GfxclkFreq3 = (uint16_t)value;
2452 case OD8_SETTING_GFXCLK_VOLTAGE3:
2453 od_table->GfxclkVolt3 = (uint16_t)value;
2456 case OD8_SETTING_UCLK_FMAX:
2457 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2458 value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2460 od_table->UclkFmax = (uint16_t)value;
2463 case OD8_SETTING_POWER_PERCENTAGE:
2464 od_table->OverDrivePct = (int16_t)value;
2467 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2468 od_table->FanMaximumRpm = (uint16_t)value;
2471 case OD8_SETTING_FAN_MIN_SPEED:
2472 od_table->FanMinimumPwm = (uint16_t)value;
2475 case OD8_SETTING_FAN_TARGET_TEMP:
2476 od_table->FanTargetTemperature = (uint16_t)value;
2479 case OD8_SETTING_OPERATING_TEMP_MAX:
2480 od_table->MaxOpTemp = (uint16_t)value;
2487 static int vega20_update_od8_settings(struct smu_context *smu,
2491 struct smu_table_context *table_context = &smu->smu_table;
2494 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
2495 table_context->overdrive_table, false);
2497 pr_err("Failed to export over drive table!\n");
2501 ret = vega20_update_specified_od8_value(smu, index, value);
2505 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE,
2506 table_context->overdrive_table, true);
2508 pr_err("Failed to import over drive table!\n");
2515 static int vega20_set_od_percentage(struct smu_context *smu,
2516 enum smu_clk_type clk_type,
2519 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2520 struct vega20_dpm_table *dpm_table = NULL;
2521 struct vega20_dpm_table *golden_table = NULL;
2522 struct vega20_single_dpm_table *single_dpm_table;
2523 struct vega20_single_dpm_table *golden_dpm_table;
2524 uint32_t od_clk, index;
2526 int feature_enabled;
2529 mutex_lock(&(smu->mutex));
2531 dpm_table = smu_dpm->dpm_context;
2532 golden_table = smu_dpm->golden_dpm_context;
2536 single_dpm_table = &(dpm_table->gfx_table);
2537 golden_dpm_table = &(golden_table->gfx_table);
2538 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT);
2539 clk_id = PPCLK_GFXCLK;
2540 index = OD8_SETTING_GFXCLK_FMAX;
2543 single_dpm_table = &(dpm_table->mem_table);
2544 golden_dpm_table = &(golden_table->mem_table);
2545 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT);
2546 clk_id = PPCLK_UCLK;
2547 index = OD8_SETTING_UCLK_FMAX;
2557 od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2559 od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2561 ret = vega20_update_od8_settings(smu, index, od_clk);
2563 pr_err("[Setoverdrive] failed to set od clk!\n");
2567 if (feature_enabled) {
2568 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2571 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2575 single_dpm_table->count = 1;
2576 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2579 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2580 AMD_PP_TASK_READJUST_POWER_STATE);
2583 mutex_unlock(&(smu->mutex));
2588 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2589 enum PP_OD_DPM_TABLE_COMMAND type,
2590 long *input, uint32_t size)
2592 struct smu_table_context *table_context = &smu->smu_table;
2593 OverDriveTable_t *od_table =
2594 (OverDriveTable_t *)(table_context->overdrive_table);
2595 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2596 struct vega20_dpm_table *dpm_table = NULL;
2597 struct vega20_single_dpm_table *single_dpm_table;
2598 struct vega20_od8_settings *od8_settings =
2599 (struct vega20_od8_settings *)table_context->od8_settings;
2600 struct pp_clock_levels_with_latency clocks;
2601 int32_t input_index, input_clk, input_vol, i;
2605 dpm_table = smu_dpm->dpm_context;
2608 pr_warn("NULL user input for clock and voltage\n");
2613 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2614 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2615 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2616 pr_info("Sclk min/max frequency overdrive not supported\n");
2620 for (i = 0; i < size; i += 2) {
2622 pr_info("invalid number of input parameters %d\n", size);
2626 input_index = input[i];
2627 input_clk = input[i + 1];
2629 if (input_index != 0 && input_index != 1) {
2630 pr_info("Invalid index %d\n", input_index);
2631 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2635 if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2636 input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2637 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2639 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2640 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2644 if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2645 od_table->GfxclkFmin = input_clk;
2646 table_context->od_gfxclk_update = true;
2647 } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2648 od_table->GfxclkFmax = input_clk;
2649 table_context->od_gfxclk_update = true;
2655 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2656 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2657 pr_info("Mclk max frequency overdrive not supported\n");
2661 single_dpm_table = &(dpm_table->mem_table);
2662 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2664 pr_err("Attempt to get memory clk levels Failed!");
2668 for (i = 0; i < size; i += 2) {
2670 pr_info("invalid number of input parameters %d\n",
2675 input_index = input[i];
2676 input_clk = input[i + 1];
2678 if (input_index != 1) {
2679 pr_info("Invalid index %d\n", input_index);
2680 pr_info("Support max Mclk frequency setting only which index by 1\n");
2684 if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2685 input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2686 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2688 clocks.data[0].clocks_in_khz / 1000,
2689 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2693 if (input_index == 1 && od_table->UclkFmax != input_clk) {
2694 table_context->od_gfxclk_update = true;
2695 od_table->UclkFmax = input_clk;
2701 case PP_OD_EDIT_VDDC_CURVE:
2702 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2703 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2704 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2705 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2706 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2707 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2708 pr_info("Voltage curve calibrate not supported\n");
2712 for (i = 0; i < size; i += 3) {
2714 pr_info("invalid number of input parameters %d\n",
2719 input_index = input[i];
2720 input_clk = input[i + 1];
2721 input_vol = input[i + 2];
2723 if (input_index > 2) {
2724 pr_info("Setting for point %d is not supported\n",
2726 pr_info("Three supported points index by 0, 1, 2\n");
2730 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2731 if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2732 input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2733 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2735 od8_settings->od8_settings_array[od8_id].min_value,
2736 od8_settings->od8_settings_array[od8_id].max_value);
2740 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2741 if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2742 input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2743 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2745 od8_settings->od8_settings_array[od8_id].min_value,
2746 od8_settings->od8_settings_array[od8_id].max_value);
2750 switch (input_index) {
2752 od_table->GfxclkFreq1 = input_clk;
2753 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2756 od_table->GfxclkFreq2 = input_clk;
2757 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2760 od_table->GfxclkFreq3 = input_clk;
2761 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2768 case PP_OD_RESTORE_DEFAULT_TABLE:
2769 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
2771 pr_err("Failed to export over drive table!\n");
2777 case PP_OD_COMMIT_DPM_TABLE:
2778 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
2780 pr_err("Failed to import over drive table!\n");
2784 /* retrieve updated gfxclk table */
2785 if (table_context->od_gfxclk_update) {
2786 table_context->od_gfxclk_update = false;
2787 single_dpm_table = &(dpm_table->gfx_table);
2789 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
2790 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2793 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2797 single_dpm_table->count = 1;
2798 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2808 if (type == PP_OD_COMMIT_DPM_TABLE) {
2809 mutex_lock(&(smu->mutex));
2810 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2811 AMD_PP_TASK_READJUST_POWER_STATE);
2812 mutex_unlock(&(smu->mutex));
2818 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
2820 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
2823 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
2826 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
2829 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
2831 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
2834 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
2837 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
2840 static int vega20_get_enabled_smc_features(struct smu_context *smu,
2841 uint64_t *features_enabled)
2843 uint32_t feature_mask[2] = {0, 0};
2846 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2850 *features_enabled = ((((uint64_t)feature_mask[0] << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
2851 (((uint64_t)feature_mask[1] << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
2856 static int vega20_enable_smc_features(struct smu_context *smu,
2857 bool enable, uint64_t feature_mask)
2859 uint32_t smu_features_low, smu_features_high;
2862 smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
2863 smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
2866 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
2870 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
2875 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
2879 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
2889 static int vega20_get_ppfeature_status(struct smu_context *smu, char *buf)
2891 static const char *ppfeature_name[] = {
2926 static const char *output_title[] = {
2930 uint64_t features_enabled;
2935 ret = vega20_get_enabled_smc_features(smu, &features_enabled);
2939 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
2940 size += sprintf(buf + size, "%-19s %-22s %s\n",
2944 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
2945 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
2948 (features_enabled & (1ULL << i)) ? "Y" : "N");
2954 static int vega20_set_ppfeature_status(struct smu_context *smu, uint64_t new_ppfeature_masks)
2956 uint64_t features_enabled;
2957 uint64_t features_to_enable;
2958 uint64_t features_to_disable;
2961 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
2964 ret = vega20_get_enabled_smc_features(smu, &features_enabled);
2968 features_to_disable =
2969 features_enabled & ~new_ppfeature_masks;
2970 features_to_enable =
2971 ~features_enabled & new_ppfeature_masks;
2973 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
2974 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
2976 if (features_to_disable) {
2977 ret = vega20_enable_smc_features(smu, false, features_to_disable);
2982 if (features_to_enable) {
2983 ret = vega20_enable_smc_features(smu, true, features_to_enable);
2991 static bool vega20_is_dpm_running(struct smu_context *smu)
2994 uint32_t feature_mask[2];
2995 unsigned long feature_enabled;
2996 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2997 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
2998 ((uint64_t)feature_mask[1] << 32));
2999 return !!(feature_enabled & SMC_DPM_FEATURE);
3002 static int vega20_set_thermal_fan_table(struct smu_context *smu)
3005 struct smu_table_context *table_context = &smu->smu_table;
3006 PPTable_t *pptable = table_context->driver_pptable;
3008 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
3009 (uint32_t)pptable->FanTargetTemperature);
3014 static int vega20_get_fan_speed_percent(struct smu_context *smu,
3018 uint32_t percent = 0;
3019 uint32_t current_rpm;
3020 PPTable_t *pptable = smu->smu_table.driver_pptable;
3022 ret = smu_get_current_rpm(smu, ¤t_rpm);
3023 percent = current_rpm * 100 / pptable->FanMaximumRpm;
3024 *speed = percent > 100 ? 100 : percent;
3029 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
3032 SmuMetrics_t metrics;
3037 ret = vega20_get_metrics_table(smu, &metrics);
3041 *value = metrics.CurrSocketPower << 8;
3046 static int vega20_get_current_activity_percent(struct smu_context *smu,
3047 enum amd_pp_sensors sensor,
3051 SmuMetrics_t metrics;
3056 ret = vega20_get_metrics_table(smu, &metrics);
3061 case AMDGPU_PP_SENSOR_GPU_LOAD:
3062 *value = metrics.AverageGfxActivity;
3064 case AMDGPU_PP_SENSOR_MEM_LOAD:
3065 *value = metrics.AverageUclkActivity;
3068 pr_err("Invalid sensor for retrieving clock activity\n");
3075 static int vega20_thermal_get_temperature(struct smu_context *smu,
3076 enum amd_pp_sensors sensor,
3079 struct amdgpu_device *adev = smu->adev;
3080 SmuMetrics_t metrics;
3087 ret = vega20_get_metrics_table(smu, &metrics);
3092 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3093 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
3094 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
3095 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
3097 temp = temp & 0x1ff;
3098 temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3102 case AMDGPU_PP_SENSOR_EDGE_TEMP:
3103 *value = metrics.TemperatureEdge *
3104 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3106 case AMDGPU_PP_SENSOR_MEM_TEMP:
3107 *value = metrics.TemperatureHBM *
3108 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3111 pr_err("Invalid sensor for retrieving temp\n");
3117 static int vega20_read_sensor(struct smu_context *smu,
3118 enum amd_pp_sensors sensor,
3119 void *data, uint32_t *size)
3122 struct smu_table_context *table_context = &smu->smu_table;
3123 PPTable_t *pptable = table_context->driver_pptable;
3126 case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
3127 *(uint32_t *)data = pptable->FanMaximumRpm;
3130 case AMDGPU_PP_SENSOR_MEM_LOAD:
3131 case AMDGPU_PP_SENSOR_GPU_LOAD:
3132 ret = vega20_get_current_activity_percent(smu,
3137 case AMDGPU_PP_SENSOR_GPU_POWER:
3138 ret = vega20_get_gpu_power(smu, (uint32_t *)data);
3141 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3142 case AMDGPU_PP_SENSOR_EDGE_TEMP:
3143 case AMDGPU_PP_SENSOR_MEM_TEMP:
3144 ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
3154 static int vega20_set_watermarks_table(struct smu_context *smu,
3155 void *watermarks, struct
3156 dm_pp_wm_sets_with_clock_ranges_soc15
3160 Watermarks_t *table = watermarks;
3162 if (!table || !clock_ranges)
3165 if (clock_ranges->num_wm_dmif_sets > 4 ||
3166 clock_ranges->num_wm_mcif_sets > 4)
3169 for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
3170 table->WatermarkRow[1][i].MinClock =
3171 cpu_to_le16((uint16_t)
3172 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
3174 table->WatermarkRow[1][i].MaxClock =
3175 cpu_to_le16((uint16_t)
3176 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
3178 table->WatermarkRow[1][i].MinUclk =
3179 cpu_to_le16((uint16_t)
3180 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3182 table->WatermarkRow[1][i].MaxUclk =
3183 cpu_to_le16((uint16_t)
3184 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3186 table->WatermarkRow[1][i].WmSetting = (uint8_t)
3187 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
3190 for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
3191 table->WatermarkRow[0][i].MinClock =
3192 cpu_to_le16((uint16_t)
3193 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
3195 table->WatermarkRow[0][i].MaxClock =
3196 cpu_to_le16((uint16_t)
3197 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
3199 table->WatermarkRow[0][i].MinUclk =
3200 cpu_to_le16((uint16_t)
3201 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3203 table->WatermarkRow[0][i].MaxUclk =
3204 cpu_to_le16((uint16_t)
3205 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3207 table->WatermarkRow[0][i].WmSetting = (uint8_t)
3208 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
3214 static const struct smu_temperature_range vega20_thermal_policy[] =
3216 {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
3217 { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
3220 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
3221 struct smu_temperature_range *range)
3224 PPTable_t *pptable = smu->smu_table.driver_pptable;
3229 memcpy(range, &vega20_thermal_policy[0], sizeof(struct smu_temperature_range));
3231 range->max = pptable->TedgeLimit *
3232 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3233 range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
3234 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3235 range->hotspot_crit_max = pptable->ThotspotLimit *
3236 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3237 range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
3238 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3239 range->mem_crit_max = pptable->ThbmLimit *
3240 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3241 range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM)*
3242 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3248 static const struct pptable_funcs vega20_ppt_funcs = {
3249 .tables_init = vega20_tables_init,
3250 .alloc_dpm_context = vega20_allocate_dpm_context,
3251 .store_powerplay_table = vega20_store_powerplay_table,
3252 .check_powerplay_table = vega20_check_powerplay_table,
3253 .append_powerplay_table = vega20_append_powerplay_table,
3254 .get_smu_msg_index = vega20_get_smu_msg_index,
3255 .get_smu_clk_index = vega20_get_smu_clk_index,
3256 .get_smu_feature_index = vega20_get_smu_feature_index,
3257 .get_smu_table_index = vega20_get_smu_table_index,
3258 .get_smu_power_index = vega20_get_pwr_src_index,
3259 .get_workload_type = vega20_get_workload_type,
3260 .run_afll_btc = vega20_run_btc_afll,
3261 .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
3262 .get_current_power_state = vega20_get_current_power_state,
3263 .set_default_dpm_table = vega20_set_default_dpm_table,
3264 .set_power_state = NULL,
3265 .populate_umd_state_clk = vega20_populate_umd_state_clk,
3266 .print_clk_levels = vega20_print_clk_levels,
3267 .force_clk_levels = vega20_force_clk_levels,
3268 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
3269 .get_od_percentage = vega20_get_od_percentage,
3270 .get_power_profile_mode = vega20_get_power_profile_mode,
3271 .set_power_profile_mode = vega20_set_power_profile_mode,
3272 .set_od_percentage = vega20_set_od_percentage,
3273 .set_default_od_settings = vega20_set_default_od_settings,
3274 .od_edit_dpm_table = vega20_odn_edit_dpm_table,
3275 .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable,
3276 .dpm_set_vce_enable = vega20_dpm_set_vce_enable,
3277 .read_sensor = vega20_read_sensor,
3278 .pre_display_config_changed = vega20_pre_display_config_changed,
3279 .display_config_changed = vega20_display_config_changed,
3280 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
3281 .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
3282 .force_dpm_limit_value = vega20_force_dpm_limit_value,
3283 .unforce_dpm_levels = vega20_unforce_dpm_levels,
3284 .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
3285 .set_ppfeature_status = vega20_set_ppfeature_status,
3286 .get_ppfeature_status = vega20_get_ppfeature_status,
3287 .is_dpm_running = vega20_is_dpm_running,
3288 .set_thermal_fan_table = vega20_set_thermal_fan_table,
3289 .get_fan_speed_percent = vega20_get_fan_speed_percent,
3290 .set_watermarks_table = vega20_set_watermarks_table,
3291 .get_thermal_temperature_range = vega20_get_thermal_temperature_range
3294 void vega20_set_ppt_funcs(struct smu_context *smu)
3296 struct smu_table_context *smu_table = &smu->smu_table;
3298 smu->ppt_funcs = &vega20_ppt_funcs;
3299 smu->smc_if_version = SMU11_DRIVER_IF_VERSION;
3300 smu_table->table_count = TABLE_COUNT;