]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/vega20_ppt.c
Merge tag 'for-5.2-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
[linux.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 "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
40 #define smnPCIE_LC_SPEED_CNTL                   0x11140290
41 #define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
42
43 #define MSG_MAP(msg) \
44         [SMU_MSG_##msg] = PPSMC_MSG_##msg
45
46 static int vega20_message_map[SMU_MSG_MAX_COUNT] = {
47         MSG_MAP(TestMessage),
48         MSG_MAP(GetSmuVersion),
49         MSG_MAP(GetDriverIfVersion),
50         MSG_MAP(SetAllowedFeaturesMaskLow),
51         MSG_MAP(SetAllowedFeaturesMaskHigh),
52         MSG_MAP(EnableAllSmuFeatures),
53         MSG_MAP(DisableAllSmuFeatures),
54         MSG_MAP(EnableSmuFeaturesLow),
55         MSG_MAP(EnableSmuFeaturesHigh),
56         MSG_MAP(DisableSmuFeaturesLow),
57         MSG_MAP(DisableSmuFeaturesHigh),
58         MSG_MAP(GetEnabledSmuFeaturesLow),
59         MSG_MAP(GetEnabledSmuFeaturesHigh),
60         MSG_MAP(SetWorkloadMask),
61         MSG_MAP(SetPptLimit),
62         MSG_MAP(SetDriverDramAddrHigh),
63         MSG_MAP(SetDriverDramAddrLow),
64         MSG_MAP(SetToolsDramAddrHigh),
65         MSG_MAP(SetToolsDramAddrLow),
66         MSG_MAP(TransferTableSmu2Dram),
67         MSG_MAP(TransferTableDram2Smu),
68         MSG_MAP(UseDefaultPPTable),
69         MSG_MAP(UseBackupPPTable),
70         MSG_MAP(RunBtc),
71         MSG_MAP(RequestI2CBus),
72         MSG_MAP(ReleaseI2CBus),
73         MSG_MAP(SetFloorSocVoltage),
74         MSG_MAP(SoftReset),
75         MSG_MAP(StartBacoMonitor),
76         MSG_MAP(CancelBacoMonitor),
77         MSG_MAP(EnterBaco),
78         MSG_MAP(SetSoftMinByFreq),
79         MSG_MAP(SetSoftMaxByFreq),
80         MSG_MAP(SetHardMinByFreq),
81         MSG_MAP(SetHardMaxByFreq),
82         MSG_MAP(GetMinDpmFreq),
83         MSG_MAP(GetMaxDpmFreq),
84         MSG_MAP(GetDpmFreqByIndex),
85         MSG_MAP(GetDpmClockFreq),
86         MSG_MAP(GetSsVoltageByDpm),
87         MSG_MAP(SetMemoryChannelConfig),
88         MSG_MAP(SetGeminiMode),
89         MSG_MAP(SetGeminiApertureHigh),
90         MSG_MAP(SetGeminiApertureLow),
91         MSG_MAP(SetMinLinkDpmByIndex),
92         MSG_MAP(OverridePcieParameters),
93         MSG_MAP(OverDriveSetPercentage),
94         MSG_MAP(SetMinDeepSleepDcefclk),
95         MSG_MAP(ReenableAcDcInterrupt),
96         MSG_MAP(NotifyPowerSource),
97         MSG_MAP(SetUclkFastSwitch),
98         MSG_MAP(SetUclkDownHyst),
99         MSG_MAP(GetCurrentRpm),
100         MSG_MAP(SetVideoFps),
101         MSG_MAP(SetTjMax),
102         MSG_MAP(SetFanTemperatureTarget),
103         MSG_MAP(PrepareMp1ForUnload),
104         MSG_MAP(DramLogSetDramAddrHigh),
105         MSG_MAP(DramLogSetDramAddrLow),
106         MSG_MAP(DramLogSetDramSize),
107         MSG_MAP(SetFanMaxRpm),
108         MSG_MAP(SetFanMinPwm),
109         MSG_MAP(ConfigureGfxDidt),
110         MSG_MAP(NumOfDisplays),
111         MSG_MAP(RemoveMargins),
112         MSG_MAP(ReadSerialNumTop32),
113         MSG_MAP(ReadSerialNumBottom32),
114         MSG_MAP(SetSystemVirtualDramAddrHigh),
115         MSG_MAP(SetSystemVirtualDramAddrLow),
116         MSG_MAP(WaflTest),
117         MSG_MAP(SetFclkGfxClkRatio),
118         MSG_MAP(AllowGfxOff),
119         MSG_MAP(DisallowGfxOff),
120         MSG_MAP(GetPptLimit),
121         MSG_MAP(GetDcModeMaxDpmFreq),
122         MSG_MAP(GetDebugData),
123         MSG_MAP(SetXgmiMode),
124         MSG_MAP(RunAfllBtc),
125         MSG_MAP(ExitBaco),
126         MSG_MAP(PrepareMp1ForReset),
127         MSG_MAP(PrepareMp1ForShutdown),
128         MSG_MAP(SetMGpuFanBoostLimitRpm),
129         MSG_MAP(GetAVFSVoltageByDpm),
130 };
131
132 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
133 {
134         int val;
135
136         if (index >= SMU_MSG_MAX_COUNT)
137                 return -EINVAL;
138
139         val = vega20_message_map[index];
140         if (val > PPSMC_Message_Count)
141                 return -EINVAL;
142
143         return val;
144 }
145
146 static int vega20_allocate_dpm_context(struct smu_context *smu)
147 {
148         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
149
150         if (smu_dpm->dpm_context)
151                 return -EINVAL;
152
153         smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
154                                        GFP_KERNEL);
155         if (!smu_dpm->dpm_context)
156                 return -ENOMEM;
157
158         if (smu_dpm->golden_dpm_context)
159                 return -EINVAL;
160
161         smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
162                                               GFP_KERNEL);
163         if (!smu_dpm->golden_dpm_context)
164                 return -ENOMEM;
165
166         smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
167
168         smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
169                                        GFP_KERNEL);
170         if (!smu_dpm->dpm_current_power_state)
171                 return -ENOMEM;
172
173         smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
174                                        GFP_KERNEL);
175         if (!smu_dpm->dpm_request_power_state)
176                 return -ENOMEM;
177
178         return 0;
179 }
180
181 static int vega20_setup_od8_information(struct smu_context *smu)
182 {
183         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
184         struct smu_table_context *table_context = &smu->smu_table;
185
186         uint32_t od_feature_count, od_feature_array_size,
187                  od_setting_count, od_setting_array_size;
188
189         if (!table_context->power_play_table)
190                 return -EINVAL;
191
192         powerplay_table = table_context->power_play_table;
193
194         if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
195                 /* Setup correct ODFeatureCount, and store ODFeatureArray from
196                  * powerplay table to od_feature_capabilities */
197                 od_feature_count =
198                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
199                          ATOM_VEGA20_ODFEATURE_COUNT) ?
200                         ATOM_VEGA20_ODFEATURE_COUNT :
201                         le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
202
203                 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
204
205                 if (table_context->od_feature_capabilities)
206                         return -EINVAL;
207
208                 table_context->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
209                                                                  od_feature_array_size,
210                                                                  GFP_KERNEL);
211                 if (!table_context->od_feature_capabilities)
212                         return -ENOMEM;
213
214                 /* Setup correct ODSettingCount, and store ODSettingArray from
215                  * powerplay table to od_settings_max and od_setting_min */
216                 od_setting_count =
217                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
218                          ATOM_VEGA20_ODSETTING_COUNT) ?
219                         ATOM_VEGA20_ODSETTING_COUNT :
220                         le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
221
222                 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
223
224                 if (table_context->od_settings_max)
225                         return -EINVAL;
226
227                 table_context->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
228                                                          od_setting_array_size,
229                                                          GFP_KERNEL);
230
231                 if (!table_context->od_settings_max) {
232                         kfree(table_context->od_feature_capabilities);
233                         table_context->od_feature_capabilities = NULL;
234                         return -ENOMEM;
235                 }
236
237                 if (table_context->od_settings_min)
238                         return -EINVAL;
239
240                 table_context->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
241                                                          od_setting_array_size,
242                                                          GFP_KERNEL);
243
244                 if (!table_context->od_settings_min) {
245                         kfree(table_context->od_feature_capabilities);
246                         table_context->od_feature_capabilities = NULL;
247                         kfree(table_context->od_settings_max);
248                         table_context->od_settings_max = NULL;
249                         return -ENOMEM;
250                 }
251         }
252
253         return 0;
254 }
255
256 static int vega20_store_powerplay_table(struct smu_context *smu)
257 {
258         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
259         struct smu_table_context *table_context = &smu->smu_table;
260         int ret;
261
262         if (!table_context->power_play_table)
263                 return -EINVAL;
264
265         powerplay_table = table_context->power_play_table;
266
267         memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
268                sizeof(PPTable_t));
269
270         table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
271         table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
272         table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
273
274         ret = vega20_setup_od8_information(smu);
275
276         return ret;
277 }
278
279 static int vega20_append_powerplay_table(struct smu_context *smu)
280 {
281         struct smu_table_context *table_context = &smu->smu_table;
282         PPTable_t *smc_pptable = table_context->driver_pptable;
283         struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
284         int index, i, ret;
285
286         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
287                                            smc_dpm_info);
288
289         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
290                                       (uint8_t **)&smc_dpm_table);
291         if (ret)
292                 return ret;
293
294         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
295         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
296
297         smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
298         smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
299         smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
300         smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
301
302         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
303         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
304         smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
305
306         smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
307         smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
308         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
309
310         smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
311         smc_pptable->SocOffset = smc_dpm_table->socoffset;
312         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
313
314         smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
315         smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
316         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
317
318         smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
319         smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
320         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
321
322         smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
323         smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
324         smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
325         smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
326
327         smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
328         smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
329         smc_pptable->Padding1 = smc_dpm_table->padding1;
330         smc_pptable->Padding2 = smc_dpm_table->padding2;
331
332         smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
333         smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
334         smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
335
336         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
337         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
338         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
339
340         smc_pptable->UclkSpreadEnabled = 0;
341         smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
342         smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
343
344         smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
345         smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
346         smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
347
348         smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
349         smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
350         smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
351
352         for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
353                 smc_pptable->I2cControllers[i].Enabled =
354                         smc_dpm_table->i2ccontrollers[i].enabled;
355                 smc_pptable->I2cControllers[i].SlaveAddress =
356                         smc_dpm_table->i2ccontrollers[i].slaveaddress;
357                 smc_pptable->I2cControllers[i].ControllerPort =
358                         smc_dpm_table->i2ccontrollers[i].controllerport;
359                 smc_pptable->I2cControllers[i].ThermalThrottler =
360                         smc_dpm_table->i2ccontrollers[i].thermalthrottler;
361                 smc_pptable->I2cControllers[i].I2cProtocol =
362                         smc_dpm_table->i2ccontrollers[i].i2cprotocol;
363                 smc_pptable->I2cControllers[i].I2cSpeed =
364                         smc_dpm_table->i2ccontrollers[i].i2cspeed;
365         }
366
367         return 0;
368 }
369
370 static int vega20_check_powerplay_table(struct smu_context *smu)
371 {
372         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
373         struct smu_table_context *table_context = &smu->smu_table;
374
375         powerplay_table = table_context->power_play_table;
376
377         if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
378                 pr_err("Unsupported PPTable format!");
379                 return -EINVAL;
380         }
381
382         if (!powerplay_table->sHeader.structuresize) {
383                 pr_err("Invalid PowerPlay Table!");
384                 return -EINVAL;
385         }
386
387         return 0;
388 }
389
390 static int vega20_run_btc_afll(struct smu_context *smu)
391 {
392         return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
393 }
394
395 static int
396 vega20_get_unallowed_feature_mask(struct smu_context *smu,
397                                   uint32_t *feature_mask, uint32_t num)
398 {
399         if (num > 2)
400                 return -EINVAL;
401
402         feature_mask[0] = 0xE0041C00;
403         feature_mask[1] = 0xFFFFFFFE; /* bit32~bit63 is Unsupported */
404
405         return 0;
406 }
407
408 static enum
409 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
410 {
411         enum amd_pm_state_type pm_type;
412         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
413
414         if (!smu_dpm_ctx->dpm_context ||
415             !smu_dpm_ctx->dpm_current_power_state)
416                 return -EINVAL;
417
418         mutex_lock(&(smu->mutex));
419         switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
420         case SMU_STATE_UI_LABEL_BATTERY:
421                 pm_type = POWER_STATE_TYPE_BATTERY;
422                 break;
423         case SMU_STATE_UI_LABEL_BALLANCED:
424                 pm_type = POWER_STATE_TYPE_BALANCED;
425                 break;
426         case SMU_STATE_UI_LABEL_PERFORMANCE:
427                 pm_type = POWER_STATE_TYPE_PERFORMANCE;
428                 break;
429         default:
430                 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
431                         pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
432                 else
433                         pm_type = POWER_STATE_TYPE_DEFAULT;
434                 break;
435         }
436         mutex_unlock(&(smu->mutex));
437
438         return pm_type;
439 }
440
441 static int
442 vega20_set_single_dpm_table(struct smu_context *smu,
443                             struct vega20_single_dpm_table *single_dpm_table,
444                             PPCLK_e clk_id)
445 {
446         int ret = 0;
447         uint32_t i, num_of_levels = 0, clk;
448
449         ret = smu_send_smc_msg_with_param(smu,
450                         SMU_MSG_GetDpmFreqByIndex,
451                         (clk_id << 16 | 0xFF));
452         if (ret) {
453                 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
454                 return ret;
455         }
456
457         smu_read_smc_arg(smu, &num_of_levels);
458         if (!num_of_levels) {
459                 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
460                 return -EINVAL;
461         }
462
463         single_dpm_table->count = num_of_levels;
464
465         for (i = 0; i < num_of_levels; i++) {
466                 ret = smu_send_smc_msg_with_param(smu,
467                                 SMU_MSG_GetDpmFreqByIndex,
468                                 (clk_id << 16 | i));
469                 if (ret) {
470                         pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
471                         return ret;
472                 }
473                 smu_read_smc_arg(smu, &clk);
474                 if (!clk) {
475                         pr_err("[GetDpmFreqByIndex] clk value is invalid!");
476                         return -EINVAL;
477                 }
478                 single_dpm_table->dpm_levels[i].value = clk;
479                 single_dpm_table->dpm_levels[i].enabled = true;
480         }
481         return 0;
482 }
483
484 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
485 {
486         dpm_state->soft_min_level = 0x0;
487         dpm_state->soft_max_level = 0xffff;
488         dpm_state->hard_min_level = 0x0;
489         dpm_state->hard_max_level = 0xffff;
490 }
491
492 static int vega20_set_default_dpm_table(struct smu_context *smu)
493 {
494         int ret;
495
496         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
497         struct vega20_dpm_table *dpm_table = NULL;
498         struct vega20_single_dpm_table *single_dpm_table;
499
500         dpm_table = smu_dpm->dpm_context;
501
502         /* socclk */
503         single_dpm_table = &(dpm_table->soc_table);
504
505         if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
506                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
507                                                   PPCLK_SOCCLK);
508                 if (ret) {
509                         pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
510                         return ret;
511                 }
512         } else {
513                 single_dpm_table->count = 1;
514                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
515         }
516         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
517
518         /* gfxclk */
519         single_dpm_table = &(dpm_table->gfx_table);
520
521         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
522                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
523                                                   PPCLK_GFXCLK);
524                 if (ret) {
525                         pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
526                         return ret;
527                 }
528         } else {
529                 single_dpm_table->count = 1;
530                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
531         }
532         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
533
534         /* memclk */
535         single_dpm_table = &(dpm_table->mem_table);
536
537         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
538                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
539                                                   PPCLK_UCLK);
540                 if (ret) {
541                         pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
542                         return ret;
543                 }
544         } else {
545                 single_dpm_table->count = 1;
546                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
547         }
548         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
549
550         /* eclk */
551         single_dpm_table = &(dpm_table->eclk_table);
552
553         if (smu_feature_is_enabled(smu, FEATURE_DPM_VCE_BIT)) {
554                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
555                 if (ret) {
556                         pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
557                         return ret;
558                 }
559         } else {
560                 single_dpm_table->count = 1;
561                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
562         }
563         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
564
565         /* vclk */
566         single_dpm_table = &(dpm_table->vclk_table);
567
568         if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
569                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
570                 if (ret) {
571                         pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
572                         return ret;
573                 }
574         } else {
575                 single_dpm_table->count = 1;
576                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
577         }
578         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
579
580         /* dclk */
581         single_dpm_table = &(dpm_table->dclk_table);
582
583         if (smu_feature_is_enabled(smu, FEATURE_DPM_UVD_BIT)) {
584                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
585                 if (ret) {
586                         pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
587                         return ret;
588                 }
589         } else {
590                 single_dpm_table->count = 1;
591                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
592         }
593         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
594
595         /* dcefclk */
596         single_dpm_table = &(dpm_table->dcef_table);
597
598         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
599                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
600                                                   PPCLK_DCEFCLK);
601                 if (ret) {
602                         pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
603                         return ret;
604                 }
605         } else {
606                 single_dpm_table->count = 1;
607                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
608         }
609         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
610
611         /* pixclk */
612         single_dpm_table = &(dpm_table->pixel_table);
613
614         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
615                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
616                                                   PPCLK_PIXCLK);
617                 if (ret) {
618                         pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
619                         return ret;
620                 }
621         } else {
622                 single_dpm_table->count = 0;
623         }
624         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
625
626         /* dispclk */
627         single_dpm_table = &(dpm_table->display_table);
628
629         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
630                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
631                                                   PPCLK_DISPCLK);
632                 if (ret) {
633                         pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
634                         return ret;
635                 }
636         } else {
637                 single_dpm_table->count = 0;
638         }
639         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
640
641         /* phyclk */
642         single_dpm_table = &(dpm_table->phy_table);
643
644         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
645                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
646                                                   PPCLK_PHYCLK);
647                 if (ret) {
648                         pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
649                         return ret;
650                 }
651         } else {
652                 single_dpm_table->count = 0;
653         }
654         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
655
656         /* fclk */
657         single_dpm_table = &(dpm_table->fclk_table);
658
659         if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
660                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
661                                                   PPCLK_FCLK);
662                 if (ret) {
663                         pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
664                         return ret;
665                 }
666         } else {
667                 single_dpm_table->count = 0;
668         }
669         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
670
671         memcpy(smu_dpm->golden_dpm_context, dpm_table,
672                sizeof(struct vega20_dpm_table));
673
674         return 0;
675 }
676
677 static int vega20_populate_umd_state_clk(struct smu_context *smu)
678 {
679         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
680         struct vega20_dpm_table *dpm_table = NULL;
681         struct vega20_single_dpm_table *gfx_table = NULL;
682         struct vega20_single_dpm_table *mem_table = NULL;
683
684         dpm_table = smu_dpm->dpm_context;
685         gfx_table = &(dpm_table->gfx_table);
686         mem_table = &(dpm_table->mem_table);
687
688         smu->pstate_sclk = gfx_table->dpm_levels[0].value;
689         smu->pstate_mclk = mem_table->dpm_levels[0].value;
690
691         if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
692             mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
693                 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
694                 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
695         }
696
697         smu->pstate_sclk = smu->pstate_sclk * 100;
698         smu->pstate_mclk = smu->pstate_mclk * 100;
699
700         return 0;
701 }
702
703 static int vega20_get_clk_table(struct smu_context *smu,
704                         struct pp_clock_levels_with_latency *clocks,
705                         struct vega20_single_dpm_table *dpm_table)
706 {
707         int i, count;
708
709         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
710         clocks->num_levels = count;
711
712         for (i = 0; i < count; i++) {
713                 clocks->data[i].clocks_in_khz =
714                         dpm_table->dpm_levels[i].value * 1000;
715                 clocks->data[i].latency_in_us = 0;
716         }
717
718         return 0;
719 }
720
721 static int vega20_print_clk_levels(struct smu_context *smu,
722                         enum pp_clock_type type, char *buf)
723 {
724         int i, now, size = 0;
725         int ret = 0;
726         uint32_t gen_speed, lane_width;
727         struct amdgpu_device *adev = smu->adev;
728         struct pp_clock_levels_with_latency clocks;
729         struct vega20_single_dpm_table *single_dpm_table;
730         struct smu_table_context *table_context = &smu->smu_table;
731         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
732         struct vega20_dpm_table *dpm_table = NULL;
733         struct vega20_od8_settings *od8_settings =
734                 (struct vega20_od8_settings *)table_context->od8_settings;
735         OverDriveTable_t *od_table =
736                 (OverDriveTable_t *)(table_context->overdrive_table);
737         PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
738
739         dpm_table = smu_dpm->dpm_context;
740
741         switch (type) {
742         case PP_SCLK:
743                 ret = smu_get_current_clk_freq(smu, PPCLK_GFXCLK, &now);
744                 if (ret) {
745                         pr_err("Attempt to get current gfx clk Failed!");
746                         return ret;
747                 }
748
749                 single_dpm_table = &(dpm_table->gfx_table);
750                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
751                 if (ret) {
752                         pr_err("Attempt to get gfx clk levels Failed!");
753                         return ret;
754                 }
755
756                 for (i = 0; i < clocks.num_levels; i++)
757                         size += sprintf(buf + size, "%d: %uMhz %s\n", i,
758                                         clocks.data[i].clocks_in_khz / 1000,
759                                         (clocks.data[i].clocks_in_khz == now * 10)
760                                         ? "*" : "");
761                 break;
762
763         case PP_MCLK:
764                 ret = smu_get_current_clk_freq(smu, PPCLK_UCLK, &now);
765                 if (ret) {
766                         pr_err("Attempt to get current mclk Failed!");
767                         return ret;
768                 }
769
770                 single_dpm_table = &(dpm_table->mem_table);
771                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
772                 if (ret) {
773                         pr_err("Attempt to get memory clk levels Failed!");
774                         return ret;
775                 }
776
777                 for (i = 0; i < clocks.num_levels; i++)
778                         size += sprintf(buf + size, "%d: %uMhz %s\n",
779                                 i, clocks.data[i].clocks_in_khz / 1000,
780                                 (clocks.data[i].clocks_in_khz == now * 10)
781                                 ? "*" : "");
782                 break;
783
784         case PP_SOCCLK:
785                 ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, &now);
786                 if (ret) {
787                         pr_err("Attempt to get current socclk Failed!");
788                         return ret;
789                 }
790
791                 single_dpm_table = &(dpm_table->soc_table);
792                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
793                 if (ret) {
794                         pr_err("Attempt to get socclk levels Failed!");
795                         return ret;
796                 }
797
798                 for (i = 0; i < clocks.num_levels; i++)
799                         size += sprintf(buf + size, "%d: %uMhz %s\n",
800                                 i, clocks.data[i].clocks_in_khz / 1000,
801                                 (clocks.data[i].clocks_in_khz == now * 10)
802                                 ? "*" : "");
803                 break;
804
805         case PP_FCLK:
806                 ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now);
807                 if (ret) {
808                         pr_err("Attempt to get current fclk Failed!");
809                         return ret;
810                 }
811
812                 single_dpm_table = &(dpm_table->fclk_table);
813                 for (i = 0; i < single_dpm_table->count; i++)
814                         size += sprintf(buf + size, "%d: %uMhz %s\n",
815                                 i, single_dpm_table->dpm_levels[i].value,
816                                 (single_dpm_table->dpm_levels[i].value == now / 100)
817                                 ? "*" : "");
818                 break;
819
820         case PP_DCEFCLK:
821                 ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, &now);
822                 if (ret) {
823                         pr_err("Attempt to get current dcefclk Failed!");
824                         return ret;
825                 }
826
827                 single_dpm_table = &(dpm_table->dcef_table);
828                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
829                 if (ret) {
830                         pr_err("Attempt to get dcefclk levels Failed!");
831                         return ret;
832                 }
833
834                 for (i = 0; i < clocks.num_levels; i++)
835                         size += sprintf(buf + size, "%d: %uMhz %s\n",
836                                 i, clocks.data[i].clocks_in_khz / 1000,
837                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
838                 break;
839
840         case PP_PCIE:
841                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
842                              PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
843                         >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
844                 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
845                               PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
846                         >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
847                 for (i = 0; i < NUM_LINK_LEVELS; i++)
848                         size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
849                                         (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
850                                         (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
851                                         (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
852                                         (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
853                                         (pptable->PcieLaneCount[i] == 1) ? "x1" :
854                                         (pptable->PcieLaneCount[i] == 2) ? "x2" :
855                                         (pptable->PcieLaneCount[i] == 3) ? "x4" :
856                                         (pptable->PcieLaneCount[i] == 4) ? "x8" :
857                                         (pptable->PcieLaneCount[i] == 5) ? "x12" :
858                                         (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
859                                         pptable->LclkFreq[i],
860                                         (gen_speed == pptable->PcieGenSpeed[i]) &&
861                                         (lane_width == pptable->PcieLaneCount[i]) ?
862                                         "*" : "");
863                 break;
864
865         case OD_SCLK:
866                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
867                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
868                         size = sprintf(buf, "%s:\n", "OD_SCLK");
869                         size += sprintf(buf + size, "0: %10uMhz\n",
870                                         od_table->GfxclkFmin);
871                         size += sprintf(buf + size, "1: %10uMhz\n",
872                                         od_table->GfxclkFmax);
873                 }
874
875                 break;
876
877         case OD_MCLK:
878                 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
879                         size = sprintf(buf, "%s:\n", "OD_MCLK");
880                         size += sprintf(buf + size, "1: %10uMhz\n",
881                                          od_table->UclkFmax);
882                 }
883
884                 break;
885
886         case OD_VDDC_CURVE:
887                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
888                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
889                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
890                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
891                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
892                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
893                         size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
894                         size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
895                                         od_table->GfxclkFreq1,
896                                         od_table->GfxclkVolt1 / VOLTAGE_SCALE);
897                         size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
898                                         od_table->GfxclkFreq2,
899                                         od_table->GfxclkVolt2 / VOLTAGE_SCALE);
900                         size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
901                                         od_table->GfxclkFreq3,
902                                         od_table->GfxclkVolt3 / VOLTAGE_SCALE);
903                 }
904
905                 break;
906
907         case OD_RANGE:
908                 size = sprintf(buf, "%s:\n", "OD_RANGE");
909
910                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
911                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
912                         size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
913                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
914                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
915                 }
916
917                 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
918                         single_dpm_table = &(dpm_table->mem_table);
919                         ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
920                         if (ret) {
921                                 pr_err("Attempt to get memory clk levels Failed!");
922                                 return ret;
923                         }
924
925                         size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
926                                         clocks.data[0].clocks_in_khz / 1000,
927                                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
928                 }
929
930                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
931                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
932                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
933                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
934                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
935                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
936                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
937                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
938                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
939                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
940                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
941                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
942                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
943                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
944                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
945                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
946                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
947                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
948                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
949                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
950                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
951                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
952                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
953                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
954                 }
955
956                 break;
957
958         default:
959                 break;
960         }
961         return size;
962 }
963
964 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
965                                    uint32_t feature_mask)
966 {
967         struct vega20_dpm_table *dpm_table;
968         struct vega20_single_dpm_table *single_dpm_table;
969         uint32_t freq;
970         int ret = 0;
971
972         dpm_table = smu->smu_dpm.dpm_context;
973
974         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT) &&
975             (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
976                 single_dpm_table = &(dpm_table->gfx_table);
977                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
978                         single_dpm_table->dpm_state.soft_min_level;
979                 ret = smu_send_smc_msg_with_param(smu,
980                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
981                         (PPCLK_GFXCLK << 16) | (freq & 0xffff));
982                 if (ret) {
983                         pr_err("Failed to set soft %s gfxclk !\n",
984                                                 max ? "max" : "min");
985                         return ret;
986                 }
987         }
988
989         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT) &&
990             (feature_mask & FEATURE_DPM_UCLK_MASK)) {
991                 single_dpm_table = &(dpm_table->mem_table);
992                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
993                         single_dpm_table->dpm_state.soft_min_level;
994                 ret = smu_send_smc_msg_with_param(smu,
995                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
996                         (PPCLK_UCLK << 16) | (freq & 0xffff));
997                 if (ret) {
998                         pr_err("Failed to set soft %s memclk !\n",
999                                                 max ? "max" : "min");
1000                         return ret;
1001                 }
1002         }
1003
1004         if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT) &&
1005             (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1006                 single_dpm_table = &(dpm_table->soc_table);
1007                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1008                         single_dpm_table->dpm_state.soft_min_level;
1009                 ret = smu_send_smc_msg_with_param(smu,
1010                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1011                         (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1012                 if (ret) {
1013                         pr_err("Failed to set soft %s socclk !\n",
1014                                                 max ? "max" : "min");
1015                         return ret;
1016                 }
1017         }
1018
1019         if (smu_feature_is_enabled(smu, FEATURE_DPM_FCLK_BIT) &&
1020             (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1021                 single_dpm_table = &(dpm_table->fclk_table);
1022                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1023                         single_dpm_table->dpm_state.soft_min_level;
1024                 ret = smu_send_smc_msg_with_param(smu,
1025                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1026                         (PPCLK_FCLK << 16) | (freq & 0xffff));
1027                 if (ret) {
1028                         pr_err("Failed to set soft %s fclk !\n",
1029                                                 max ? "max" : "min");
1030                         return ret;
1031                 }
1032         }
1033
1034         if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1035             (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1036                 single_dpm_table = &(dpm_table->dcef_table);
1037                 freq = single_dpm_table->dpm_state.hard_min_level;
1038                 if (!max) {
1039                         ret = smu_send_smc_msg_with_param(smu,
1040                                 SMU_MSG_SetHardMinByFreq,
1041                                 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1042                         if (ret) {
1043                                 pr_err("Failed to set hard min dcefclk !\n");
1044                                 return ret;
1045                         }
1046                 }
1047         }
1048
1049         return ret;
1050 }
1051
1052 static int vega20_force_clk_levels(struct smu_context *smu,
1053                         enum pp_clock_type type, uint32_t mask)
1054 {
1055         struct vega20_dpm_table *dpm_table;
1056         struct vega20_single_dpm_table *single_dpm_table;
1057         uint32_t soft_min_level, soft_max_level, hard_min_level;
1058         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1059         int ret = 0;
1060
1061         if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1062                 pr_info("force clock level is for dpm manual mode only.\n");
1063                 return -EINVAL;
1064         }
1065
1066         mutex_lock(&(smu->mutex));
1067
1068         soft_min_level = mask ? (ffs(mask) - 1) : 0;
1069         soft_max_level = mask ? (fls(mask) - 1) : 0;
1070
1071         dpm_table = smu->smu_dpm.dpm_context;
1072
1073         switch (type) {
1074         case PP_SCLK:
1075                 single_dpm_table = &(dpm_table->gfx_table);
1076
1077                 if (soft_max_level >= single_dpm_table->count) {
1078                         pr_err("Clock level specified %d is over max allowed %d\n",
1079                                         soft_max_level, single_dpm_table->count - 1);
1080                         ret = -EINVAL;
1081                         break;
1082                 }
1083
1084                 single_dpm_table->dpm_state.soft_min_level =
1085                         single_dpm_table->dpm_levels[soft_min_level].value;
1086                 single_dpm_table->dpm_state.soft_max_level =
1087                         single_dpm_table->dpm_levels[soft_max_level].value;
1088
1089                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1090                 if (ret) {
1091                         pr_err("Failed to upload boot level to lowest!\n");
1092                         break;
1093                 }
1094
1095                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1096                 if (ret)
1097                         pr_err("Failed to upload dpm max level to highest!\n");
1098
1099                 break;
1100
1101         case PP_MCLK:
1102                 single_dpm_table = &(dpm_table->mem_table);
1103
1104                 if (soft_max_level >= single_dpm_table->count) {
1105                         pr_err("Clock level specified %d is over max allowed %d\n",
1106                                         soft_max_level, single_dpm_table->count - 1);
1107                         ret = -EINVAL;
1108                         break;
1109                 }
1110
1111                 single_dpm_table->dpm_state.soft_min_level =
1112                         single_dpm_table->dpm_levels[soft_min_level].value;
1113                 single_dpm_table->dpm_state.soft_max_level =
1114                         single_dpm_table->dpm_levels[soft_max_level].value;
1115
1116                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1117                 if (ret) {
1118                         pr_err("Failed to upload boot level to lowest!\n");
1119                         break;
1120                 }
1121
1122                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1123                 if (ret)
1124                         pr_err("Failed to upload dpm max level to highest!\n");
1125
1126                 break;
1127
1128         case PP_SOCCLK:
1129                 single_dpm_table = &(dpm_table->soc_table);
1130
1131                 if (soft_max_level >= single_dpm_table->count) {
1132                         pr_err("Clock level specified %d is over max allowed %d\n",
1133                                         soft_max_level, single_dpm_table->count - 1);
1134                         ret = -EINVAL;
1135                         break;
1136                 }
1137
1138                 single_dpm_table->dpm_state.soft_min_level =
1139                         single_dpm_table->dpm_levels[soft_min_level].value;
1140                 single_dpm_table->dpm_state.soft_max_level =
1141                         single_dpm_table->dpm_levels[soft_max_level].value;
1142
1143                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1144                 if (ret) {
1145                         pr_err("Failed to upload boot level to lowest!\n");
1146                         break;
1147                 }
1148
1149                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1150                 if (ret)
1151                         pr_err("Failed to upload dpm max level to highest!\n");
1152
1153                 break;
1154
1155         case PP_FCLK:
1156                 single_dpm_table = &(dpm_table->fclk_table);
1157
1158                 if (soft_max_level >= single_dpm_table->count) {
1159                         pr_err("Clock level specified %d is over max allowed %d\n",
1160                                         soft_max_level, single_dpm_table->count - 1);
1161                         ret = -EINVAL;
1162                         break;
1163                 }
1164
1165                 single_dpm_table->dpm_state.soft_min_level =
1166                         single_dpm_table->dpm_levels[soft_min_level].value;
1167                 single_dpm_table->dpm_state.soft_max_level =
1168                         single_dpm_table->dpm_levels[soft_max_level].value;
1169
1170                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1171                 if (ret) {
1172                         pr_err("Failed to upload boot level to lowest!\n");
1173                         break;
1174                 }
1175
1176                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1177                 if (ret)
1178                         pr_err("Failed to upload dpm max level to highest!\n");
1179
1180                 break;
1181
1182         case PP_DCEFCLK:
1183                 hard_min_level = soft_min_level;
1184                 single_dpm_table = &(dpm_table->dcef_table);
1185
1186                 if (hard_min_level >= single_dpm_table->count) {
1187                         pr_err("Clock level specified %d is over max allowed %d\n",
1188                                         hard_min_level, single_dpm_table->count - 1);
1189                         ret = -EINVAL;
1190                         break;
1191                 }
1192
1193                 single_dpm_table->dpm_state.hard_min_level =
1194                         single_dpm_table->dpm_levels[hard_min_level].value;
1195
1196                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1197                 if (ret)
1198                         pr_err("Failed to upload boot level to lowest!\n");
1199
1200                 break;
1201
1202         case PP_PCIE:
1203                 if (soft_min_level >= NUM_LINK_LEVELS ||
1204                     soft_max_level >= NUM_LINK_LEVELS) {
1205                         ret = -EINVAL;
1206                         break;
1207                 }
1208
1209                 ret = smu_send_smc_msg_with_param(smu,
1210                                 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1211                 if (ret)
1212                         pr_err("Failed to set min link dpm level!\n");
1213
1214                 break;
1215
1216         default:
1217                 break;
1218         }
1219
1220         mutex_unlock(&(smu->mutex));
1221         return ret;
1222 }
1223
1224 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1225                                                  enum amd_pp_clock_type type,
1226                                                  struct pp_clock_levels_with_latency *clocks)
1227 {
1228         int ret;
1229         struct vega20_single_dpm_table *single_dpm_table;
1230         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1231         struct vega20_dpm_table *dpm_table = NULL;
1232
1233         dpm_table = smu_dpm->dpm_context;
1234
1235         mutex_lock(&smu->mutex);
1236
1237         switch (type) {
1238         case amd_pp_sys_clock:
1239                 single_dpm_table = &(dpm_table->gfx_table);
1240                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1241                 break;
1242         case amd_pp_mem_clock:
1243                 single_dpm_table = &(dpm_table->mem_table);
1244                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1245                 break;
1246         case amd_pp_dcef_clock:
1247                 single_dpm_table = &(dpm_table->dcef_table);
1248                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1249                 break;
1250         case amd_pp_soc_clock:
1251                 single_dpm_table = &(dpm_table->soc_table);
1252                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1253                 break;
1254         default:
1255                 ret = -EINVAL;
1256         }
1257
1258         mutex_unlock(&smu->mutex);
1259         return ret;
1260 }
1261
1262 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1263                                                      uint32_t *voltage,
1264                                                      uint32_t freq)
1265 {
1266         int ret;
1267
1268         ret = smu_send_smc_msg_with_param(smu,
1269                         SMU_MSG_GetAVFSVoltageByDpm,
1270                         ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1271         if (ret) {
1272                 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1273                 return ret;
1274         }
1275
1276         smu_read_smc_arg(smu, voltage);
1277         *voltage = *voltage / VOLTAGE_SCALE;
1278
1279         return 0;
1280 }
1281
1282 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1283 {
1284         struct smu_table_context *table_context = &smu->smu_table;
1285         OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1286         struct vega20_od8_settings *od8_settings = NULL;
1287         PPTable_t *smc_pptable = table_context->driver_pptable;
1288         int i, ret;
1289
1290         if (table_context->od8_settings)
1291                 return -EINVAL;
1292
1293         table_context->od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1294
1295         if (!table_context->od8_settings)
1296                 return -ENOMEM;
1297
1298         memset(table_context->od8_settings, 0, sizeof(struct vega20_od8_settings));
1299         od8_settings = (struct vega20_od8_settings *)table_context->od8_settings;
1300
1301         if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
1302                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1303                     table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1304                     table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1305                     (table_context->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1306                      table_context->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1307                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1308                                 OD8_GFXCLK_LIMITS;
1309                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1310                                 OD8_GFXCLK_LIMITS;
1311                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1312                                 od_table->GfxclkFmin;
1313                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1314                                 od_table->GfxclkFmax;
1315                 }
1316
1317                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1318                     (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1319                      smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1320                     (table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1321                      smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1322                     (table_context->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1323                      table_context->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1324                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1325                                 OD8_GFXCLK_CURVE;
1326                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1327                                 OD8_GFXCLK_CURVE;
1328                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1329                                 OD8_GFXCLK_CURVE;
1330                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1331                                 OD8_GFXCLK_CURVE;
1332                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1333                                 OD8_GFXCLK_CURVE;
1334                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1335                                 OD8_GFXCLK_CURVE;
1336
1337                         od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1338                         od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1339                         od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1340                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1341                                 od_table->GfxclkFreq1;
1342                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1343                                 od_table->GfxclkFreq2;
1344                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1345                                 od_table->GfxclkFreq3;
1346
1347                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1348                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1349                                 od_table->GfxclkFreq1);
1350                         if (ret)
1351                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1352                         od_table->GfxclkVolt1 =
1353                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1354                                 * VOLTAGE_SCALE;
1355                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1356                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1357                                 od_table->GfxclkFreq2);
1358                         if (ret)
1359                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1360                         od_table->GfxclkVolt2 =
1361                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1362                                 * VOLTAGE_SCALE;
1363                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1364                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1365                                 od_table->GfxclkFreq3);
1366                         if (ret)
1367                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1368                         od_table->GfxclkVolt3 =
1369                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1370                                 * VOLTAGE_SCALE;
1371                 }
1372         }
1373
1374         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1375                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1376                     table_context->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1377                     table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1378                     (table_context->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1379                      table_context->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1380                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1381                                 OD8_UCLK_MAX;
1382                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1383                                 od_table->UclkFmax;
1384                 }
1385         }
1386
1387         if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1388             table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1389             table_context->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1390             table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1391             table_context->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1392                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1393                         OD8_POWER_LIMIT;
1394                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1395                         od_table->OverDrivePct;
1396         }
1397
1398         if (smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT)) {
1399                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1400                     table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1401                     table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1402                     (table_context->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1403                      table_context->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1404                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1405                                 OD8_ACOUSTIC_LIMIT_SCLK;
1406                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1407                                 od_table->FanMaximumRpm;
1408                 }
1409
1410                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1411                     table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1412                     table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1413                     (table_context->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1414                      table_context->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1415                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1416                                 OD8_FAN_SPEED_MIN;
1417                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1418                                 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1419                 }
1420         }
1421
1422         if (smu_feature_is_enabled(smu, FEATURE_THERMAL_BIT)) {
1423                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1424                     table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1425                     table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1426                     (table_context->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1427                      table_context->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1428                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1429                                 OD8_TEMPERATURE_FAN;
1430                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1431                                 od_table->FanTargetTemperature;
1432                 }
1433
1434                 if (table_context->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1435                     table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1436                     table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1437                     (table_context->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1438                      table_context->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1439                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1440                                 OD8_TEMPERATURE_SYSTEM;
1441                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1442                                 od_table->MaxOpTemp;
1443                 }
1444         }
1445
1446         for (i = 0; i < OD8_SETTING_COUNT; i++) {
1447                 if (od8_settings->od8_settings_array[i].feature_id) {
1448                         od8_settings->od8_settings_array[i].min_value =
1449                                 table_context->od_settings_min[i];
1450                         od8_settings->od8_settings_array[i].max_value =
1451                                 table_context->od_settings_max[i];
1452                         od8_settings->od8_settings_array[i].current_value =
1453                                 od8_settings->od8_settings_array[i].default_value;
1454                 } else {
1455                         od8_settings->od8_settings_array[i].min_value = 0;
1456                         od8_settings->od8_settings_array[i].max_value = 0;
1457                         od8_settings->od8_settings_array[i].current_value = 0;
1458                 }
1459         }
1460
1461         return 0;
1462 }
1463
1464 static int vega20_get_od_percentage(struct smu_context *smu,
1465                                     enum pp_clock_type type)
1466 {
1467         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1468         struct vega20_dpm_table *dpm_table = NULL;
1469         struct vega20_dpm_table *golden_table = NULL;
1470         struct vega20_single_dpm_table *single_dpm_table;
1471         struct vega20_single_dpm_table *golden_dpm_table;
1472         int value, golden_value;
1473
1474         dpm_table = smu_dpm->dpm_context;
1475         golden_table = smu_dpm->golden_dpm_context;
1476
1477         switch (type) {
1478         case OD_SCLK:
1479                 single_dpm_table = &(dpm_table->gfx_table);
1480                 golden_dpm_table = &(golden_table->gfx_table);
1481                 break;
1482         case OD_MCLK:
1483                 single_dpm_table = &(dpm_table->mem_table);
1484                 golden_dpm_table = &(golden_table->mem_table);
1485                 break;
1486         default:
1487                 return -EINVAL;
1488                 break;
1489         }
1490
1491         value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1492         golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1493
1494         value -= golden_value;
1495         value = DIV_ROUND_UP(value * 100, golden_value);
1496
1497         return value;
1498 }
1499
1500 static int
1501 vega20_get_profiling_clk_mask(struct smu_context *smu,
1502                               enum amd_dpm_forced_level level,
1503                               uint32_t *sclk_mask,
1504                               uint32_t *mclk_mask,
1505                               uint32_t *soc_mask)
1506 {
1507         struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1508         struct vega20_single_dpm_table *gfx_dpm_table;
1509         struct vega20_single_dpm_table *mem_dpm_table;
1510         struct vega20_single_dpm_table *soc_dpm_table;
1511
1512         if (!smu->smu_dpm.dpm_context)
1513                 return -EINVAL;
1514
1515         gfx_dpm_table = &dpm_table->gfx_table;
1516         mem_dpm_table = &dpm_table->mem_table;
1517         soc_dpm_table = &dpm_table->soc_table;
1518
1519         *sclk_mask = 0;
1520         *mclk_mask = 0;
1521         *soc_mask  = 0;
1522
1523         if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1524             mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1525             soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1526                 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1527                 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
1528                 *soc_mask  = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
1529         }
1530
1531         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1532                 *sclk_mask = 0;
1533         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1534                 *mclk_mask = 0;
1535         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1536                 *sclk_mask = gfx_dpm_table->count - 1;
1537                 *mclk_mask = mem_dpm_table->count - 1;
1538                 *soc_mask  = soc_dpm_table->count - 1;
1539         }
1540
1541         return 0;
1542 }
1543
1544 static int
1545 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
1546                                      struct vega20_single_dpm_table *dpm_table)
1547 {
1548         int ret = 0;
1549         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1550         if (!smu_dpm_ctx->dpm_context)
1551                 return -EINVAL;
1552
1553         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1554                 if (dpm_table->count <= 0) {
1555                         pr_err("[%s] Dpm table has no entry!", __func__);
1556                                 return -EINVAL;
1557                 }
1558
1559                 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
1560                         pr_err("[%s] Dpm table has too many entries!", __func__);
1561                                 return -EINVAL;
1562                 }
1563
1564                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1565                 ret = smu_send_smc_msg_with_param(smu,
1566                                 SMU_MSG_SetHardMinByFreq,
1567                                 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
1568                 if (ret) {
1569                         pr_err("[%s] Set hard min uclk failed!", __func__);
1570                                 return ret;
1571                 }
1572         }
1573
1574         return ret;
1575 }
1576
1577 static int vega20_pre_display_config_changed(struct smu_context *smu)
1578 {
1579         int ret = 0;
1580         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1581
1582         if (!smu->smu_dpm.dpm_context)
1583                 return -EINVAL;
1584
1585         smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
1586         ret = vega20_set_uclk_to_highest_dpm_level(smu,
1587                                                    &dpm_table->mem_table);
1588         if (ret)
1589                 pr_err("Failed to set uclk to highest dpm level");
1590         return ret;
1591 }
1592
1593 static int vega20_display_config_changed(struct smu_context *smu)
1594 {
1595         int ret = 0;
1596
1597         if (!smu->funcs)
1598                 return -EINVAL;
1599
1600         if (!smu->smu_dpm.dpm_context ||
1601             !smu->smu_table.tables ||
1602             !smu->smu_table.tables[TABLE_WATERMARKS].cpu_addr)
1603                 return -EINVAL;
1604
1605         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1606             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1607                 ret = smu->funcs->write_watermarks_table(smu);
1608                 if (ret) {
1609                         pr_err("Failed to update WMTABLE!");
1610                         return ret;
1611                 }
1612                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1613         }
1614
1615         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1616             smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT) &&
1617             smu_feature_is_supported(smu, FEATURE_DPM_SOCCLK_BIT)) {
1618                 smu_send_smc_msg_with_param(smu,
1619                                             SMU_MSG_NumOfDisplays,
1620                                             smu->display_config->num_display);
1621         }
1622
1623         return ret;
1624 }
1625
1626 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
1627 {
1628         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1629         struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
1630         struct vega20_single_dpm_table *dpm_table;
1631         bool vblank_too_short = false;
1632         bool disable_mclk_switching;
1633         uint32_t i, latency;
1634
1635         disable_mclk_switching = ((1 < smu->display_config->num_display) &&
1636                                   !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
1637         latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
1638
1639         /* gfxclk */
1640         dpm_table = &(dpm_ctx->gfx_table);
1641         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1642         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1643         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1644         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1645
1646                 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
1647                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1648                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1649                 }
1650
1651                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1652                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1653                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1654                 }
1655
1656                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1657                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1658                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1659                 }
1660
1661         /* memclk */
1662         dpm_table = &(dpm_ctx->mem_table);
1663         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1664         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1665         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1666         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1667
1668                 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
1669                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1670                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1671                 }
1672
1673                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1674                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1675                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
1676                 }
1677
1678                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1679                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1680                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1681                 }
1682
1683         /* honour DAL's UCLK Hardmin */
1684         if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
1685                 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
1686
1687         /* Hardmin is dependent on displayconfig */
1688         if (disable_mclk_switching) {
1689                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1690                 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
1691                         if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
1692                                 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
1693                                         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
1694                                         break;
1695                                 }
1696                         }
1697                 }
1698         }
1699
1700         if (smu->display_config->nb_pstate_switch_disable)
1701                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1702
1703         /* vclk */
1704         dpm_table = &(dpm_ctx->vclk_table);
1705         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1706         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1707         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1708         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1709
1710                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1711                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1712                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1713                 }
1714
1715                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1716                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1717                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1718                 }
1719
1720         /* dclk */
1721         dpm_table = &(dpm_ctx->dclk_table);
1722         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1723         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1724         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1725         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1726
1727                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
1728                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1729                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
1730                 }
1731
1732                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1733                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1734                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1735                 }
1736
1737         /* socclk */
1738         dpm_table = &(dpm_ctx->soc_table);
1739         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1740         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1741         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1742         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1743
1744                 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
1745                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1746                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
1747                 }
1748
1749                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1750                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1751                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1752                 }
1753
1754         /* eclk */
1755         dpm_table = &(dpm_ctx->eclk_table);
1756         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
1757         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1758         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
1759         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1760
1761                 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
1762                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1763                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
1764                 }
1765
1766                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1767                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1768                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
1769                 }
1770         return 0;
1771 }
1772
1773 static int
1774 vega20_notify_smc_dispaly_config(struct smu_context *smu)
1775 {
1776         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
1777         struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
1778         struct smu_clocks min_clocks = {0};
1779         struct pp_display_clock_request clock_req;
1780         int ret = 0;
1781
1782         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1783         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1784         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1785
1786         if (smu_feature_is_supported(smu, FEATURE_DPM_DCEFCLK_BIT)) {
1787                 clock_req.clock_type = amd_pp_dcef_clock;
1788                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1789                 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
1790                         if (smu_feature_is_supported(smu, FEATURE_DS_DCEFCLK_BIT)) {
1791                                 ret = smu_send_smc_msg_with_param(smu,
1792                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
1793                                                                   min_clocks.dcef_clock_in_sr/100);
1794                                 if (ret) {
1795                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
1796                                         return ret;
1797                                 }
1798                         }
1799                 } else {
1800                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1801                 }
1802         }
1803
1804         if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
1805                 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
1806                 ret = smu_send_smc_msg_with_param(smu,
1807                                                   SMU_MSG_SetHardMinByFreq,
1808                                                   (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
1809                 if (ret) {
1810                         pr_err("[%s] Set hard min uclk failed!", __func__);
1811                         return ret;
1812                 }
1813         }
1814
1815         return 0;
1816 }
1817
1818 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
1819 {
1820         uint32_t i;
1821
1822         for (i = 0; i < table->count; i++) {
1823                 if (table->dpm_levels[i].enabled)
1824                         break;
1825         }
1826         if (i >= table->count) {
1827                 i = 0;
1828                 table->dpm_levels[i].enabled = true;
1829         }
1830
1831         return i;
1832 }
1833
1834 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
1835 {
1836         int i = 0;
1837
1838         if (!table) {
1839                 pr_err("[%s] DPM Table does not exist!", __func__);
1840                 return 0;
1841         }
1842         if (table->count <= 0) {
1843                 pr_err("[%s] DPM Table has no entry!", __func__);
1844                 return 0;
1845         }
1846         if (table->count > MAX_REGULAR_DPM_NUMBER) {
1847                 pr_err("[%s] DPM Table has too many entries!", __func__);
1848                 return MAX_REGULAR_DPM_NUMBER - 1;
1849         }
1850
1851         for (i = table->count - 1; i >= 0; i--) {
1852                 if (table->dpm_levels[i].enabled)
1853                         break;
1854         }
1855         if (i < 0) {
1856                 i = 0;
1857                 table->dpm_levels[i].enabled = true;
1858         }
1859
1860         return i;
1861 }
1862
1863 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
1864 {
1865         uint32_t soft_level;
1866         int ret = 0;
1867         struct vega20_dpm_table *dpm_table =
1868                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1869
1870         if (highest)
1871                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1872         else
1873                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1874
1875         dpm_table->gfx_table.dpm_state.soft_min_level =
1876                 dpm_table->gfx_table.dpm_state.soft_max_level =
1877                 dpm_table->gfx_table.dpm_levels[soft_level].value;
1878
1879         if (highest)
1880                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1881         else
1882                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1883
1884         dpm_table->mem_table.dpm_state.soft_min_level =
1885                 dpm_table->mem_table.dpm_state.soft_max_level =
1886                 dpm_table->mem_table.dpm_levels[soft_level].value;
1887
1888         if (highest)
1889                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1890         else
1891                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1892
1893         dpm_table->soc_table.dpm_state.soft_min_level =
1894                 dpm_table->soc_table.dpm_state.soft_max_level =
1895                 dpm_table->soc_table.dpm_levels[soft_level].value;
1896
1897         ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
1898         if (ret) {
1899                 pr_err("Failed to upload boot level to %s!\n",
1900                                 highest ? "highest" : "lowest");
1901                 return ret;
1902         }
1903
1904         ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
1905         if (ret) {
1906                 pr_err("Failed to upload dpm max level to %s!\n!",
1907                                 highest ? "highest" : "lowest");
1908                 return ret;
1909         }
1910
1911         return ret;
1912 }
1913
1914 static int vega20_unforce_dpm_levels(struct smu_context *smu)
1915 {
1916         uint32_t soft_min_level, soft_max_level;
1917         int ret = 0;
1918         struct vega20_dpm_table *dpm_table =
1919                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1920
1921         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
1922         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
1923         dpm_table->gfx_table.dpm_state.soft_min_level =
1924                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1925         dpm_table->gfx_table.dpm_state.soft_max_level =
1926                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1927
1928         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
1929         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
1930         dpm_table->mem_table.dpm_state.soft_min_level =
1931                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
1932         dpm_table->mem_table.dpm_state.soft_max_level =
1933                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
1934
1935         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
1936         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
1937         dpm_table->soc_table.dpm_state.soft_min_level =
1938                 dpm_table->soc_table.dpm_levels[soft_min_level].value;
1939         dpm_table->soc_table.dpm_state.soft_max_level =
1940                 dpm_table->soc_table.dpm_levels[soft_max_level].value;
1941
1942         ret = smu_upload_dpm_level(smu, false, 0xFFFFFFFF);
1943         if (ret) {
1944                 pr_err("Failed to upload DPM Bootup Levels!");
1945                 return ret;
1946         }
1947
1948         ret = smu_upload_dpm_level(smu, true, 0xFFFFFFFF);
1949         if (ret) {
1950                 pr_err("Failed to upload DPM Max Levels!");
1951                 return ret;
1952         }
1953
1954         return ret;
1955 }
1956
1957 static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context *smu)
1958 {
1959         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1960         if (!smu_dpm_ctx->dpm_context)
1961                 return -EINVAL;
1962
1963         if (smu_dpm_ctx->dpm_level != smu_dpm_ctx->saved_dpm_level) {
1964                 mutex_lock(&(smu->mutex));
1965                 smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
1966                 mutex_unlock(&(smu->mutex));
1967         }
1968         return smu_dpm_ctx->dpm_level;
1969 }
1970
1971 static int
1972 vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1973 {
1974         int ret = 0;
1975         int i;
1976         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1977
1978         if (!smu_dpm_ctx->dpm_context)
1979                 return -EINVAL;
1980
1981         for (i = 0; i < smu->adev->num_ip_blocks; i++) {
1982                 if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
1983                         break;
1984         }
1985
1986         mutex_lock(&smu->mutex);
1987
1988         smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
1989         ret = smu_handle_task(smu, level,
1990                               AMD_PP_TASK_READJUST_POWER_STATE);
1991
1992         mutex_unlock(&smu->mutex);
1993
1994         return ret;
1995 }
1996
1997 static int vega20_update_specified_od8_value(struct smu_context *smu,
1998                                              uint32_t index,
1999                                              uint32_t value)
2000 {
2001         struct smu_table_context *table_context = &smu->smu_table;
2002         OverDriveTable_t *od_table =
2003                 (OverDriveTable_t *)(table_context->overdrive_table);
2004         struct vega20_od8_settings *od8_settings =
2005                 (struct vega20_od8_settings *)table_context->od8_settings;
2006
2007         switch (index) {
2008         case OD8_SETTING_GFXCLK_FMIN:
2009                 od_table->GfxclkFmin = (uint16_t)value;
2010                 break;
2011
2012         case OD8_SETTING_GFXCLK_FMAX:
2013                 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2014                     value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2015                         return -EINVAL;
2016                 od_table->GfxclkFmax = (uint16_t)value;
2017                 break;
2018
2019         case OD8_SETTING_GFXCLK_FREQ1:
2020                 od_table->GfxclkFreq1 = (uint16_t)value;
2021                 break;
2022
2023         case OD8_SETTING_GFXCLK_VOLTAGE1:
2024                 od_table->GfxclkVolt1 = (uint16_t)value;
2025                 break;
2026
2027         case OD8_SETTING_GFXCLK_FREQ2:
2028                 od_table->GfxclkFreq2 = (uint16_t)value;
2029                 break;
2030
2031         case OD8_SETTING_GFXCLK_VOLTAGE2:
2032                 od_table->GfxclkVolt2 = (uint16_t)value;
2033                 break;
2034
2035         case OD8_SETTING_GFXCLK_FREQ3:
2036                 od_table->GfxclkFreq3 = (uint16_t)value;
2037                 break;
2038
2039         case OD8_SETTING_GFXCLK_VOLTAGE3:
2040                 od_table->GfxclkVolt3 = (uint16_t)value;
2041                 break;
2042
2043         case OD8_SETTING_UCLK_FMAX:
2044                 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2045                     value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2046                         return -EINVAL;
2047                 od_table->UclkFmax = (uint16_t)value;
2048                 break;
2049
2050         case OD8_SETTING_POWER_PERCENTAGE:
2051                 od_table->OverDrivePct = (int16_t)value;
2052                 break;
2053
2054         case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2055                 od_table->FanMaximumRpm = (uint16_t)value;
2056                 break;
2057
2058         case OD8_SETTING_FAN_MIN_SPEED:
2059                 od_table->FanMinimumPwm = (uint16_t)value;
2060                 break;
2061
2062         case OD8_SETTING_FAN_TARGET_TEMP:
2063                 od_table->FanTargetTemperature = (uint16_t)value;
2064                 break;
2065
2066         case OD8_SETTING_OPERATING_TEMP_MAX:
2067                 od_table->MaxOpTemp = (uint16_t)value;
2068                 break;
2069         }
2070
2071         return 0;
2072 }
2073
2074 static int vega20_set_od_percentage(struct smu_context *smu,
2075                                     enum pp_clock_type type,
2076                                     uint32_t value)
2077 {
2078         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2079         struct vega20_dpm_table *dpm_table = NULL;
2080         struct vega20_dpm_table *golden_table = NULL;
2081         struct vega20_single_dpm_table *single_dpm_table;
2082         struct vega20_single_dpm_table *golden_dpm_table;
2083         uint32_t od_clk, index;
2084         int ret = 0;
2085         int feature_enabled;
2086         PPCLK_e clk_id;
2087
2088         mutex_lock(&(smu->mutex));
2089
2090         dpm_table = smu_dpm->dpm_context;
2091         golden_table = smu_dpm->golden_dpm_context;
2092
2093         switch (type) {
2094         case OD_SCLK:
2095                 single_dpm_table = &(dpm_table->gfx_table);
2096                 golden_dpm_table = &(golden_table->gfx_table);
2097                 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT);
2098                 clk_id = PPCLK_GFXCLK;
2099                 index = OD8_SETTING_GFXCLK_FMAX;
2100                 break;
2101         case OD_MCLK:
2102                 single_dpm_table = &(dpm_table->mem_table);
2103                 golden_dpm_table = &(golden_table->mem_table);
2104                 feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT);
2105                 clk_id = PPCLK_UCLK;
2106                 index = OD8_SETTING_UCLK_FMAX;
2107                 break;
2108         default:
2109                 ret = -EINVAL;
2110                 break;
2111         }
2112
2113         if (ret)
2114                 goto set_od_failed;
2115
2116         od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2117         od_clk /= 100;
2118         od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2119
2120         ret = smu_update_od8_settings(smu, index, od_clk);
2121         if (ret) {
2122                 pr_err("[Setoverdrive] failed to set od clk!\n");
2123                 goto set_od_failed;
2124         }
2125
2126         if (feature_enabled) {
2127                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2128                                                   clk_id);
2129                 if (ret) {
2130                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2131                         goto set_od_failed;
2132                 }
2133         } else {
2134                 single_dpm_table->count = 1;
2135                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2136         }
2137
2138         ret = smu_handle_task(smu, smu_dpm->dpm_level,
2139                               AMD_PP_TASK_READJUST_POWER_STATE);
2140
2141 set_od_failed:
2142         mutex_unlock(&(smu->mutex));
2143
2144         return ret;
2145 }
2146
2147 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2148                                      enum PP_OD_DPM_TABLE_COMMAND type,
2149                                      long *input, uint32_t size)
2150 {
2151         struct smu_table_context *table_context = &smu->smu_table;
2152         OverDriveTable_t *od_table =
2153                 (OverDriveTable_t *)(table_context->overdrive_table);
2154         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2155         struct vega20_dpm_table *dpm_table = NULL;
2156         struct vega20_single_dpm_table *single_dpm_table;
2157         struct vega20_od8_settings *od8_settings =
2158                 (struct vega20_od8_settings *)table_context->od8_settings;
2159         struct pp_clock_levels_with_latency clocks;
2160         int32_t input_index, input_clk, input_vol, i;
2161         int od8_id;
2162         int ret = 0;
2163
2164         dpm_table = smu_dpm->dpm_context;
2165
2166         if (!input) {
2167                 pr_warn("NULL user input for clock and voltage\n");
2168                 return -EINVAL;
2169         }
2170
2171         switch (type) {
2172         case PP_OD_EDIT_SCLK_VDDC_TABLE:
2173                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2174                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2175                         pr_info("Sclk min/max frequency overdrive not supported\n");
2176                         return -EOPNOTSUPP;
2177                 }
2178
2179                 for (i = 0; i < size; i += 2) {
2180                         if (i + 2 > size) {
2181                                 pr_info("invalid number of input parameters %d\n", size);
2182                                 return -EINVAL;
2183                         }
2184
2185                         input_index = input[i];
2186                         input_clk = input[i + 1];
2187
2188                         if (input_index != 0 && input_index != 1) {
2189                                 pr_info("Invalid index %d\n", input_index);
2190                                 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2191                                 return -EINVAL;
2192                         }
2193
2194                         if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2195                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2196                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2197                                         input_clk,
2198                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2199                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2200                                 return -EINVAL;
2201                         }
2202
2203                         if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2204                                 od_table->GfxclkFmin = input_clk;
2205                                 table_context->od_gfxclk_update = true;
2206                         } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2207                                 od_table->GfxclkFmax = input_clk;
2208                                 table_context->od_gfxclk_update = true;
2209                         }
2210                 }
2211
2212                 break;
2213
2214         case PP_OD_EDIT_MCLK_VDDC_TABLE:
2215                 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2216                         pr_info("Mclk max frequency overdrive not supported\n");
2217                         return -EOPNOTSUPP;
2218                 }
2219
2220                 single_dpm_table = &(dpm_table->mem_table);
2221                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2222                 if (ret) {
2223                         pr_err("Attempt to get memory clk levels Failed!");
2224                         return ret;
2225                 }
2226
2227                 for (i = 0; i < size; i += 2) {
2228                         if (i + 2 > size) {
2229                                 pr_info("invalid number of input parameters %d\n",
2230                                          size);
2231                                 return -EINVAL;
2232                         }
2233
2234                         input_index = input[i];
2235                         input_clk = input[i + 1];
2236
2237                         if (input_index != 1) {
2238                                 pr_info("Invalid index %d\n", input_index);
2239                                 pr_info("Support max Mclk frequency setting only which index by 1\n");
2240                                 return -EINVAL;
2241                         }
2242
2243                         if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2244                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2245                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2246                                         input_clk,
2247                                         clocks.data[0].clocks_in_khz / 1000,
2248                                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2249                                 return -EINVAL;
2250                         }
2251
2252                         if (input_index == 1 && od_table->UclkFmax != input_clk) {
2253                                 table_context->od_gfxclk_update = true;
2254                                 od_table->UclkFmax = input_clk;
2255                         }
2256                 }
2257
2258                 break;
2259
2260         case PP_OD_EDIT_VDDC_CURVE:
2261                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2262                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2263                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2264                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2265                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2266                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2267                         pr_info("Voltage curve calibrate not supported\n");
2268                         return -EOPNOTSUPP;
2269                 }
2270
2271                 for (i = 0; i < size; i += 3) {
2272                         if (i + 3 > size) {
2273                                 pr_info("invalid number of input parameters %d\n",
2274                                         size);
2275                                 return -EINVAL;
2276                         }
2277
2278                         input_index = input[i];
2279                         input_clk = input[i + 1];
2280                         input_vol = input[i + 2];
2281
2282                         if (input_index > 2) {
2283                                 pr_info("Setting for point %d is not supported\n",
2284                                         input_index + 1);
2285                                 pr_info("Three supported points index by 0, 1, 2\n");
2286                                 return -EINVAL;
2287                         }
2288
2289                         od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2290                         if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2291                             input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2292                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2293                                         input_clk,
2294                                         od8_settings->od8_settings_array[od8_id].min_value,
2295                                         od8_settings->od8_settings_array[od8_id].max_value);
2296                                 return -EINVAL;
2297                         }
2298
2299                         od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2300                         if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2301                             input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2302                                 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2303                                         input_vol,
2304                                         od8_settings->od8_settings_array[od8_id].min_value,
2305                                         od8_settings->od8_settings_array[od8_id].max_value);
2306                                 return -EINVAL;
2307                         }
2308
2309                         switch (input_index) {
2310                         case 0:
2311                                 od_table->GfxclkFreq1 = input_clk;
2312                                 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2313                                 break;
2314                         case 1:
2315                                 od_table->GfxclkFreq2 = input_clk;
2316                                 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2317                                 break;
2318                         case 2:
2319                                 od_table->GfxclkFreq3 = input_clk;
2320                                 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2321                                 break;
2322                         }
2323                 }
2324
2325                 break;
2326
2327         case PP_OD_RESTORE_DEFAULT_TABLE:
2328                 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false);
2329                 if (ret) {
2330                         pr_err("Failed to export over drive table!\n");
2331                         return ret;
2332                 }
2333
2334                 break;
2335
2336         case PP_OD_COMMIT_DPM_TABLE:
2337                 ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true);
2338                 if (ret) {
2339                         pr_err("Failed to import over drive table!\n");
2340                         return ret;
2341                 }
2342
2343                 /* retrieve updated gfxclk table */
2344                 if (table_context->od_gfxclk_update) {
2345                         table_context->od_gfxclk_update = false;
2346                         single_dpm_table = &(dpm_table->gfx_table);
2347
2348                         if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) {
2349                                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2350                                                                   PPCLK_GFXCLK);
2351                                 if (ret) {
2352                                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2353                                         return ret;
2354                                 }
2355                         } else {
2356                                 single_dpm_table->count = 1;
2357                                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2358                         }
2359                 }
2360
2361                 break;
2362
2363         default:
2364                 return -EINVAL;
2365         }
2366
2367         if (type == PP_OD_COMMIT_DPM_TABLE) {
2368                 mutex_lock(&(smu->mutex));
2369                 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2370                                       AMD_PP_TASK_READJUST_POWER_STATE);
2371                 mutex_unlock(&(smu->mutex));
2372         }
2373
2374         return ret;
2375 }
2376
2377 static const struct pptable_funcs vega20_ppt_funcs = {
2378         .alloc_dpm_context = vega20_allocate_dpm_context,
2379         .store_powerplay_table = vega20_store_powerplay_table,
2380         .check_powerplay_table = vega20_check_powerplay_table,
2381         .append_powerplay_table = vega20_append_powerplay_table,
2382         .get_smu_msg_index = vega20_get_smu_msg_index,
2383         .run_afll_btc = vega20_run_btc_afll,
2384         .get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
2385         .get_current_power_state = vega20_get_current_power_state,
2386         .set_default_dpm_table = vega20_set_default_dpm_table,
2387         .set_power_state = NULL,
2388         .populate_umd_state_clk = vega20_populate_umd_state_clk,
2389         .print_clk_levels = vega20_print_clk_levels,
2390         .force_clk_levels = vega20_force_clk_levels,
2391         .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
2392         .set_default_od8_settings = vega20_set_default_od8_setttings,
2393         .get_od_percentage = vega20_get_od_percentage,
2394         .get_performance_level = vega20_get_performance_level,
2395         .force_performance_level = vega20_force_performance_level,
2396         .update_specified_od8_value = vega20_update_specified_od8_value,
2397         .set_od_percentage = vega20_set_od_percentage,
2398         .od_edit_dpm_table = vega20_odn_edit_dpm_table,
2399         .pre_display_config_changed = vega20_pre_display_config_changed,
2400         .display_config_changed = vega20_display_config_changed,
2401         .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
2402         .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
2403         .force_dpm_limit_value = vega20_force_dpm_limit_value,
2404         .unforce_dpm_levels = vega20_unforce_dpm_levels,
2405         .upload_dpm_level = vega20_upload_dpm_level,
2406         .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
2407 };
2408
2409 void vega20_set_ppt_funcs(struct smu_context *smu)
2410 {
2411         smu->ppt_funcs = &vega20_ppt_funcs;
2412         smu->smc_if_version = SMU11_DRIVER_IF_VERSION;
2413 }