drm/amd/powerplay: add function to set default overdrive settings
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / vega20_ppt.c
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
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.
21  *
22  */
23
24 #include "pp_debug.h"
25 #include <linux/firmware.h>
26 #include "amdgpu.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"
33 #include "atom.h"
34 #include "vega20_ppt.h"
35 #include "vega20_pptable.h"
36 #include "vega20_ppsmc.h"
37
38 #define MSG_MAP(msg, index) \
39         [SMU_MSG_##msg] = index
40
41 static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
42         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
43         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
44         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
45         MSG_MAP(SetAllowedFeaturesMaskLow,      PPSMC_MSG_SetAllowedFeaturesMaskLow),
46         MSG_MAP(SetAllowedFeaturesMaskHigh,     PPSMC_MSG_SetAllowedFeaturesMaskHigh),
47         MSG_MAP(EnableAllSmuFeatures,           PPSMC_MSG_EnableAllSmuFeatures),
48         MSG_MAP(DisableAllSmuFeatures,          PPSMC_MSG_DisableAllSmuFeatures),
49         MSG_MAP(EnableSmuFeaturesLow,           PPSMC_MSG_EnableSmuFeaturesLow),
50         MSG_MAP(EnableSmuFeaturesHigh,          PPSMC_MSG_EnableSmuFeaturesHigh),
51         MSG_MAP(DisableSmuFeaturesLow,          PPSMC_MSG_DisableSmuFeaturesLow),
52         MSG_MAP(DisableSmuFeaturesHigh,         PPSMC_MSG_DisableSmuFeaturesHigh),
53         MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetEnabledSmuFeaturesLow),
54         MSG_MAP(GetEnabledSmuFeaturesHigh,      PPSMC_MSG_GetEnabledSmuFeaturesHigh),
55         MSG_MAP(SetWorkloadMask,                PPSMC_MSG_SetWorkloadMask),
56         MSG_MAP(SetPptLimit,                    PPSMC_MSG_SetPptLimit),
57         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
58         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
59         MSG_MAP(SetToolsDramAddrHigh,           PPSMC_MSG_SetToolsDramAddrHigh),
60         MSG_MAP(SetToolsDramAddrLow,            PPSMC_MSG_SetToolsDramAddrLow),
61         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
62         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
63         MSG_MAP(UseDefaultPPTable,              PPSMC_MSG_UseDefaultPPTable),
64         MSG_MAP(UseBackupPPTable,               PPSMC_MSG_UseBackupPPTable),
65         MSG_MAP(RunBtc,                         PPSMC_MSG_RunBtc),
66         MSG_MAP(RequestI2CBus,                  PPSMC_MSG_RequestI2CBus),
67         MSG_MAP(ReleaseI2CBus,                  PPSMC_MSG_ReleaseI2CBus),
68         MSG_MAP(SetFloorSocVoltage,             PPSMC_MSG_SetFloorSocVoltage),
69         MSG_MAP(SoftReset,                      PPSMC_MSG_SoftReset),
70         MSG_MAP(StartBacoMonitor,               PPSMC_MSG_StartBacoMonitor),
71         MSG_MAP(CancelBacoMonitor,              PPSMC_MSG_CancelBacoMonitor),
72         MSG_MAP(EnterBaco,                      PPSMC_MSG_EnterBaco),
73         MSG_MAP(SetSoftMinByFreq,               PPSMC_MSG_SetSoftMinByFreq),
74         MSG_MAP(SetSoftMaxByFreq,               PPSMC_MSG_SetSoftMaxByFreq),
75         MSG_MAP(SetHardMinByFreq,               PPSMC_MSG_SetHardMinByFreq),
76         MSG_MAP(SetHardMaxByFreq,               PPSMC_MSG_SetHardMaxByFreq),
77         MSG_MAP(GetMinDpmFreq,                  PPSMC_MSG_GetMinDpmFreq),
78         MSG_MAP(GetMaxDpmFreq,                  PPSMC_MSG_GetMaxDpmFreq),
79         MSG_MAP(GetDpmFreqByIndex,              PPSMC_MSG_GetDpmFreqByIndex),
80         MSG_MAP(GetDpmClockFreq,                PPSMC_MSG_GetDpmClockFreq),
81         MSG_MAP(GetSsVoltageByDpm,              PPSMC_MSG_GetSsVoltageByDpm),
82         MSG_MAP(SetMemoryChannelConfig,         PPSMC_MSG_SetMemoryChannelConfig),
83         MSG_MAP(SetGeminiMode,                  PPSMC_MSG_SetGeminiMode),
84         MSG_MAP(SetGeminiApertureHigh,          PPSMC_MSG_SetGeminiApertureHigh),
85         MSG_MAP(SetGeminiApertureLow,           PPSMC_MSG_SetGeminiApertureLow),
86         MSG_MAP(SetMinLinkDpmByIndex,           PPSMC_MSG_SetMinLinkDpmByIndex),
87         MSG_MAP(OverridePcieParameters,         PPSMC_MSG_OverridePcieParameters),
88         MSG_MAP(OverDriveSetPercentage,         PPSMC_MSG_OverDriveSetPercentage),
89         MSG_MAP(SetMinDeepSleepDcefclk,         PPSMC_MSG_SetMinDeepSleepDcefclk),
90         MSG_MAP(ReenableAcDcInterrupt,          PPSMC_MSG_ReenableAcDcInterrupt),
91         MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource),
92         MSG_MAP(SetUclkFastSwitch,              PPSMC_MSG_SetUclkFastSwitch),
93         MSG_MAP(SetUclkDownHyst,                PPSMC_MSG_SetUclkDownHyst),
94         MSG_MAP(GetCurrentRpm,                  PPSMC_MSG_GetCurrentRpm),
95         MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
96         MSG_MAP(SetTjMax,                       PPSMC_MSG_SetTjMax),
97         MSG_MAP(SetFanTemperatureTarget,        PPSMC_MSG_SetFanTemperatureTarget),
98         MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload),
99         MSG_MAP(DramLogSetDramAddrHigh,         PPSMC_MSG_DramLogSetDramAddrHigh),
100         MSG_MAP(DramLogSetDramAddrLow,          PPSMC_MSG_DramLogSetDramAddrLow),
101         MSG_MAP(DramLogSetDramSize,             PPSMC_MSG_DramLogSetDramSize),
102         MSG_MAP(SetFanMaxRpm,                   PPSMC_MSG_SetFanMaxRpm),
103         MSG_MAP(SetFanMinPwm,                   PPSMC_MSG_SetFanMinPwm),
104         MSG_MAP(ConfigureGfxDidt,               PPSMC_MSG_ConfigureGfxDidt),
105         MSG_MAP(NumOfDisplays,                  PPSMC_MSG_NumOfDisplays),
106         MSG_MAP(RemoveMargins,                  PPSMC_MSG_RemoveMargins),
107         MSG_MAP(ReadSerialNumTop32,             PPSMC_MSG_ReadSerialNumTop32),
108         MSG_MAP(ReadSerialNumBottom32,          PPSMC_MSG_ReadSerialNumBottom32),
109         MSG_MAP(SetSystemVirtualDramAddrHigh,   PPSMC_MSG_SetSystemVirtualDramAddrHigh),
110         MSG_MAP(SetSystemVirtualDramAddrLow,    PPSMC_MSG_SetSystemVirtualDramAddrLow),
111         MSG_MAP(WaflTest,                       PPSMC_MSG_WaflTest),
112         MSG_MAP(SetFclkGfxClkRatio,             PPSMC_MSG_SetFclkGfxClkRatio),
113         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff),
114         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff),
115         MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit),
116         MSG_MAP(GetDcModeMaxDpmFreq,            PPSMC_MSG_GetDcModeMaxDpmFreq),
117         MSG_MAP(GetDebugData,                   PPSMC_MSG_GetDebugData),
118         MSG_MAP(SetXgmiMode,                    PPSMC_MSG_SetXgmiMode),
119         MSG_MAP(RunAfllBtc,                     PPSMC_MSG_RunAfllBtc),
120         MSG_MAP(ExitBaco,                       PPSMC_MSG_ExitBaco),
121         MSG_MAP(PrepareMp1ForReset,             PPSMC_MSG_PrepareMp1ForReset),
122         MSG_MAP(PrepareMp1ForShutdown,          PPSMC_MSG_PrepareMp1ForShutdown),
123         MSG_MAP(SetMGpuFanBoostLimitRpm,        PPSMC_MSG_SetMGpuFanBoostLimitRpm),
124         MSG_MAP(GetAVFSVoltageByDpm,            PPSMC_MSG_GetAVFSVoltageByDpm),
125 };
126
127 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
128 {
129         if (index > SMU_MSG_MAX_COUNT || index > PPSMC_Message_Count)
130                 return -EINVAL;
131         return vega20_message_map[index];
132
133 }
134
135 static int vega20_allocate_dpm_context(struct smu_context *smu)
136 {
137         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
138
139         smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
140                                        GFP_KERNEL);
141         if (!smu_dpm->dpm_context)
142                 return -ENOMEM;
143
144         smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
145
146         return 0;
147 }
148
149 static int vega20_setup_od8_information(struct smu_context *smu)
150 {
151         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
152         struct smu_table_context *table_context = &smu->smu_table;
153
154         uint32_t od_feature_count, od_feature_array_size,
155                  od_setting_count, od_setting_array_size;
156
157         if (!table_context->power_play_table)
158                 return -EINVAL;
159
160         powerplay_table = table_context->power_play_table;
161
162         if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
163                 /* Setup correct ODFeatureCount, and store ODFeatureArray from
164                  * powerplay table to od_feature_capabilities */
165                 od_feature_count =
166                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
167                          ATOM_VEGA20_ODFEATURE_COUNT) ?
168                         ATOM_VEGA20_ODFEATURE_COUNT :
169                         le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
170
171                 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
172
173                 if (table_context->od_feature_capabilities)
174                         return -EINVAL;
175
176                 table_context->od_feature_capabilities = kzalloc(od_feature_array_size, GFP_KERNEL);
177                 if (!table_context->od_feature_capabilities)
178                         return -ENOMEM;
179
180                 memcpy(table_context->od_feature_capabilities,
181                        &powerplay_table->OverDrive8Table.ODFeatureCapabilities,
182                        od_feature_array_size);
183
184                 /* Setup correct ODSettingCount, and store ODSettingArray from
185                  * powerplay table to od_settings_max and od_setting_min */
186                 od_setting_count =
187                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
188                          ATOM_VEGA20_ODSETTING_COUNT) ?
189                         ATOM_VEGA20_ODSETTING_COUNT :
190                         le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
191
192                 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
193
194                 if (table_context->od_settings_max)
195                         return -EINVAL;
196
197                 table_context->od_settings_max = kzalloc(od_setting_array_size, GFP_KERNEL);
198
199                 if (!table_context->od_settings_max) {
200                         kfree(table_context->od_feature_capabilities);
201                         table_context->od_feature_capabilities = NULL;
202                         return -ENOMEM;
203                 }
204
205                 memcpy(table_context->od_settings_max,
206                        &powerplay_table->OverDrive8Table.ODSettingsMax,
207                        od_setting_array_size);
208
209                 if (table_context->od_settings_min)
210                         return -EINVAL;
211
212                 table_context->od_settings_min = kzalloc(od_setting_array_size, GFP_KERNEL);
213
214                 if (!table_context->od_settings_min) {
215                         kfree(table_context->od_feature_capabilities);
216                         table_context->od_feature_capabilities = NULL;
217                         kfree(table_context->od_settings_max);
218                         table_context->od_settings_max = NULL;
219                         return -ENOMEM;
220                 }
221
222                 memcpy(table_context->od_settings_min,
223                        &powerplay_table->OverDrive8Table.ODSettingsMin,
224                        od_setting_array_size);
225         }
226
227         return 0;
228 }
229
230 static int vega20_store_powerplay_table(struct smu_context *smu)
231 {
232         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
233         struct smu_table_context *table_context = &smu->smu_table;
234         int ret;
235
236         if (!table_context->power_play_table)
237                 return -EINVAL;
238
239         powerplay_table = table_context->power_play_table;
240
241         memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
242                sizeof(PPTable_t));
243
244         table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
245         table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
246
247         ret = vega20_setup_od8_information(smu);
248
249         return ret;
250 }
251
252 static int vega20_append_powerplay_table(struct smu_context *smu)
253 {
254         struct smu_table_context *table_context = &smu->smu_table;
255         PPTable_t *smc_pptable = table_context->driver_pptable;
256         struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
257         int index, i, ret;
258
259         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
260                                            smc_dpm_info);
261
262         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
263                                       (uint8_t **)&smc_dpm_table);
264         if (ret)
265                 return ret;
266
267         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
268         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
269
270         smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
271         smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
272         smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
273         smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
274
275         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
276         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
277         smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
278
279         smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
280         smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
281         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
282
283         smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
284         smc_pptable->SocOffset = smc_dpm_table->socoffset;
285         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
286
287         smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
288         smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
289         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
290
291         smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
292         smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
293         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
294
295         smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
296         smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
297         smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
298         smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
299
300         smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
301         smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
302         smc_pptable->Padding1 = smc_dpm_table->padding1;
303         smc_pptable->Padding2 = smc_dpm_table->padding2;
304
305         smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
306         smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
307         smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
308
309         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
310         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
311         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
312
313         smc_pptable->UclkSpreadEnabled = 0;
314         smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
315         smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
316
317         smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
318         smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
319         smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
320
321         smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
322         smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
323         smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
324
325         for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
326                 smc_pptable->I2cControllers[i].Enabled =
327                         smc_dpm_table->i2ccontrollers[i].enabled;
328                 smc_pptable->I2cControllers[i].SlaveAddress =
329                         smc_dpm_table->i2ccontrollers[i].slaveaddress;
330                 smc_pptable->I2cControllers[i].ControllerPort =
331                         smc_dpm_table->i2ccontrollers[i].controllerport;
332                 smc_pptable->I2cControllers[i].ThermalThrottler =
333                         smc_dpm_table->i2ccontrollers[i].thermalthrottler;
334                 smc_pptable->I2cControllers[i].I2cProtocol =
335                         smc_dpm_table->i2ccontrollers[i].i2cprotocol;
336                 smc_pptable->I2cControllers[i].I2cSpeed =
337                         smc_dpm_table->i2ccontrollers[i].i2cspeed;
338         }
339
340         return 0;
341 }
342
343 static int vega20_check_powerplay_table(struct smu_context *smu)
344 {
345         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
346         struct smu_table_context *table_context = &smu->smu_table;
347
348         powerplay_table = table_context->power_play_table;
349
350         if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
351                 pr_err("Unsupported PPTable format!");
352                 return -EINVAL;
353         }
354
355         if (!powerplay_table->sHeader.structuresize) {
356                 pr_err("Invalid PowerPlay Table!");
357                 return -EINVAL;
358         }
359
360         return 0;
361 }
362
363 static int vega20_run_btc_afll(struct smu_context *smu)
364 {
365         return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
366 }
367
368 static int
369 vega20_get_unallowed_feature_mask(struct smu_context *smu,
370                                   uint32_t *feature_mask, uint32_t num)
371 {
372         if (num > 2)
373                 return -EINVAL;
374
375         feature_mask[0] = 0xE0041C00;
376         feature_mask[1] = 0xFFFFFFFE; /* bit32~bit63 is Unsupported */
377
378         return 0;
379 }
380
381 static int
382 vega20_set_single_dpm_table(struct smu_context *smu,
383                             struct vega20_single_dpm_table *single_dpm_table,
384                             PPCLK_e clk_id)
385 {
386         int ret = 0;
387         uint32_t i, num_of_levels, clk;
388
389         ret = smu_send_smc_msg_with_param(smu,
390                         SMU_MSG_GetDpmFreqByIndex,
391                         (clk_id << 16 | 0xFF));
392         if (ret) {
393                 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
394                 return ret;
395         }
396
397         smu_read_smc_arg(smu, &num_of_levels);
398         if (!num_of_levels) {
399                 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
400                 return -EINVAL;
401         }
402
403         single_dpm_table->count = num_of_levels;
404
405         for (i = 0; i < num_of_levels; i++) {
406                 ret = smu_send_smc_msg_with_param(smu,
407                                 SMU_MSG_GetDpmFreqByIndex,
408                                 (clk_id << 16 | i));
409                 if (ret) {
410                         pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
411                         return ret;
412                 }
413                 smu_read_smc_arg(smu, &clk);
414                 if (!clk) {
415                         pr_err("[GetDpmFreqByIndex] clk value is invalid!");
416                         return -EINVAL;
417                 }
418                 single_dpm_table->dpm_levels[i].value = clk;
419                 single_dpm_table->dpm_levels[i].enabled = true;
420         }
421         return 0;
422 }
423
424 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
425 {
426         dpm_state->soft_min_level = 0x0;
427         dpm_state->soft_max_level = 0xffff;
428         dpm_state->hard_min_level = 0x0;
429         dpm_state->hard_max_level = 0xffff;
430 }
431
432 static int vega20_set_default_dpm_table(struct smu_context *smu)
433 {
434         int ret;
435
436         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
437         struct vega20_dpm_table *dpm_table = NULL;
438         struct vega20_single_dpm_table *single_dpm_table;
439
440         dpm_table = smu_dpm->dpm_context;
441
442         /* socclk */
443         single_dpm_table = &(dpm_table->soc_table);
444
445         if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
446                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
447                                                   PPCLK_SOCCLK);
448                 if (ret) {
449                         pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
450                         return ret;
451                 }
452         } else {
453                 single_dpm_table->count = 1;
454                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
455         }
456         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
457
458         /* gfxclk */
459         single_dpm_table = &(dpm_table->gfx_table);
460
461         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
462                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
463                                                   PPCLK_GFXCLK);
464                 if (ret) {
465                         pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
466                         return ret;
467                 }
468         } else {
469                 single_dpm_table->count = 1;
470                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
471         }
472         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
473
474         /* memclk */
475         single_dpm_table = &(dpm_table->mem_table);
476
477         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
478                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
479                                                   PPCLK_UCLK);
480                 if (ret) {
481                         pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
482                         return ret;
483                 }
484         } else {
485                 single_dpm_table->count = 1;
486                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
487         }
488         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
489
490 #if 0
491         /* eclk */
492         single_dpm_table = &(dpm_table->eclk_table);
493
494         if (feature->fea_enabled[FEATURE_DPM_VCE_BIT]) {
495                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
496                 if (ret) {
497                         pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
498                         return ret;
499                 }
500         } else {
501                 single_dpm_table->count = 1;
502                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclock / 100;
503         }
504         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
505
506         /* vclk */
507         single_dpm_table = &(dpm_table->vclk_table);
508
509         if (feature->fea_enabled[FEATURE_DPM_UVD_BIT]) {
510                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
511                 if (ret) {
512                         pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
513                         return ret;
514                 }
515         } else {
516                 single_dpm_table->count = 1;
517                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclock / 100;
518         }
519         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
520
521         /* dclk */
522         single_dpm_table = &(dpm_table->dclk_table);
523
524         if (feature->fea_enabled[FEATURE_DPM_UVD_BIT]) {
525                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
526                 if (ret) {
527                         pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
528                         return ret;
529                 }
530         } else {
531                 single_dpm_table->count = 1;
532                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclock / 100;
533         }
534         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
535 #endif
536
537         /* dcefclk */
538         single_dpm_table = &(dpm_table->dcef_table);
539
540         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
541                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
542                                                   PPCLK_DCEFCLK);
543                 if (ret) {
544                         pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
545                         return ret;
546                 }
547         } else {
548                 single_dpm_table->count = 1;
549                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
550         }
551         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
552
553         /* pixclk */
554         single_dpm_table = &(dpm_table->pixel_table);
555
556         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
557                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
558                                                   PPCLK_PIXCLK);
559                 if (ret) {
560                         pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
561                         return ret;
562                 }
563         } else {
564                 single_dpm_table->count = 0;
565         }
566         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
567
568         /* dispclk */
569         single_dpm_table = &(dpm_table->display_table);
570
571         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
572                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
573                                                   PPCLK_DISPCLK);
574                 if (ret) {
575                         pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
576                         return ret;
577                 }
578         } else {
579                 single_dpm_table->count = 0;
580         }
581         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
582
583         /* phyclk */
584         single_dpm_table = &(dpm_table->phy_table);
585
586         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
587                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
588                                                   PPCLK_PHYCLK);
589                 if (ret) {
590                         pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
591                         return ret;
592                 }
593         } else {
594                 single_dpm_table->count = 0;
595         }
596         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
597
598         /* fclk */
599         single_dpm_table = &(dpm_table->fclk_table);
600
601         if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
602                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
603                                                   PPCLK_FCLK);
604                 if (ret) {
605                         pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
606                         return ret;
607                 }
608         } else {
609                 single_dpm_table->count = 0;
610         }
611         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
612
613         return 0;
614 }
615
616 static int vega20_populate_umd_state_clk(struct smu_context *smu)
617 {
618         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
619         struct vega20_dpm_table *dpm_table = NULL;
620         struct vega20_single_dpm_table *gfx_table = NULL;
621         struct vega20_single_dpm_table *mem_table = NULL;
622
623         dpm_table = smu_dpm->dpm_context;
624         gfx_table = &(dpm_table->gfx_table);
625         mem_table = &(dpm_table->mem_table);
626
627         smu->pstate_sclk = gfx_table->dpm_levels[0].value;
628         smu->pstate_mclk = mem_table->dpm_levels[0].value;
629
630         if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
631             mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
632                 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
633                 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
634         }
635
636         smu->pstate_sclk = smu->pstate_sclk * 100;
637         smu->pstate_mclk = smu->pstate_mclk * 100;
638
639         return 0;
640 }
641
642 static int vega20_get_clk_table(struct smu_context *smu,
643                         struct pp_clock_levels_with_latency *clocks,
644                         struct vega20_single_dpm_table *dpm_table)
645 {
646         int i, count;
647
648         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
649         clocks->num_levels = count;
650
651         for (i = 0; i < count; i++) {
652                 clocks->data[i].clocks_in_khz =
653                         dpm_table->dpm_levels[i].value * 1000;
654                 clocks->data[i].latency_in_us = 0;
655         }
656
657         return 0;
658 }
659
660 static int vega20_print_clk_levels(struct smu_context *smu,
661                         enum pp_clock_type type, char *buf)
662 {
663         int i, now, size = 0;
664         int ret = 0;
665         struct pp_clock_levels_with_latency clocks;
666         struct vega20_single_dpm_table *single_dpm_table;
667         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
668         struct vega20_dpm_table *dpm_table = NULL;
669
670         dpm_table = smu_dpm->dpm_context;
671
672         switch (type) {
673         case PP_SCLK:
674                 ret = smu_get_current_clk_freq(smu, PPCLK_GFXCLK, &now);
675                 if (ret) {
676                         pr_err("Attempt to get current gfx clk Failed!");
677                         return ret;
678                 }
679
680                 single_dpm_table = &(dpm_table->gfx_table);
681                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
682                 if (ret) {
683                         pr_err("Attempt to get gfx clk levels Failed!");
684                         return ret;
685                 }
686
687                 for (i = 0; i < clocks.num_levels; i++)
688                         size += sprintf(buf + size, "%d: %uMhz %s\n", i,
689                                         clocks.data[i].clocks_in_khz / 1000,
690                                         (clocks.data[i].clocks_in_khz == now * 10)
691                                         ? "*" : "");
692                 break;
693
694         case PP_MCLK:
695                 ret = smu_get_current_clk_freq(smu, PPCLK_UCLK, &now);
696                 if (ret) {
697                         pr_err("Attempt to get current mclk Failed!");
698                         return ret;
699                 }
700
701                 single_dpm_table = &(dpm_table->mem_table);
702                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
703                 if (ret) {
704                         pr_err("Attempt to get memory clk levels Failed!");
705                         return ret;
706                 }
707
708                 for (i = 0; i < clocks.num_levels; i++)
709                         size += sprintf(buf + size, "%d: %uMhz %s\n",
710                                 i, clocks.data[i].clocks_in_khz / 1000,
711                                 (clocks.data[i].clocks_in_khz == now * 10)
712                                 ? "*" : "");
713                 break;
714         default:
715                 break;
716         }
717         return size;
718 }
719
720 static int vega20_upload_dpm_min_level(struct smu_context *smu)
721 {
722         struct vega20_dpm_table *dpm_table;
723         struct vega20_single_dpm_table *single_dpm_table;
724         uint32_t min_freq;
725         int ret = 0;
726
727         dpm_table = smu->smu_dpm.dpm_context;
728
729         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
730                 single_dpm_table = &(dpm_table->gfx_table);
731                 min_freq = single_dpm_table->dpm_state.soft_min_level;
732                 ret = smu_send_smc_msg_with_param(smu,
733                         SMU_MSG_SetSoftMinByFreq,
734                         (PPCLK_GFXCLK << 16) | (min_freq & 0xffff));
735                 if (ret) {
736                         pr_err("Failed to set soft min gfxclk !\n");
737                         return ret;
738                 }
739         }
740
741         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
742                 single_dpm_table = &(dpm_table->mem_table);
743                 min_freq = single_dpm_table->dpm_state.soft_min_level;
744                 ret = smu_send_smc_msg_with_param(smu,
745                         SMU_MSG_SetSoftMinByFreq,
746                         (PPCLK_UCLK << 16) | (min_freq & 0xffff));
747                 if (ret) {
748                         pr_err("Failed to set soft min memclk !\n");
749                         return ret;
750                 }
751         }
752
753         return ret;
754 }
755
756 static int vega20_upload_dpm_max_level(struct smu_context *smu)
757 {
758         struct vega20_dpm_table *dpm_table;
759         struct vega20_single_dpm_table *single_dpm_table;
760         uint32_t max_freq;
761         int ret = 0;
762
763         dpm_table = smu->smu_dpm.dpm_context;
764
765         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
766                 single_dpm_table = &(dpm_table->gfx_table);
767                 max_freq = single_dpm_table->dpm_state.soft_max_level;
768                 ret = smu_send_smc_msg_with_param(smu,
769                         SMU_MSG_SetSoftMaxByFreq,
770                         (PPCLK_GFXCLK << 16) | (max_freq & 0xffff));
771                 if (ret) {
772                         pr_err("Failed to set soft max gfxclk !\n");
773                         return ret;
774                 }
775         }
776
777         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
778                 single_dpm_table = &(dpm_table->mem_table);
779                 max_freq = single_dpm_table->dpm_state.soft_max_level;
780                 ret = smu_send_smc_msg_with_param(smu,
781                         SMU_MSG_SetSoftMaxByFreq,
782                         (PPCLK_UCLK << 16) | (max_freq & 0xffff));
783                 if (ret) {
784                         pr_err("Failed to set soft max memclk !\n");
785                         return ret;
786                 }
787         }
788
789         return ret;
790 }
791
792 static int vega20_force_clk_levels(struct smu_context *smu,
793                         enum pp_clock_type type, uint32_t mask)
794 {
795         struct vega20_dpm_table *dpm_table;
796         struct vega20_single_dpm_table *single_dpm_table;
797         uint32_t soft_min_level, soft_max_level;
798         int ret;
799
800         soft_min_level = mask ? (ffs(mask) - 1) : 0;
801         soft_max_level = mask ? (fls(mask) - 1) : 0;
802
803         dpm_table = smu->smu_dpm.dpm_context;
804
805         switch (type) {
806         case PP_SCLK:
807                 single_dpm_table = &(dpm_table->gfx_table);
808
809                 if (soft_max_level >= single_dpm_table->count) {
810                         pr_err("Clock level specified %d is over max allowed %d\n",
811                                         soft_max_level, single_dpm_table->count - 1);
812                         return -EINVAL;
813                 }
814
815                 single_dpm_table->dpm_state.soft_min_level =
816                         single_dpm_table->dpm_levels[soft_min_level].value;
817                 single_dpm_table->dpm_state.soft_max_level =
818                         single_dpm_table->dpm_levels[soft_max_level].value;
819
820                 ret = vega20_upload_dpm_min_level(smu);
821                 if (ret) {
822                         pr_err("Failed to upload boot level to lowest!\n");
823                         return ret;
824                 }
825
826                 ret = vega20_upload_dpm_max_level(smu);
827                 if (ret) {
828                         pr_err("Failed to upload dpm max level to highest!\n");
829                         return ret;
830                 }
831
832                 break;
833
834         case PP_MCLK:
835                 single_dpm_table = &(dpm_table->mem_table);
836
837                 if (soft_max_level >= single_dpm_table->count) {
838                         pr_err("Clock level specified %d is over max allowed %d\n",
839                                         soft_max_level, single_dpm_table->count - 1);
840                         return -EINVAL;
841                 }
842
843                 single_dpm_table->dpm_state.soft_min_level =
844                         single_dpm_table->dpm_levels[soft_min_level].value;
845                 single_dpm_table->dpm_state.soft_max_level =
846                         single_dpm_table->dpm_levels[soft_max_level].value;
847
848                 ret = vega20_upload_dpm_min_level(smu);
849                 if (ret) {
850                         pr_err("Failed to upload boot level to lowest!\n");
851                         return ret;
852                 }
853
854                 ret = vega20_upload_dpm_max_level(smu);
855                 if (ret) {
856                         pr_err("Failed to upload dpm max level to highest!\n");
857                         return ret;
858                 }
859
860                 break;
861
862         default:
863                 break;
864         }
865
866         return 0;
867 }
868
869 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
870                                                  enum amd_pp_clock_type type,
871                                                  struct pp_clock_levels_with_latency *clocks)
872 {
873         int ret;
874         struct vega20_single_dpm_table *single_dpm_table;
875         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
876         struct vega20_dpm_table *dpm_table = NULL;
877
878         dpm_table = smu_dpm->dpm_context;
879
880         mutex_lock(&smu->mutex);
881
882         switch (type) {
883         case amd_pp_sys_clock:
884                 single_dpm_table = &(dpm_table->gfx_table);
885                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
886                 break;
887         case amd_pp_mem_clock:
888                 single_dpm_table = &(dpm_table->mem_table);
889                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
890                 break;
891         case amd_pp_dcef_clock:
892                 single_dpm_table = &(dpm_table->dcef_table);
893                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
894                 break;
895         case amd_pp_soc_clock:
896                 single_dpm_table = &(dpm_table->soc_table);
897                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
898                 break;
899         default:
900                 ret = -EINVAL;
901         }
902
903         mutex_unlock(&smu->mutex);
904         return ret;
905 }
906
907 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
908                                                      uint32_t *voltage,
909                                                      uint32_t freq)
910 {
911         int ret;
912
913         ret = smu_send_smc_msg_with_param(smu,
914                         SMU_MSG_GetAVFSVoltageByDpm,
915                         ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
916         if (ret) {
917                 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
918                 return ret;
919         }
920
921         smu_read_smc_arg(smu, voltage);
922         *voltage = *voltage / VOLTAGE_SCALE;
923
924         return 0;
925 }
926
927 static int vega20_set_default_od8_setttings(struct smu_context *smu)
928 {
929         struct smu_table_context *table_context = &smu->smu_table;
930         OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
931         struct vega20_od8_settings *od8_settings = NULL;
932         PPTable_t *smc_pptable = table_context->driver_pptable;
933         int i, ret;
934
935         if (table_context->od8_settings)
936                 return -EINVAL;
937
938         table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
939
940         if (!table_context->od8_settings)
941                 return -ENOMEM;
942
943         memset(table_context->od8_settings, 0, sizeof(struct vega20_od8_settings));
944         od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
945
946         if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
947                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
948                     table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
949                     table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
950                     (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
951                      table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
952                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
953                                 OD8_GFXCLK_LIMITS;
954                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
955                                 OD8_GFXCLK_LIMITS;
956                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
957                                 od_table->GfxclkFmin;
958                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
959                                 od_table->GfxclkFmax;
960                 }
961
962                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
963                     (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
964                      smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
965                     (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
966                      smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
967                     (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
968                      table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
969                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
970                                 OD8_GFXCLK_CURVE;
971                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
972                                 OD8_GFXCLK_CURVE;
973                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
974                                 OD8_GFXCLK_CURVE;
975                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
976                                 OD8_GFXCLK_CURVE;
977                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
978                                 OD8_GFXCLK_CURVE;
979                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
980                                 OD8_GFXCLK_CURVE;
981
982                         od_table->GfxclkFreq1 = od_table->GfxclkFmin;
983                         od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
984                         od_table->GfxclkFreq3 = od_table->GfxclkFmax;
985                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
986                                 od_table->GfxclkFreq1;
987                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
988                                 od_table->GfxclkFreq2;
989                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
990                                 od_table->GfxclkFreq3;
991
992                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
993                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
994                                 od_table->GfxclkFreq1);
995                         if (ret)
996                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
997                         od_table->GfxclkVolt1 =
998                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
999                                 * VOLTAGE_SCALE;
1000                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1001                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1002                                 od_table->GfxclkFreq2);
1003                         if (ret)
1004                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1005                         od_table->GfxclkVolt2 =
1006                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1007                                 * VOLTAGE_SCALE;
1008                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1009                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1010                                 od_table->GfxclkFreq3);
1011                         if (ret)
1012                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1013                         od_table->GfxclkVolt3 =
1014                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1015                                 * VOLTAGE_SCALE;
1016                 }
1017         }
1018
1019         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1020                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1021                     table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1022                     table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1023                     (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1024                      table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1025                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1026                                 OD8_UCLK_MAX;
1027                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1028                                 od_table->UclkFmax;
1029                 }
1030         }
1031
1032         if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1033             table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1034             table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1035             table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1036             table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1037                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1038                         OD8_POWER_LIMIT;
1039                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1040                         od_table->OverDrivePct;
1041         }
1042
1043         if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
1044                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1045                     table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1046                     table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1047                     (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1048                      table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1049                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1050                                 OD8_ACOUSTIC_LIMIT_SCLK;
1051                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1052                                 od_table->FanMaximumRpm;
1053                 }
1054
1055                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1056                     table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1057                     table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1058                     (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1059                      table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1060                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1061                                 OD8_FAN_SPEED_MIN;
1062                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1063                                 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1064                 }
1065         }
1066
1067         if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
1068                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1069                     table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1070                     table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1071                     (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1072                      table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1073                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1074                                 OD8_TEMPERATURE_FAN;
1075                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1076                                 od_table->FanTargetTemperature;
1077                 }
1078
1079                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1080                     table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1081                     table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1082                     (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1083                      table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1084                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1085                                 OD8_TEMPERATURE_SYSTEM;
1086                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1087                                 od_table->MaxOpTemp;
1088                 }
1089         }
1090
1091         for (i = 0; i < OD8_SETTING_COUNT; i++) {
1092                 if (od8_settings->od8_settings_array[i].feature_id) {
1093                         od8_settings->od8_settings_array[i].min_value =
1094                                 table_context->od_settings_min[i];
1095                         od8_settings->od8_settings_array[i].max_value =
1096                                 table_context->od_settings_max[i];
1097                         od8_settings->od8_settings_array[i].current_value =
1098                                 od8_settings->od8_settings_array[i].default_value;
1099                 } else {
1100                         od8_settings->od8_settings_array[i].min_value = 0;
1101                         od8_settings->od8_settings_array[i].max_value = 0;
1102                         od8_settings->od8_settings_array[i].current_value = 0;
1103                 }
1104         }
1105
1106         return 0;
1107 }
1108
1109 static const struct pptable_funcs vega20_ppt_funcs = {
1110         .alloc_dpm_context = vega20_allocate_dpm_context,
1111         .store_powerplay_table = vega20_store_powerplay_table,
1112         .check_powerplay_table = vega20_check_powerplay_table,
1113         .append_powerplay_table = vega20_append_powerplay_table,
1114         .get_smu_msg_index = vega20_get_smu_msg_index,
1115         .run_afll_btc = vega20_run_btc_afll,
1116         .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
1117         .set_default_dpm_table = vega20_set_default_dpm_table,
1118         .populate_umd_state_clk = vega20_populate_umd_state_clk,
1119         .print_clk_levels = vega20_print_clk_levels,
1120         .force_clk_levels = vega20_force_clk_levels,
1121         .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
1122         .set_default_od8_settings = vega20_set_default_od8_setttings,
1123 };
1124
1125 void vega20_set_ppt_funcs(struct smu_context *smu)
1126 {
1127         smu->ppt_funcs = &vega20_ppt_funcs;
1128 }