]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/vega20_ppt.c
Merge tag 'juno-fixes-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep...
[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 #include "asic_reg/thm/thm_11_0_2_offset.h"
40 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
41
42 #define smnPCIE_LC_SPEED_CNTL                   0x11140290
43 #define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
44
45 #define CTF_OFFSET_EDGE                 5
46 #define CTF_OFFSET_HOTSPOT              5
47 #define CTF_OFFSET_HBM                  5
48
49 #define MSG_MAP(msg) \
50         [SMU_MSG_##msg] = {1, PPSMC_MSG_##msg}
51
52 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
53                          FEATURE_DPM_GFXCLK_MASK | \
54                          FEATURE_DPM_UCLK_MASK | \
55                          FEATURE_DPM_SOCCLK_MASK | \
56                          FEATURE_DPM_UVD_MASK | \
57                          FEATURE_DPM_VCE_MASK | \
58                          FEATURE_DPM_MP0CLK_MASK | \
59                          FEATURE_DPM_LINK_MASK | \
60                          FEATURE_DPM_DCEFCLK_MASK)
61
62 static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] = {
63         MSG_MAP(TestMessage),
64         MSG_MAP(GetSmuVersion),
65         MSG_MAP(GetDriverIfVersion),
66         MSG_MAP(SetAllowedFeaturesMaskLow),
67         MSG_MAP(SetAllowedFeaturesMaskHigh),
68         MSG_MAP(EnableAllSmuFeatures),
69         MSG_MAP(DisableAllSmuFeatures),
70         MSG_MAP(EnableSmuFeaturesLow),
71         MSG_MAP(EnableSmuFeaturesHigh),
72         MSG_MAP(DisableSmuFeaturesLow),
73         MSG_MAP(DisableSmuFeaturesHigh),
74         MSG_MAP(GetEnabledSmuFeaturesLow),
75         MSG_MAP(GetEnabledSmuFeaturesHigh),
76         MSG_MAP(SetWorkloadMask),
77         MSG_MAP(SetPptLimit),
78         MSG_MAP(SetDriverDramAddrHigh),
79         MSG_MAP(SetDriverDramAddrLow),
80         MSG_MAP(SetToolsDramAddrHigh),
81         MSG_MAP(SetToolsDramAddrLow),
82         MSG_MAP(TransferTableSmu2Dram),
83         MSG_MAP(TransferTableDram2Smu),
84         MSG_MAP(UseDefaultPPTable),
85         MSG_MAP(UseBackupPPTable),
86         MSG_MAP(RunBtc),
87         MSG_MAP(RequestI2CBus),
88         MSG_MAP(ReleaseI2CBus),
89         MSG_MAP(SetFloorSocVoltage),
90         MSG_MAP(SoftReset),
91         MSG_MAP(StartBacoMonitor),
92         MSG_MAP(CancelBacoMonitor),
93         MSG_MAP(EnterBaco),
94         MSG_MAP(SetSoftMinByFreq),
95         MSG_MAP(SetSoftMaxByFreq),
96         MSG_MAP(SetHardMinByFreq),
97         MSG_MAP(SetHardMaxByFreq),
98         MSG_MAP(GetMinDpmFreq),
99         MSG_MAP(GetMaxDpmFreq),
100         MSG_MAP(GetDpmFreqByIndex),
101         MSG_MAP(GetDpmClockFreq),
102         MSG_MAP(GetSsVoltageByDpm),
103         MSG_MAP(SetMemoryChannelConfig),
104         MSG_MAP(SetGeminiMode),
105         MSG_MAP(SetGeminiApertureHigh),
106         MSG_MAP(SetGeminiApertureLow),
107         MSG_MAP(SetMinLinkDpmByIndex),
108         MSG_MAP(OverridePcieParameters),
109         MSG_MAP(OverDriveSetPercentage),
110         MSG_MAP(SetMinDeepSleepDcefclk),
111         MSG_MAP(ReenableAcDcInterrupt),
112         MSG_MAP(NotifyPowerSource),
113         MSG_MAP(SetUclkFastSwitch),
114         MSG_MAP(SetUclkDownHyst),
115         MSG_MAP(GetCurrentRpm),
116         MSG_MAP(SetVideoFps),
117         MSG_MAP(SetTjMax),
118         MSG_MAP(SetFanTemperatureTarget),
119         MSG_MAP(PrepareMp1ForUnload),
120         MSG_MAP(DramLogSetDramAddrHigh),
121         MSG_MAP(DramLogSetDramAddrLow),
122         MSG_MAP(DramLogSetDramSize),
123         MSG_MAP(SetFanMaxRpm),
124         MSG_MAP(SetFanMinPwm),
125         MSG_MAP(ConfigureGfxDidt),
126         MSG_MAP(NumOfDisplays),
127         MSG_MAP(RemoveMargins),
128         MSG_MAP(ReadSerialNumTop32),
129         MSG_MAP(ReadSerialNumBottom32),
130         MSG_MAP(SetSystemVirtualDramAddrHigh),
131         MSG_MAP(SetSystemVirtualDramAddrLow),
132         MSG_MAP(WaflTest),
133         MSG_MAP(SetFclkGfxClkRatio),
134         MSG_MAP(AllowGfxOff),
135         MSG_MAP(DisallowGfxOff),
136         MSG_MAP(GetPptLimit),
137         MSG_MAP(GetDcModeMaxDpmFreq),
138         MSG_MAP(GetDebugData),
139         MSG_MAP(SetXgmiMode),
140         MSG_MAP(RunAfllBtc),
141         MSG_MAP(ExitBaco),
142         MSG_MAP(PrepareMp1ForReset),
143         MSG_MAP(PrepareMp1ForShutdown),
144         MSG_MAP(SetMGpuFanBoostLimitRpm),
145         MSG_MAP(GetAVFSVoltageByDpm),
146 };
147
148 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = {
149         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
150         CLK_MAP(VCLK, PPCLK_VCLK),
151         CLK_MAP(DCLK, PPCLK_DCLK),
152         CLK_MAP(ECLK, PPCLK_ECLK),
153         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
154         CLK_MAP(UCLK, PPCLK_UCLK),
155         CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
156         CLK_MAP(DISPCLK, PPCLK_DISPCLK),
157         CLK_MAP(PIXCLK, PPCLK_PIXCLK),
158         CLK_MAP(PHYCLK, PPCLK_PHYCLK),
159         CLK_MAP(FCLK, PPCLK_FCLK),
160 };
161
162 static struct smu_11_0_cmn2aisc_mapping vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
163         FEA_MAP(DPM_PREFETCHER),
164         FEA_MAP(DPM_GFXCLK),
165         FEA_MAP(DPM_UCLK),
166         FEA_MAP(DPM_SOCCLK),
167         FEA_MAP(DPM_UVD),
168         FEA_MAP(DPM_VCE),
169         FEA_MAP(ULV),
170         FEA_MAP(DPM_MP0CLK),
171         FEA_MAP(DPM_LINK),
172         FEA_MAP(DPM_DCEFCLK),
173         FEA_MAP(DS_GFXCLK),
174         FEA_MAP(DS_SOCCLK),
175         FEA_MAP(DS_LCLK),
176         FEA_MAP(PPT),
177         FEA_MAP(TDC),
178         FEA_MAP(THERMAL),
179         FEA_MAP(GFX_PER_CU_CG),
180         FEA_MAP(RM),
181         FEA_MAP(DS_DCEFCLK),
182         FEA_MAP(ACDC),
183         FEA_MAP(VR0HOT),
184         FEA_MAP(VR1HOT),
185         FEA_MAP(FW_CTF),
186         FEA_MAP(LED_DISPLAY),
187         FEA_MAP(FAN_CONTROL),
188         FEA_MAP(GFX_EDC),
189         FEA_MAP(GFXOFF),
190         FEA_MAP(CG),
191         FEA_MAP(DPM_FCLK),
192         FEA_MAP(DS_FCLK),
193         FEA_MAP(DS_MP1CLK),
194         FEA_MAP(DS_MP0CLK),
195         FEA_MAP(XGMI),
196 };
197
198 static struct smu_11_0_cmn2aisc_mapping vega20_table_map[SMU_TABLE_COUNT] = {
199         TAB_MAP(PPTABLE),
200         TAB_MAP(WATERMARKS),
201         TAB_MAP(AVFS),
202         TAB_MAP(AVFS_PSM_DEBUG),
203         TAB_MAP(AVFS_FUSE_OVERRIDE),
204         TAB_MAP(PMSTATUSLOG),
205         TAB_MAP(SMU_METRICS),
206         TAB_MAP(DRIVER_SMU_CONFIG),
207         TAB_MAP(ACTIVITY_MONITOR_COEFF),
208         TAB_MAP(OVERDRIVE),
209 };
210
211 static struct smu_11_0_cmn2aisc_mapping vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
212         PWR_MAP(AC),
213         PWR_MAP(DC),
214 };
215
216 static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
217         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_DEFAULT_BIT),
218         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
219         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
220         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
221         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
222         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_CUSTOM_BIT),
223         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
224 };
225
226 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
227 {
228         struct smu_11_0_cmn2aisc_mapping mapping;
229
230         if (index >= SMU_TABLE_COUNT)
231                 return -EINVAL;
232
233         mapping = vega20_table_map[index];
234         if (!(mapping.valid_mapping)) {
235                 return -EINVAL;
236         }
237
238         return mapping.map_to;
239 }
240
241 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
242 {
243         struct smu_11_0_cmn2aisc_mapping mapping;
244
245         if (index >= SMU_POWER_SOURCE_COUNT)
246                 return -EINVAL;
247
248         mapping = vega20_pwr_src_map[index];
249         if (!(mapping.valid_mapping)) {
250                 return -EINVAL;
251         }
252
253         return mapping.map_to;
254 }
255
256 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
257 {
258         struct smu_11_0_cmn2aisc_mapping mapping;
259
260         if (index >= SMU_FEATURE_COUNT)
261                 return -EINVAL;
262
263         mapping = vega20_feature_mask_map[index];
264         if (!(mapping.valid_mapping)) {
265                 return -EINVAL;
266         }
267
268         return mapping.map_to;
269 }
270
271 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
272 {
273         struct smu_11_0_cmn2aisc_mapping mapping;
274
275         if (index >= SMU_CLK_COUNT)
276                 return -EINVAL;
277
278         mapping = vega20_clk_map[index];
279         if (!(mapping.valid_mapping)) {
280                 return -EINVAL;
281         }
282
283         return mapping.map_to;
284 }
285
286 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
287 {
288         struct smu_11_0_cmn2aisc_mapping mapping;
289
290         if (index >= SMU_MSG_MAX_COUNT)
291                 return -EINVAL;
292
293         mapping = vega20_message_map[index];
294         if (!(mapping.valid_mapping)) {
295                 return -EINVAL;
296         }
297
298         return mapping.map_to;
299 }
300
301 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
302 {
303         struct smu_11_0_cmn2aisc_mapping mapping;
304
305         if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
306                 return -EINVAL;
307
308         mapping = vega20_workload_map[profile];
309         if (!(mapping.valid_mapping)) {
310                 return -EINVAL;
311         }
312
313         return mapping.map_to;
314 }
315
316 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
317 {
318         struct smu_table_context *smu_table = &smu->smu_table;
319
320         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
321                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
322         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
323                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
324         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
325                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
326         SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
327                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
328         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
329                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
330         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
331                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
332                        AMDGPU_GEM_DOMAIN_VRAM);
333
334         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
335         if (!smu_table->metrics_table)
336                 return -ENOMEM;
337         smu_table->metrics_time = 0;
338
339         return 0;
340 }
341
342 static int vega20_allocate_dpm_context(struct smu_context *smu)
343 {
344         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
345
346         if (smu_dpm->dpm_context)
347                 return -EINVAL;
348
349         smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
350                                        GFP_KERNEL);
351         if (!smu_dpm->dpm_context)
352                 return -ENOMEM;
353
354         if (smu_dpm->golden_dpm_context)
355                 return -EINVAL;
356
357         smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
358                                               GFP_KERNEL);
359         if (!smu_dpm->golden_dpm_context)
360                 return -ENOMEM;
361
362         smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
363
364         smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
365                                        GFP_KERNEL);
366         if (!smu_dpm->dpm_current_power_state)
367                 return -ENOMEM;
368
369         smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
370                                        GFP_KERNEL);
371         if (!smu_dpm->dpm_request_power_state)
372                 return -ENOMEM;
373
374         return 0;
375 }
376
377 static int vega20_setup_od8_information(struct smu_context *smu)
378 {
379         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
380         struct smu_table_context *table_context = &smu->smu_table;
381         struct vega20_od8_settings *od8_settings = (struct vega20_od8_settings *)smu->od_settings;
382
383         uint32_t od_feature_count, od_feature_array_size,
384                  od_setting_count, od_setting_array_size;
385
386         if (!table_context->power_play_table)
387                 return -EINVAL;
388
389         powerplay_table = table_context->power_play_table;
390
391         if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
392                 /* Setup correct ODFeatureCount, and store ODFeatureArray from
393                  * powerplay table to od_feature_capabilities */
394                 od_feature_count =
395                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
396                          ATOM_VEGA20_ODFEATURE_COUNT) ?
397                         ATOM_VEGA20_ODFEATURE_COUNT :
398                         le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
399
400                 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
401
402                 if (od8_settings->od_feature_capabilities)
403                         return -EINVAL;
404
405                 od8_settings->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
406                                                                  od_feature_array_size,
407                                                                  GFP_KERNEL);
408                 if (!od8_settings->od_feature_capabilities)
409                         return -ENOMEM;
410
411                 /* Setup correct ODSettingCount, and store ODSettingArray from
412                  * powerplay table to od_settings_max and od_setting_min */
413                 od_setting_count =
414                         (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
415                          ATOM_VEGA20_ODSETTING_COUNT) ?
416                         ATOM_VEGA20_ODSETTING_COUNT :
417                         le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
418
419                 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
420
421                 if (od8_settings->od_settings_max)
422                         return -EINVAL;
423
424                 od8_settings->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
425                                                          od_setting_array_size,
426                                                          GFP_KERNEL);
427
428                 if (!od8_settings->od_settings_max) {
429                         kfree(od8_settings->od_feature_capabilities);
430                         od8_settings->od_feature_capabilities = NULL;
431                         return -ENOMEM;
432                 }
433
434                 if (od8_settings->od_settings_min)
435                         return -EINVAL;
436
437                 od8_settings->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
438                                                          od_setting_array_size,
439                                                          GFP_KERNEL);
440
441                 if (!od8_settings->od_settings_min) {
442                         kfree(od8_settings->od_feature_capabilities);
443                         od8_settings->od_feature_capabilities = NULL;
444                         kfree(od8_settings->od_settings_max);
445                         od8_settings->od_settings_max = NULL;
446                         return -ENOMEM;
447                 }
448         }
449
450         return 0;
451 }
452
453 static int vega20_store_powerplay_table(struct smu_context *smu)
454 {
455         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
456         struct smu_table_context *table_context = &smu->smu_table;
457
458         if (!table_context->power_play_table)
459                 return -EINVAL;
460
461         powerplay_table = table_context->power_play_table;
462
463         memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
464                sizeof(PPTable_t));
465
466         table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
467         table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
468
469         return 0;
470 }
471
472 static int vega20_append_powerplay_table(struct smu_context *smu)
473 {
474         struct smu_table_context *table_context = &smu->smu_table;
475         PPTable_t *smc_pptable = table_context->driver_pptable;
476         struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
477         int index, i, ret;
478
479         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
480                                            smc_dpm_info);
481
482         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
483                                       (uint8_t **)&smc_dpm_table);
484         if (ret)
485                 return ret;
486
487         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
488         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
489
490         smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
491         smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
492         smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
493         smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
494
495         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
496         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
497         smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
498
499         smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
500         smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
501         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
502
503         smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
504         smc_pptable->SocOffset = smc_dpm_table->socoffset;
505         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
506
507         smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
508         smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
509         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
510
511         smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
512         smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
513         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
514
515         smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
516         smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
517         smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
518         smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
519
520         smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
521         smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
522         smc_pptable->Padding1 = smc_dpm_table->padding1;
523         smc_pptable->Padding2 = smc_dpm_table->padding2;
524
525         smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
526         smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
527         smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
528
529         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
530         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
531         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
532
533         smc_pptable->UclkSpreadEnabled = 0;
534         smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
535         smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
536
537         smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
538         smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
539         smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
540
541         smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
542         smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
543         smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
544
545         for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
546                 smc_pptable->I2cControllers[i].Enabled =
547                         smc_dpm_table->i2ccontrollers[i].enabled;
548                 smc_pptable->I2cControllers[i].SlaveAddress =
549                         smc_dpm_table->i2ccontrollers[i].slaveaddress;
550                 smc_pptable->I2cControllers[i].ControllerPort =
551                         smc_dpm_table->i2ccontrollers[i].controllerport;
552                 smc_pptable->I2cControllers[i].ThermalThrottler =
553                         smc_dpm_table->i2ccontrollers[i].thermalthrottler;
554                 smc_pptable->I2cControllers[i].I2cProtocol =
555                         smc_dpm_table->i2ccontrollers[i].i2cprotocol;
556                 smc_pptable->I2cControllers[i].I2cSpeed =
557                         smc_dpm_table->i2ccontrollers[i].i2cspeed;
558         }
559
560         return 0;
561 }
562
563 static int vega20_check_powerplay_table(struct smu_context *smu)
564 {
565         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
566         struct smu_table_context *table_context = &smu->smu_table;
567
568         powerplay_table = table_context->power_play_table;
569
570         if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
571                 pr_err("Unsupported PPTable format!");
572                 return -EINVAL;
573         }
574
575         if (!powerplay_table->sHeader.structuresize) {
576                 pr_err("Invalid PowerPlay Table!");
577                 return -EINVAL;
578         }
579
580         return 0;
581 }
582
583 static int vega20_run_btc_afll(struct smu_context *smu)
584 {
585         return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
586 }
587
588 #define FEATURE_MASK(feature) (1ULL << feature)
589 static int
590 vega20_get_allowed_feature_mask(struct smu_context *smu,
591                                   uint32_t *feature_mask, uint32_t num)
592 {
593         if (num > 2)
594                 return -EINVAL;
595
596         memset(feature_mask, 0, sizeof(uint32_t) * num);
597
598         *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
599                                 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
600                                 | FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
601                                 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
602                                 | FEATURE_MASK(FEATURE_DPM_UVD_BIT)
603                                 | FEATURE_MASK(FEATURE_DPM_VCE_BIT)
604                                 | FEATURE_MASK(FEATURE_ULV_BIT)
605                                 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
606                                 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
607                                 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
608                                 | FEATURE_MASK(FEATURE_PPT_BIT)
609                                 | FEATURE_MASK(FEATURE_TDC_BIT)
610                                 | FEATURE_MASK(FEATURE_THERMAL_BIT)
611                                 | FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT)
612                                 | FEATURE_MASK(FEATURE_RM_BIT)
613                                 | FEATURE_MASK(FEATURE_ACDC_BIT)
614                                 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
615                                 | FEATURE_MASK(FEATURE_VR1HOT_BIT)
616                                 | FEATURE_MASK(FEATURE_FW_CTF_BIT)
617                                 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
618                                 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
619                                 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
620                                 | FEATURE_MASK(FEATURE_GFXOFF_BIT)
621                                 | FEATURE_MASK(FEATURE_CG_BIT)
622                                 | FEATURE_MASK(FEATURE_DPM_FCLK_BIT)
623                                 | FEATURE_MASK(FEATURE_XGMI_BIT);
624         return 0;
625 }
626
627 static enum
628 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
629 {
630         enum amd_pm_state_type pm_type;
631         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
632
633         if (!smu_dpm_ctx->dpm_context ||
634             !smu_dpm_ctx->dpm_current_power_state)
635                 return -EINVAL;
636
637         mutex_lock(&(smu->mutex));
638         switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
639         case SMU_STATE_UI_LABEL_BATTERY:
640                 pm_type = POWER_STATE_TYPE_BATTERY;
641                 break;
642         case SMU_STATE_UI_LABEL_BALLANCED:
643                 pm_type = POWER_STATE_TYPE_BALANCED;
644                 break;
645         case SMU_STATE_UI_LABEL_PERFORMANCE:
646                 pm_type = POWER_STATE_TYPE_PERFORMANCE;
647                 break;
648         default:
649                 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
650                         pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
651                 else
652                         pm_type = POWER_STATE_TYPE_DEFAULT;
653                 break;
654         }
655         mutex_unlock(&(smu->mutex));
656
657         return pm_type;
658 }
659
660 static int
661 vega20_set_single_dpm_table(struct smu_context *smu,
662                             struct vega20_single_dpm_table *single_dpm_table,
663                             PPCLK_e clk_id)
664 {
665         int ret = 0;
666         uint32_t i, num_of_levels = 0, clk;
667
668         ret = smu_send_smc_msg_with_param(smu,
669                         SMU_MSG_GetDpmFreqByIndex,
670                         (clk_id << 16 | 0xFF));
671         if (ret) {
672                 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
673                 return ret;
674         }
675
676         smu_read_smc_arg(smu, &num_of_levels);
677         if (!num_of_levels) {
678                 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
679                 return -EINVAL;
680         }
681
682         single_dpm_table->count = num_of_levels;
683
684         for (i = 0; i < num_of_levels; i++) {
685                 ret = smu_send_smc_msg_with_param(smu,
686                                 SMU_MSG_GetDpmFreqByIndex,
687                                 (clk_id << 16 | i));
688                 if (ret) {
689                         pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
690                         return ret;
691                 }
692                 smu_read_smc_arg(smu, &clk);
693                 if (!clk) {
694                         pr_err("[GetDpmFreqByIndex] clk value is invalid!");
695                         return -EINVAL;
696                 }
697                 single_dpm_table->dpm_levels[i].value = clk;
698                 single_dpm_table->dpm_levels[i].enabled = true;
699         }
700         return 0;
701 }
702
703 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
704 {
705         dpm_state->soft_min_level = 0x0;
706         dpm_state->soft_max_level = 0xffff;
707         dpm_state->hard_min_level = 0x0;
708         dpm_state->hard_max_level = 0xffff;
709 }
710
711 static int vega20_set_default_dpm_table(struct smu_context *smu)
712 {
713         int ret;
714
715         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
716         struct vega20_dpm_table *dpm_table = NULL;
717         struct vega20_single_dpm_table *single_dpm_table;
718
719         dpm_table = smu_dpm->dpm_context;
720
721         /* socclk */
722         single_dpm_table = &(dpm_table->soc_table);
723
724         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
725                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
726                                                   PPCLK_SOCCLK);
727                 if (ret) {
728                         pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
729                         return ret;
730                 }
731         } else {
732                 single_dpm_table->count = 1;
733                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
734         }
735         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
736
737         /* gfxclk */
738         single_dpm_table = &(dpm_table->gfx_table);
739
740         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
741                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
742                                                   PPCLK_GFXCLK);
743                 if (ret) {
744                         pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
745                         return ret;
746                 }
747         } else {
748                 single_dpm_table->count = 1;
749                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
750         }
751         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
752
753         /* memclk */
754         single_dpm_table = &(dpm_table->mem_table);
755
756         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
757                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
758                                                   PPCLK_UCLK);
759                 if (ret) {
760                         pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
761                         return ret;
762                 }
763         } else {
764                 single_dpm_table->count = 1;
765                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
766         }
767         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
768
769         /* eclk */
770         single_dpm_table = &(dpm_table->eclk_table);
771
772         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) {
773                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
774                 if (ret) {
775                         pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
776                         return ret;
777                 }
778         } else {
779                 single_dpm_table->count = 1;
780                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
781         }
782         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
783
784         /* vclk */
785         single_dpm_table = &(dpm_table->vclk_table);
786
787         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
788                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
789                 if (ret) {
790                         pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
791                         return ret;
792                 }
793         } else {
794                 single_dpm_table->count = 1;
795                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
796         }
797         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
798
799         /* dclk */
800         single_dpm_table = &(dpm_table->dclk_table);
801
802         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
803                 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
804                 if (ret) {
805                         pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
806                         return ret;
807                 }
808         } else {
809                 single_dpm_table->count = 1;
810                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
811         }
812         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
813
814         /* dcefclk */
815         single_dpm_table = &(dpm_table->dcef_table);
816
817         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
818                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
819                                                   PPCLK_DCEFCLK);
820                 if (ret) {
821                         pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
822                         return ret;
823                 }
824         } else {
825                 single_dpm_table->count = 1;
826                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
827         }
828         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
829
830         /* pixclk */
831         single_dpm_table = &(dpm_table->pixel_table);
832
833         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
834                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
835                                                   PPCLK_PIXCLK);
836                 if (ret) {
837                         pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
838                         return ret;
839                 }
840         } else {
841                 single_dpm_table->count = 0;
842         }
843         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
844
845         /* dispclk */
846         single_dpm_table = &(dpm_table->display_table);
847
848         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
849                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
850                                                   PPCLK_DISPCLK);
851                 if (ret) {
852                         pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
853                         return ret;
854                 }
855         } else {
856                 single_dpm_table->count = 0;
857         }
858         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
859
860         /* phyclk */
861         single_dpm_table = &(dpm_table->phy_table);
862
863         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
864                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
865                                                   PPCLK_PHYCLK);
866                 if (ret) {
867                         pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
868                         return ret;
869                 }
870         } else {
871                 single_dpm_table->count = 0;
872         }
873         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
874
875         /* fclk */
876         single_dpm_table = &(dpm_table->fclk_table);
877
878         if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
879                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
880                                                   PPCLK_FCLK);
881                 if (ret) {
882                         pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
883                         return ret;
884                 }
885         } else {
886                 single_dpm_table->count = 0;
887         }
888         vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
889
890         memcpy(smu_dpm->golden_dpm_context, dpm_table,
891                sizeof(struct vega20_dpm_table));
892
893         return 0;
894 }
895
896 static int vega20_populate_umd_state_clk(struct smu_context *smu)
897 {
898         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
899         struct vega20_dpm_table *dpm_table = NULL;
900         struct vega20_single_dpm_table *gfx_table = NULL;
901         struct vega20_single_dpm_table *mem_table = NULL;
902
903         dpm_table = smu_dpm->dpm_context;
904         gfx_table = &(dpm_table->gfx_table);
905         mem_table = &(dpm_table->mem_table);
906
907         smu->pstate_sclk = gfx_table->dpm_levels[0].value;
908         smu->pstate_mclk = mem_table->dpm_levels[0].value;
909
910         if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
911             mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
912                 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
913                 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
914         }
915
916         smu->pstate_sclk = smu->pstate_sclk * 100;
917         smu->pstate_mclk = smu->pstate_mclk * 100;
918
919         return 0;
920 }
921
922 static int vega20_get_clk_table(struct smu_context *smu,
923                         struct pp_clock_levels_with_latency *clocks,
924                         struct vega20_single_dpm_table *dpm_table)
925 {
926         int i, count;
927
928         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
929         clocks->num_levels = count;
930
931         for (i = 0; i < count; i++) {
932                 clocks->data[i].clocks_in_khz =
933                         dpm_table->dpm_levels[i].value * 1000;
934                 clocks->data[i].latency_in_us = 0;
935         }
936
937         return 0;
938 }
939
940 static int vega20_print_clk_levels(struct smu_context *smu,
941                         enum smu_clk_type type, char *buf)
942 {
943         int i, now, size = 0;
944         int ret = 0;
945         uint32_t gen_speed, lane_width;
946         struct amdgpu_device *adev = smu->adev;
947         struct pp_clock_levels_with_latency clocks;
948         struct vega20_single_dpm_table *single_dpm_table;
949         struct smu_table_context *table_context = &smu->smu_table;
950         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
951         struct vega20_dpm_table *dpm_table = NULL;
952         struct vega20_od8_settings *od8_settings =
953                 (struct vega20_od8_settings *)smu->od_settings;
954         OverDriveTable_t *od_table =
955                 (OverDriveTable_t *)(table_context->overdrive_table);
956         PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
957
958         dpm_table = smu_dpm->dpm_context;
959
960         switch (type) {
961         case SMU_SCLK:
962                 ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now);
963                 if (ret) {
964                         pr_err("Attempt to get current gfx clk Failed!");
965                         return ret;
966                 }
967
968                 single_dpm_table = &(dpm_table->gfx_table);
969                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
970                 if (ret) {
971                         pr_err("Attempt to get gfx clk levels Failed!");
972                         return ret;
973                 }
974
975                 for (i = 0; i < clocks.num_levels; i++)
976                         size += sprintf(buf + size, "%d: %uMhz %s\n", i,
977                                         clocks.data[i].clocks_in_khz / 1000,
978                                         (clocks.data[i].clocks_in_khz == now * 10)
979                                         ? "*" : "");
980                 break;
981
982         case SMU_MCLK:
983                 ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now);
984                 if (ret) {
985                         pr_err("Attempt to get current mclk Failed!");
986                         return ret;
987                 }
988
989                 single_dpm_table = &(dpm_table->mem_table);
990                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
991                 if (ret) {
992                         pr_err("Attempt to get memory clk levels Failed!");
993                         return ret;
994                 }
995
996                 for (i = 0; i < clocks.num_levels; i++)
997                         size += sprintf(buf + size, "%d: %uMhz %s\n",
998                                 i, clocks.data[i].clocks_in_khz / 1000,
999                                 (clocks.data[i].clocks_in_khz == now * 10)
1000                                 ? "*" : "");
1001                 break;
1002
1003         case SMU_SOCCLK:
1004                 ret = smu_get_current_clk_freq(smu, SMU_SOCCLK, &now);
1005                 if (ret) {
1006                         pr_err("Attempt to get current socclk Failed!");
1007                         return ret;
1008                 }
1009
1010                 single_dpm_table = &(dpm_table->soc_table);
1011                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1012                 if (ret) {
1013                         pr_err("Attempt to get socclk levels Failed!");
1014                         return ret;
1015                 }
1016
1017                 for (i = 0; i < clocks.num_levels; i++)
1018                         size += sprintf(buf + size, "%d: %uMhz %s\n",
1019                                 i, clocks.data[i].clocks_in_khz / 1000,
1020                                 (clocks.data[i].clocks_in_khz == now * 10)
1021                                 ? "*" : "");
1022                 break;
1023
1024         case SMU_FCLK:
1025                 ret = smu_get_current_clk_freq(smu, SMU_FCLK, &now);
1026                 if (ret) {
1027                         pr_err("Attempt to get current fclk Failed!");
1028                         return ret;
1029                 }
1030
1031                 single_dpm_table = &(dpm_table->fclk_table);
1032                 for (i = 0; i < single_dpm_table->count; i++)
1033                         size += sprintf(buf + size, "%d: %uMhz %s\n",
1034                                 i, single_dpm_table->dpm_levels[i].value,
1035                                 (single_dpm_table->dpm_levels[i].value == now / 100)
1036                                 ? "*" : "");
1037                 break;
1038
1039         case SMU_DCEFCLK:
1040                 ret = smu_get_current_clk_freq(smu, SMU_DCEFCLK, &now);
1041                 if (ret) {
1042                         pr_err("Attempt to get current dcefclk Failed!");
1043                         return ret;
1044                 }
1045
1046                 single_dpm_table = &(dpm_table->dcef_table);
1047                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1048                 if (ret) {
1049                         pr_err("Attempt to get dcefclk levels Failed!");
1050                         return ret;
1051                 }
1052
1053                 for (i = 0; i < clocks.num_levels; i++)
1054                         size += sprintf(buf + size, "%d: %uMhz %s\n",
1055                                 i, clocks.data[i].clocks_in_khz / 1000,
1056                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
1057                 break;
1058
1059         case SMU_PCIE:
1060                 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
1061                              PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
1062                         >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
1063                 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
1064                               PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
1065                         >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
1066                 for (i = 0; i < NUM_LINK_LEVELS; i++)
1067                         size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
1068                                         (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
1069                                         (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
1070                                         (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
1071                                         (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
1072                                         (pptable->PcieLaneCount[i] == 1) ? "x1" :
1073                                         (pptable->PcieLaneCount[i] == 2) ? "x2" :
1074                                         (pptable->PcieLaneCount[i] == 3) ? "x4" :
1075                                         (pptable->PcieLaneCount[i] == 4) ? "x8" :
1076                                         (pptable->PcieLaneCount[i] == 5) ? "x12" :
1077                                         (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
1078                                         pptable->LclkFreq[i],
1079                                         (gen_speed == pptable->PcieGenSpeed[i]) &&
1080                                         (lane_width == pptable->PcieLaneCount[i]) ?
1081                                         "*" : "");
1082                 break;
1083
1084         case SMU_OD_SCLK:
1085                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1086                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1087                         size = sprintf(buf, "%s:\n", "OD_SCLK");
1088                         size += sprintf(buf + size, "0: %10uMhz\n",
1089                                         od_table->GfxclkFmin);
1090                         size += sprintf(buf + size, "1: %10uMhz\n",
1091                                         od_table->GfxclkFmax);
1092                 }
1093
1094                 break;
1095
1096         case SMU_OD_MCLK:
1097                 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1098                         size = sprintf(buf, "%s:\n", "OD_MCLK");
1099                         size += sprintf(buf + size, "1: %10uMhz\n",
1100                                          od_table->UclkFmax);
1101                 }
1102
1103                 break;
1104
1105         case SMU_OD_VDDC_CURVE:
1106                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1107                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1108                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1109                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1110                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1111                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1112                         size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
1113                         size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
1114                                         od_table->GfxclkFreq1,
1115                                         od_table->GfxclkVolt1 / VOLTAGE_SCALE);
1116                         size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
1117                                         od_table->GfxclkFreq2,
1118                                         od_table->GfxclkVolt2 / VOLTAGE_SCALE);
1119                         size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
1120                                         od_table->GfxclkFreq3,
1121                                         od_table->GfxclkVolt3 / VOLTAGE_SCALE);
1122                 }
1123
1124                 break;
1125
1126         case SMU_OD_RANGE:
1127                 size = sprintf(buf, "%s:\n", "OD_RANGE");
1128
1129                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1130                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1131                         size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
1132                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
1133                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
1134                 }
1135
1136                 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1137                         single_dpm_table = &(dpm_table->mem_table);
1138                         ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1139                         if (ret) {
1140                                 pr_err("Attempt to get memory clk levels Failed!");
1141                                 return ret;
1142                         }
1143
1144                         size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
1145                                         clocks.data[0].clocks_in_khz / 1000,
1146                                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
1147                 }
1148
1149                 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1150                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1151                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1152                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1153                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1154                     od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1155                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1156                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
1157                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
1158                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1159                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
1160                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
1161                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1162                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
1163                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
1164                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1165                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
1166                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
1167                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1168                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
1169                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
1170                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1171                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
1172                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
1173                 }
1174
1175                 break;
1176
1177         default:
1178                 break;
1179         }
1180         return size;
1181 }
1182
1183 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
1184                                    uint32_t feature_mask)
1185 {
1186         struct vega20_dpm_table *dpm_table;
1187         struct vega20_single_dpm_table *single_dpm_table;
1188         uint32_t freq;
1189         int ret = 0;
1190
1191         dpm_table = smu->smu_dpm.dpm_context;
1192
1193         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
1194             (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1195                 single_dpm_table = &(dpm_table->gfx_table);
1196                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1197                         single_dpm_table->dpm_state.soft_min_level;
1198                 ret = smu_send_smc_msg_with_param(smu,
1199                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1200                         (PPCLK_GFXCLK << 16) | (freq & 0xffff));
1201                 if (ret) {
1202                         pr_err("Failed to set soft %s gfxclk !\n",
1203                                                 max ? "max" : "min");
1204                         return ret;
1205                 }
1206         }
1207
1208         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
1209             (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1210                 single_dpm_table = &(dpm_table->mem_table);
1211                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1212                         single_dpm_table->dpm_state.soft_min_level;
1213                 ret = smu_send_smc_msg_with_param(smu,
1214                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1215                         (PPCLK_UCLK << 16) | (freq & 0xffff));
1216                 if (ret) {
1217                         pr_err("Failed to set soft %s memclk !\n",
1218                                                 max ? "max" : "min");
1219                         return ret;
1220                 }
1221         }
1222
1223         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
1224             (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1225                 single_dpm_table = &(dpm_table->soc_table);
1226                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1227                         single_dpm_table->dpm_state.soft_min_level;
1228                 ret = smu_send_smc_msg_with_param(smu,
1229                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1230                         (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1231                 if (ret) {
1232                         pr_err("Failed to set soft %s socclk !\n",
1233                                                 max ? "max" : "min");
1234                         return ret;
1235                 }
1236         }
1237
1238         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) &&
1239             (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1240                 single_dpm_table = &(dpm_table->fclk_table);
1241                 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1242                         single_dpm_table->dpm_state.soft_min_level;
1243                 ret = smu_send_smc_msg_with_param(smu,
1244                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1245                         (PPCLK_FCLK << 16) | (freq & 0xffff));
1246                 if (ret) {
1247                         pr_err("Failed to set soft %s fclk !\n",
1248                                                 max ? "max" : "min");
1249                         return ret;
1250                 }
1251         }
1252
1253         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
1254             (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1255                 single_dpm_table = &(dpm_table->dcef_table);
1256                 freq = single_dpm_table->dpm_state.hard_min_level;
1257                 if (!max) {
1258                         ret = smu_send_smc_msg_with_param(smu,
1259                                 SMU_MSG_SetHardMinByFreq,
1260                                 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1261                         if (ret) {
1262                                 pr_err("Failed to set hard min dcefclk !\n");
1263                                 return ret;
1264                         }
1265                 }
1266         }
1267
1268         return ret;
1269 }
1270
1271 static int vega20_force_clk_levels(struct smu_context *smu,
1272                         enum  smu_clk_type clk_type, uint32_t mask)
1273 {
1274         struct vega20_dpm_table *dpm_table;
1275         struct vega20_single_dpm_table *single_dpm_table;
1276         uint32_t soft_min_level, soft_max_level, hard_min_level;
1277         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1278         int ret = 0;
1279
1280         if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
1281                 pr_info("force clock level is for dpm manual mode only.\n");
1282                 return -EINVAL;
1283         }
1284
1285         mutex_lock(&(smu->mutex));
1286
1287         soft_min_level = mask ? (ffs(mask) - 1) : 0;
1288         soft_max_level = mask ? (fls(mask) - 1) : 0;
1289
1290         dpm_table = smu->smu_dpm.dpm_context;
1291
1292         switch (clk_type) {
1293         case SMU_SCLK:
1294                 single_dpm_table = &(dpm_table->gfx_table);
1295
1296                 if (soft_max_level >= single_dpm_table->count) {
1297                         pr_err("Clock level specified %d is over max allowed %d\n",
1298                                         soft_max_level, single_dpm_table->count - 1);
1299                         ret = -EINVAL;
1300                         break;
1301                 }
1302
1303                 single_dpm_table->dpm_state.soft_min_level =
1304                         single_dpm_table->dpm_levels[soft_min_level].value;
1305                 single_dpm_table->dpm_state.soft_max_level =
1306                         single_dpm_table->dpm_levels[soft_max_level].value;
1307
1308                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1309                 if (ret) {
1310                         pr_err("Failed to upload boot level to lowest!\n");
1311                         break;
1312                 }
1313
1314                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1315                 if (ret)
1316                         pr_err("Failed to upload dpm max level to highest!\n");
1317
1318                 break;
1319
1320         case SMU_MCLK:
1321                 single_dpm_table = &(dpm_table->mem_table);
1322
1323                 if (soft_max_level >= single_dpm_table->count) {
1324                         pr_err("Clock level specified %d is over max allowed %d\n",
1325                                         soft_max_level, single_dpm_table->count - 1);
1326                         ret = -EINVAL;
1327                         break;
1328                 }
1329
1330                 single_dpm_table->dpm_state.soft_min_level =
1331                         single_dpm_table->dpm_levels[soft_min_level].value;
1332                 single_dpm_table->dpm_state.soft_max_level =
1333                         single_dpm_table->dpm_levels[soft_max_level].value;
1334
1335                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1336                 if (ret) {
1337                         pr_err("Failed to upload boot level to lowest!\n");
1338                         break;
1339                 }
1340
1341                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1342                 if (ret)
1343                         pr_err("Failed to upload dpm max level to highest!\n");
1344
1345                 break;
1346
1347         case SMU_SOCCLK:
1348                 single_dpm_table = &(dpm_table->soc_table);
1349
1350                 if (soft_max_level >= single_dpm_table->count) {
1351                         pr_err("Clock level specified %d is over max allowed %d\n",
1352                                         soft_max_level, single_dpm_table->count - 1);
1353                         ret = -EINVAL;
1354                         break;
1355                 }
1356
1357                 single_dpm_table->dpm_state.soft_min_level =
1358                         single_dpm_table->dpm_levels[soft_min_level].value;
1359                 single_dpm_table->dpm_state.soft_max_level =
1360                         single_dpm_table->dpm_levels[soft_max_level].value;
1361
1362                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1363                 if (ret) {
1364                         pr_err("Failed to upload boot level to lowest!\n");
1365                         break;
1366                 }
1367
1368                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1369                 if (ret)
1370                         pr_err("Failed to upload dpm max level to highest!\n");
1371
1372                 break;
1373
1374         case SMU_FCLK:
1375                 single_dpm_table = &(dpm_table->fclk_table);
1376
1377                 if (soft_max_level >= single_dpm_table->count) {
1378                         pr_err("Clock level specified %d is over max allowed %d\n",
1379                                         soft_max_level, single_dpm_table->count - 1);
1380                         ret = -EINVAL;
1381                         break;
1382                 }
1383
1384                 single_dpm_table->dpm_state.soft_min_level =
1385                         single_dpm_table->dpm_levels[soft_min_level].value;
1386                 single_dpm_table->dpm_state.soft_max_level =
1387                         single_dpm_table->dpm_levels[soft_max_level].value;
1388
1389                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1390                 if (ret) {
1391                         pr_err("Failed to upload boot level to lowest!\n");
1392                         break;
1393                 }
1394
1395                 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1396                 if (ret)
1397                         pr_err("Failed to upload dpm max level to highest!\n");
1398
1399                 break;
1400
1401         case SMU_DCEFCLK:
1402                 hard_min_level = soft_min_level;
1403                 single_dpm_table = &(dpm_table->dcef_table);
1404
1405                 if (hard_min_level >= single_dpm_table->count) {
1406                         pr_err("Clock level specified %d is over max allowed %d\n",
1407                                         hard_min_level, single_dpm_table->count - 1);
1408                         ret = -EINVAL;
1409                         break;
1410                 }
1411
1412                 single_dpm_table->dpm_state.hard_min_level =
1413                         single_dpm_table->dpm_levels[hard_min_level].value;
1414
1415                 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1416                 if (ret)
1417                         pr_err("Failed to upload boot level to lowest!\n");
1418
1419                 break;
1420
1421         case SMU_PCIE:
1422                 if (soft_min_level >= NUM_LINK_LEVELS ||
1423                     soft_max_level >= NUM_LINK_LEVELS) {
1424                         ret = -EINVAL;
1425                         break;
1426                 }
1427
1428                 ret = smu_send_smc_msg_with_param(smu,
1429                                 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1430                 if (ret)
1431                         pr_err("Failed to set min link dpm level!\n");
1432
1433                 break;
1434
1435         default:
1436                 break;
1437         }
1438
1439         mutex_unlock(&(smu->mutex));
1440         return ret;
1441 }
1442
1443 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1444                                                  enum smu_clk_type clk_type,
1445                                                  struct pp_clock_levels_with_latency *clocks)
1446 {
1447         int ret;
1448         struct vega20_single_dpm_table *single_dpm_table;
1449         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1450         struct vega20_dpm_table *dpm_table = NULL;
1451
1452         dpm_table = smu_dpm->dpm_context;
1453
1454         mutex_lock(&smu->mutex);
1455
1456         switch (clk_type) {
1457         case SMU_GFXCLK:
1458                 single_dpm_table = &(dpm_table->gfx_table);
1459                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1460                 break;
1461         case SMU_MCLK:
1462                 single_dpm_table = &(dpm_table->mem_table);
1463                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1464                 break;
1465         case SMU_DCEFCLK:
1466                 single_dpm_table = &(dpm_table->dcef_table);
1467                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1468                 break;
1469         case SMU_SOCCLK:
1470                 single_dpm_table = &(dpm_table->soc_table);
1471                 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1472                 break;
1473         default:
1474                 ret = -EINVAL;
1475         }
1476
1477         mutex_unlock(&smu->mutex);
1478         return ret;
1479 }
1480
1481 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1482                                                      uint32_t *voltage,
1483                                                      uint32_t freq)
1484 {
1485         int ret;
1486
1487         ret = smu_send_smc_msg_with_param(smu,
1488                         SMU_MSG_GetAVFSVoltageByDpm,
1489                         ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1490         if (ret) {
1491                 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1492                 return ret;
1493         }
1494
1495         smu_read_smc_arg(smu, voltage);
1496         *voltage = *voltage / VOLTAGE_SCALE;
1497
1498         return 0;
1499 }
1500
1501 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1502 {
1503         struct smu_table_context *table_context = &smu->smu_table;
1504         OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1505         struct vega20_od8_settings *od8_settings = NULL;
1506         PPTable_t *smc_pptable = table_context->driver_pptable;
1507         int i, ret;
1508
1509         if (smu->od_settings)
1510                 return -EINVAL;
1511
1512         od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1513
1514         if (!od8_settings)
1515                 return -ENOMEM;
1516
1517         smu->od_settings = (void *)od8_settings;
1518
1519         ret = vega20_setup_od8_information(smu);
1520         if (ret) {
1521                 pr_err("Retrieve board OD limits failed!\n");
1522                 return ret;
1523         }
1524
1525         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
1526                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1527                     od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1528                     od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1529                     (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1530                      od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1531                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1532                                 OD8_GFXCLK_LIMITS;
1533                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1534                                 OD8_GFXCLK_LIMITS;
1535                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1536                                 od_table->GfxclkFmin;
1537                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1538                                 od_table->GfxclkFmax;
1539                 }
1540
1541                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1542                     (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1543                      smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1544                     (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1545                      smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1546                     (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1547                      od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1548                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1549                                 OD8_GFXCLK_CURVE;
1550                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1551                                 OD8_GFXCLK_CURVE;
1552                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1553                                 OD8_GFXCLK_CURVE;
1554                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1555                                 OD8_GFXCLK_CURVE;
1556                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1557                                 OD8_GFXCLK_CURVE;
1558                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1559                                 OD8_GFXCLK_CURVE;
1560
1561                         od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1562                         od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1563                         od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1564                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1565                                 od_table->GfxclkFreq1;
1566                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1567                                 od_table->GfxclkFreq2;
1568                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1569                                 od_table->GfxclkFreq3;
1570
1571                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1572                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1573                                 od_table->GfxclkFreq1);
1574                         if (ret)
1575                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1576                         od_table->GfxclkVolt1 =
1577                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1578                                 * VOLTAGE_SCALE;
1579                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1580                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1581                                 od_table->GfxclkFreq2);
1582                         if (ret)
1583                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1584                         od_table->GfxclkVolt2 =
1585                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1586                                 * VOLTAGE_SCALE;
1587                         ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1588                                 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1589                                 od_table->GfxclkFreq3);
1590                         if (ret)
1591                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1592                         od_table->GfxclkVolt3 =
1593                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1594                                 * VOLTAGE_SCALE;
1595                 }
1596         }
1597
1598         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1599                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1600                     od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1601                     od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1602                     (od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1603                      od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1604                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1605                                 OD8_UCLK_MAX;
1606                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1607                                 od_table->UclkFmax;
1608                 }
1609         }
1610
1611         if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1612             od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1613             od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1614             od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1615             od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1616                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1617                         OD8_POWER_LIMIT;
1618                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1619                         od_table->OverDrivePct;
1620         }
1621
1622         if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) {
1623                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1624                     od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1625                     od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1626                     (od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1627                      od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1628                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1629                                 OD8_ACOUSTIC_LIMIT_SCLK;
1630                         od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1631                                 od_table->FanMaximumRpm;
1632                 }
1633
1634                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1635                     od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1636                     od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1637                     (od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1638                      od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1639                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1640                                 OD8_FAN_SPEED_MIN;
1641                         od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1642                                 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1643                 }
1644         }
1645
1646         if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) {
1647                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1648                     od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1649                     od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1650                     (od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1651                      od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1652                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1653                                 OD8_TEMPERATURE_FAN;
1654                         od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1655                                 od_table->FanTargetTemperature;
1656                 }
1657
1658                 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1659                     od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1660                     od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1661                     (od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1662                      od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1663                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1664                                 OD8_TEMPERATURE_SYSTEM;
1665                         od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1666                                 od_table->MaxOpTemp;
1667                 }
1668         }
1669
1670         for (i = 0; i < OD8_SETTING_COUNT; i++) {
1671                 if (od8_settings->od8_settings_array[i].feature_id) {
1672                         od8_settings->od8_settings_array[i].min_value =
1673                                 od8_settings->od_settings_min[i];
1674                         od8_settings->od8_settings_array[i].max_value =
1675                                 od8_settings->od_settings_max[i];
1676                         od8_settings->od8_settings_array[i].current_value =
1677                                 od8_settings->od8_settings_array[i].default_value;
1678                 } else {
1679                         od8_settings->od8_settings_array[i].min_value = 0;
1680                         od8_settings->od8_settings_array[i].max_value = 0;
1681                         od8_settings->od8_settings_array[i].current_value = 0;
1682                 }
1683         }
1684
1685         return 0;
1686 }
1687
1688 static int vega20_get_metrics_table(struct smu_context *smu,
1689                                     SmuMetrics_t *metrics_table)
1690 {
1691         struct smu_table_context *smu_table= &smu->smu_table;
1692         int ret = 0;
1693
1694         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
1695                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
1696                                 (void *)smu_table->metrics_table, false);
1697                 if (ret) {
1698                         pr_info("Failed to export SMU metrics table!\n");
1699                         return ret;
1700                 }
1701                 smu_table->metrics_time = jiffies;
1702         }
1703
1704         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
1705
1706         return ret;
1707 }
1708
1709 static int vega20_set_default_od_settings(struct smu_context *smu,
1710                                           bool initialize)
1711 {
1712         struct smu_table_context *table_context = &smu->smu_table;
1713         int ret;
1714
1715         if (initialize) {
1716                 if (table_context->overdrive_table)
1717                         return -EINVAL;
1718
1719                 table_context->overdrive_table = kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL);
1720
1721                 if (!table_context->overdrive_table)
1722                         return -ENOMEM;
1723
1724                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
1725                                        table_context->overdrive_table, false);
1726                 if (ret) {
1727                         pr_err("Failed to export over drive table!\n");
1728                         return ret;
1729                 }
1730
1731                 ret = vega20_set_default_od8_setttings(smu);
1732                 if (ret)
1733                         return ret;
1734         }
1735
1736         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
1737                                table_context->overdrive_table, true);
1738         if (ret) {
1739                 pr_err("Failed to import over drive table!\n");
1740                 return ret;
1741         }
1742
1743         return 0;
1744 }
1745
1746 static int vega20_get_od_percentage(struct smu_context *smu,
1747                                     enum smu_clk_type clk_type)
1748 {
1749         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1750         struct vega20_dpm_table *dpm_table = NULL;
1751         struct vega20_dpm_table *golden_table = NULL;
1752         struct vega20_single_dpm_table *single_dpm_table;
1753         struct vega20_single_dpm_table *golden_dpm_table;
1754         int value, golden_value;
1755
1756         dpm_table = smu_dpm->dpm_context;
1757         golden_table = smu_dpm->golden_dpm_context;
1758
1759         switch (clk_type) {
1760         case SMU_OD_SCLK:
1761                 single_dpm_table = &(dpm_table->gfx_table);
1762                 golden_dpm_table = &(golden_table->gfx_table);
1763                 break;
1764         case SMU_OD_MCLK:
1765                 single_dpm_table = &(dpm_table->mem_table);
1766                 golden_dpm_table = &(golden_table->mem_table);
1767                 break;
1768         default:
1769                 return -EINVAL;
1770                 break;
1771         }
1772
1773         value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1774         golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1775
1776         value -= golden_value;
1777         value = DIV_ROUND_UP(value * 100, golden_value);
1778
1779         return value;
1780 }
1781
1782 static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
1783 {
1784         DpmActivityMonitorCoeffInt_t activity_monitor;
1785         uint32_t i, size = 0;
1786         int16_t workload_type = 0;
1787         static const char *profile_name[] = {
1788                                         "BOOTUP_DEFAULT",
1789                                         "3D_FULL_SCREEN",
1790                                         "POWER_SAVING",
1791                                         "VIDEO",
1792                                         "VR",
1793                                         "COMPUTE",
1794                                         "CUSTOM"};
1795         static const char *title[] = {
1796                         "PROFILE_INDEX(NAME)",
1797                         "CLOCK_TYPE(NAME)",
1798                         "FPS",
1799                         "UseRlcBusy",
1800                         "MinActiveFreqType",
1801                         "MinActiveFreq",
1802                         "BoosterFreqType",
1803                         "BoosterFreq",
1804                         "PD_Data_limit_c",
1805                         "PD_Data_error_coeff",
1806                         "PD_Data_error_rate_coeff"};
1807         int result = 0;
1808
1809         if (!smu->pm_enabled || !buf)
1810                 return -EINVAL;
1811
1812         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1813                         title[0], title[1], title[2], title[3], title[4], title[5],
1814                         title[6], title[7], title[8], title[9], title[10]);
1815
1816         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1817                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1818                 workload_type = smu_workload_get_type(smu, i);
1819                 if (workload_type < 0)
1820                         return -EINVAL;
1821
1822                 result = smu_update_table(smu,
1823                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1824                                           (void *)(&activity_monitor), false);
1825                 if (result) {
1826                         pr_err("[%s] Failed to get activity monitor!", __func__);
1827                         return result;
1828                 }
1829
1830                 size += sprintf(buf + size, "%2d %14s%s:\n",
1831                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1832
1833                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1834                         " ",
1835                         0,
1836                         "GFXCLK",
1837                         activity_monitor.Gfx_FPS,
1838                         activity_monitor.Gfx_UseRlcBusy,
1839                         activity_monitor.Gfx_MinActiveFreqType,
1840                         activity_monitor.Gfx_MinActiveFreq,
1841                         activity_monitor.Gfx_BoosterFreqType,
1842                         activity_monitor.Gfx_BoosterFreq,
1843                         activity_monitor.Gfx_PD_Data_limit_c,
1844                         activity_monitor.Gfx_PD_Data_error_coeff,
1845                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
1846
1847                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1848                         " ",
1849                         1,
1850                         "SOCCLK",
1851                         activity_monitor.Soc_FPS,
1852                         activity_monitor.Soc_UseRlcBusy,
1853                         activity_monitor.Soc_MinActiveFreqType,
1854                         activity_monitor.Soc_MinActiveFreq,
1855                         activity_monitor.Soc_BoosterFreqType,
1856                         activity_monitor.Soc_BoosterFreq,
1857                         activity_monitor.Soc_PD_Data_limit_c,
1858                         activity_monitor.Soc_PD_Data_error_coeff,
1859                         activity_monitor.Soc_PD_Data_error_rate_coeff);
1860
1861                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1862                         " ",
1863                         2,
1864                         "UCLK",
1865                         activity_monitor.Mem_FPS,
1866                         activity_monitor.Mem_UseRlcBusy,
1867                         activity_monitor.Mem_MinActiveFreqType,
1868                         activity_monitor.Mem_MinActiveFreq,
1869                         activity_monitor.Mem_BoosterFreqType,
1870                         activity_monitor.Mem_BoosterFreq,
1871                         activity_monitor.Mem_PD_Data_limit_c,
1872                         activity_monitor.Mem_PD_Data_error_coeff,
1873                         activity_monitor.Mem_PD_Data_error_rate_coeff);
1874
1875                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1876                         " ",
1877                         3,
1878                         "FCLK",
1879                         activity_monitor.Fclk_FPS,
1880                         activity_monitor.Fclk_UseRlcBusy,
1881                         activity_monitor.Fclk_MinActiveFreqType,
1882                         activity_monitor.Fclk_MinActiveFreq,
1883                         activity_monitor.Fclk_BoosterFreqType,
1884                         activity_monitor.Fclk_BoosterFreq,
1885                         activity_monitor.Fclk_PD_Data_limit_c,
1886                         activity_monitor.Fclk_PD_Data_error_coeff,
1887                         activity_monitor.Fclk_PD_Data_error_rate_coeff);
1888         }
1889
1890         return size;
1891 }
1892
1893 static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1894 {
1895         DpmActivityMonitorCoeffInt_t activity_monitor;
1896         int workload_type = 0, ret = 0;
1897
1898         smu->power_profile_mode = input[size];
1899
1900         if (!smu->pm_enabled)
1901                 return ret;
1902         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1903                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1904                 return -EINVAL;
1905         }
1906
1907         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1908                 ret = smu_update_table(smu,
1909                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1910                                        (void *)(&activity_monitor), false);
1911                 if (ret) {
1912                         pr_err("[%s] Failed to get activity monitor!", __func__);
1913                         return ret;
1914                 }
1915
1916                 switch (input[0]) {
1917                 case 0: /* Gfxclk */
1918                         activity_monitor.Gfx_FPS = input[1];
1919                         activity_monitor.Gfx_UseRlcBusy = input[2];
1920                         activity_monitor.Gfx_MinActiveFreqType = input[3];
1921                         activity_monitor.Gfx_MinActiveFreq = input[4];
1922                         activity_monitor.Gfx_BoosterFreqType = input[5];
1923                         activity_monitor.Gfx_BoosterFreq = input[6];
1924                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
1925                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1926                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1927                         break;
1928                 case 1: /* Socclk */
1929                         activity_monitor.Soc_FPS = input[1];
1930                         activity_monitor.Soc_UseRlcBusy = input[2];
1931                         activity_monitor.Soc_MinActiveFreqType = input[3];
1932                         activity_monitor.Soc_MinActiveFreq = input[4];
1933                         activity_monitor.Soc_BoosterFreqType = input[5];
1934                         activity_monitor.Soc_BoosterFreq = input[6];
1935                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1936                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1937                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1938                         break;
1939                 case 2: /* Uclk */
1940                         activity_monitor.Mem_FPS = input[1];
1941                         activity_monitor.Mem_UseRlcBusy = input[2];
1942                         activity_monitor.Mem_MinActiveFreqType = input[3];
1943                         activity_monitor.Mem_MinActiveFreq = input[4];
1944                         activity_monitor.Mem_BoosterFreqType = input[5];
1945                         activity_monitor.Mem_BoosterFreq = input[6];
1946                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1947                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1948                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1949                         break;
1950                 case 3: /* Fclk */
1951                         activity_monitor.Fclk_FPS = input[1];
1952                         activity_monitor.Fclk_UseRlcBusy = input[2];
1953                         activity_monitor.Fclk_MinActiveFreqType = input[3];
1954                         activity_monitor.Fclk_MinActiveFreq = input[4];
1955                         activity_monitor.Fclk_BoosterFreqType = input[5];
1956                         activity_monitor.Fclk_BoosterFreq = input[6];
1957                         activity_monitor.Fclk_PD_Data_limit_c = input[7];
1958                         activity_monitor.Fclk_PD_Data_error_coeff = input[8];
1959                         activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
1960                         break;
1961                 }
1962
1963                 ret = smu_update_table(smu,
1964                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1965                                        (void *)(&activity_monitor), true);
1966                 if (ret) {
1967                         pr_err("[%s] Failed to set activity monitor!", __func__);
1968                         return ret;
1969                 }
1970         }
1971
1972         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1973         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1974         if (workload_type < 0)
1975                 return -EINVAL;
1976         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1977                                     1 << workload_type);
1978
1979         return ret;
1980 }
1981
1982 static int
1983 vega20_get_profiling_clk_mask(struct smu_context *smu,
1984                               enum amd_dpm_forced_level level,
1985                               uint32_t *sclk_mask,
1986                               uint32_t *mclk_mask,
1987                               uint32_t *soc_mask)
1988 {
1989         struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1990         struct vega20_single_dpm_table *gfx_dpm_table;
1991         struct vega20_single_dpm_table *mem_dpm_table;
1992         struct vega20_single_dpm_table *soc_dpm_table;
1993
1994         if (!smu->smu_dpm.dpm_context)
1995                 return -EINVAL;
1996
1997         gfx_dpm_table = &dpm_table->gfx_table;
1998         mem_dpm_table = &dpm_table->mem_table;
1999         soc_dpm_table = &dpm_table->soc_table;
2000
2001         *sclk_mask = 0;
2002         *mclk_mask = 0;
2003         *soc_mask  = 0;
2004
2005         if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
2006             mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
2007             soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
2008                 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
2009                 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2010                 *soc_mask  = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2011         }
2012
2013         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2014                 *sclk_mask = 0;
2015         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2016                 *mclk_mask = 0;
2017         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2018                 *sclk_mask = gfx_dpm_table->count - 1;
2019                 *mclk_mask = mem_dpm_table->count - 1;
2020                 *soc_mask  = soc_dpm_table->count - 1;
2021         }
2022
2023         return 0;
2024 }
2025
2026 static int
2027 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
2028                                      struct vega20_single_dpm_table *dpm_table)
2029 {
2030         int ret = 0;
2031         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2032         if (!smu_dpm_ctx->dpm_context)
2033                 return -EINVAL;
2034
2035         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2036                 if (dpm_table->count <= 0) {
2037                         pr_err("[%s] Dpm table has no entry!", __func__);
2038                                 return -EINVAL;
2039                 }
2040
2041                 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
2042                         pr_err("[%s] Dpm table has too many entries!", __func__);
2043                                 return -EINVAL;
2044                 }
2045
2046                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2047                 ret = smu_send_smc_msg_with_param(smu,
2048                                 SMU_MSG_SetHardMinByFreq,
2049                                 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
2050                 if (ret) {
2051                         pr_err("[%s] Set hard min uclk failed!", __func__);
2052                                 return ret;
2053                 }
2054         }
2055
2056         return ret;
2057 }
2058
2059 static int vega20_pre_display_config_changed(struct smu_context *smu)
2060 {
2061         int ret = 0;
2062         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2063
2064         if (!smu->smu_dpm.dpm_context)
2065                 return -EINVAL;
2066
2067         smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
2068         ret = vega20_set_uclk_to_highest_dpm_level(smu,
2069                                                    &dpm_table->mem_table);
2070         if (ret)
2071                 pr_err("Failed to set uclk to highest dpm level");
2072         return ret;
2073 }
2074
2075 static int vega20_display_config_changed(struct smu_context *smu)
2076 {
2077         int ret = 0;
2078
2079         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2080             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
2081                 ret = smu_write_watermarks_table(smu);
2082                 if (ret) {
2083                         pr_err("Failed to update WMTABLE!");
2084                         return ret;
2085                 }
2086                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
2087         }
2088
2089         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2090             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
2091             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
2092                 smu_send_smc_msg_with_param(smu,
2093                                             SMU_MSG_NumOfDisplays,
2094                                             smu->display_config->num_display);
2095         }
2096
2097         return ret;
2098 }
2099
2100 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
2101 {
2102         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2103         struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
2104         struct vega20_single_dpm_table *dpm_table;
2105         bool vblank_too_short = false;
2106         bool disable_mclk_switching;
2107         uint32_t i, latency;
2108
2109         disable_mclk_switching = ((1 < smu->display_config->num_display) &&
2110                                   !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
2111         latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
2112
2113         /* gfxclk */
2114         dpm_table = &(dpm_ctx->gfx_table);
2115         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2116         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2117         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2118         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2119
2120                 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
2121                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2122                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2123                 }
2124
2125                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2126                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2127                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2128                 }
2129
2130                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2131                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2132                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2133                 }
2134
2135         /* memclk */
2136         dpm_table = &(dpm_ctx->mem_table);
2137         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2138         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2139         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2140         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2141
2142                 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
2143                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2144                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2145                 }
2146
2147                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2148                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2149                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2150                 }
2151
2152                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2153                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2154                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2155                 }
2156
2157         /* honour DAL's UCLK Hardmin */
2158         if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
2159                 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
2160
2161         /* Hardmin is dependent on displayconfig */
2162         if (disable_mclk_switching) {
2163                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2164                 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
2165                         if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
2166                                 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
2167                                         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
2168                                         break;
2169                                 }
2170                         }
2171                 }
2172         }
2173
2174         if (smu->display_config->nb_pstate_switch_disable)
2175                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2176
2177         /* vclk */
2178         dpm_table = &(dpm_ctx->vclk_table);
2179         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2180         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2181         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2182         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2183
2184                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2185                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2186                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2187                 }
2188
2189                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2190                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2191                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2192                 }
2193
2194         /* dclk */
2195         dpm_table = &(dpm_ctx->dclk_table);
2196         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2197         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2198         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2199         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2200
2201                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2202                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2203                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2204                 }
2205
2206                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2207                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2208                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2209                 }
2210
2211         /* socclk */
2212         dpm_table = &(dpm_ctx->soc_table);
2213         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2214         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2215         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2216         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2217
2218                 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
2219                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2220                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2221                 }
2222
2223                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2224                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2225                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2226                 }
2227
2228         /* eclk */
2229         dpm_table = &(dpm_ctx->eclk_table);
2230         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2231         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2232         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2233         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2234
2235                 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
2236                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2237                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2238                 }
2239
2240                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2241                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2242                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2243                 }
2244         return 0;
2245 }
2246
2247 static int
2248 vega20_notify_smc_dispaly_config(struct smu_context *smu)
2249 {
2250         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2251         struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
2252         struct smu_clocks min_clocks = {0};
2253         struct pp_display_clock_request clock_req;
2254         int ret = 0;
2255
2256         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
2257         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
2258         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
2259
2260         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
2261                 clock_req.clock_type = amd_pp_dcef_clock;
2262                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
2263                 if (!smu->funcs->display_clock_voltage_request(smu, &clock_req)) {
2264                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
2265                                 ret = smu_send_smc_msg_with_param(smu,
2266                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
2267                                                                   min_clocks.dcef_clock_in_sr/100);
2268                                 if (ret) {
2269                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
2270                                         return ret;
2271                                 }
2272                         }
2273                 } else {
2274                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2275                 }
2276         }
2277
2278         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2279                 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
2280                 ret = smu_send_smc_msg_with_param(smu,
2281                                                   SMU_MSG_SetHardMinByFreq,
2282                                                   (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
2283                 if (ret) {
2284                         pr_err("[%s] Set hard min uclk failed!", __func__);
2285                         return ret;
2286                 }
2287         }
2288
2289         return 0;
2290 }
2291
2292 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
2293 {
2294         uint32_t i;
2295
2296         for (i = 0; i < table->count; i++) {
2297                 if (table->dpm_levels[i].enabled)
2298                         break;
2299         }
2300         if (i >= table->count) {
2301                 i = 0;
2302                 table->dpm_levels[i].enabled = true;
2303         }
2304
2305         return i;
2306 }
2307
2308 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
2309 {
2310         int i = 0;
2311
2312         if (!table) {
2313                 pr_err("[%s] DPM Table does not exist!", __func__);
2314                 return 0;
2315         }
2316         if (table->count <= 0) {
2317                 pr_err("[%s] DPM Table has no entry!", __func__);
2318                 return 0;
2319         }
2320         if (table->count > MAX_REGULAR_DPM_NUMBER) {
2321                 pr_err("[%s] DPM Table has too many entries!", __func__);
2322                 return MAX_REGULAR_DPM_NUMBER - 1;
2323         }
2324
2325         for (i = table->count - 1; i >= 0; i--) {
2326                 if (table->dpm_levels[i].enabled)
2327                         break;
2328         }
2329         if (i < 0) {
2330                 i = 0;
2331                 table->dpm_levels[i].enabled = true;
2332         }
2333
2334         return i;
2335 }
2336
2337 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
2338 {
2339         uint32_t soft_level;
2340         int ret = 0;
2341         struct vega20_dpm_table *dpm_table =
2342                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2343
2344         if (highest)
2345                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2346         else
2347                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2348
2349         dpm_table->gfx_table.dpm_state.soft_min_level =
2350                 dpm_table->gfx_table.dpm_state.soft_max_level =
2351                 dpm_table->gfx_table.dpm_levels[soft_level].value;
2352
2353         if (highest)
2354                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2355         else
2356                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2357
2358         dpm_table->mem_table.dpm_state.soft_min_level =
2359                 dpm_table->mem_table.dpm_state.soft_max_level =
2360                 dpm_table->mem_table.dpm_levels[soft_level].value;
2361
2362         if (highest)
2363                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2364         else
2365                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2366
2367         dpm_table->soc_table.dpm_state.soft_min_level =
2368                 dpm_table->soc_table.dpm_state.soft_max_level =
2369                 dpm_table->soc_table.dpm_levels[soft_level].value;
2370
2371         ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2372         if (ret) {
2373                 pr_err("Failed to upload boot level to %s!\n",
2374                                 highest ? "highest" : "lowest");
2375                 return ret;
2376         }
2377
2378         ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2379         if (ret) {
2380                 pr_err("Failed to upload dpm max level to %s!\n!",
2381                                 highest ? "highest" : "lowest");
2382                 return ret;
2383         }
2384
2385         return ret;
2386 }
2387
2388 static int vega20_unforce_dpm_levels(struct smu_context *smu)
2389 {
2390         uint32_t soft_min_level, soft_max_level;
2391         int ret = 0;
2392         struct vega20_dpm_table *dpm_table =
2393                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2394
2395         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2396         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2397         dpm_table->gfx_table.dpm_state.soft_min_level =
2398                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2399         dpm_table->gfx_table.dpm_state.soft_max_level =
2400                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2401
2402         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2403         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2404         dpm_table->mem_table.dpm_state.soft_min_level =
2405                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2406         dpm_table->mem_table.dpm_state.soft_max_level =
2407                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2408
2409         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2410         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2411         dpm_table->soc_table.dpm_state.soft_min_level =
2412                 dpm_table->soc_table.dpm_levels[soft_min_level].value;
2413         dpm_table->soc_table.dpm_state.soft_max_level =
2414                 dpm_table->soc_table.dpm_levels[soft_max_level].value;
2415
2416         ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2417         if (ret) {
2418                 pr_err("Failed to upload DPM Bootup Levels!");
2419                 return ret;
2420         }
2421
2422         ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2423         if (ret) {
2424                 pr_err("Failed to upload DPM Max Levels!");
2425                 return ret;
2426         }
2427
2428         return ret;
2429 }
2430
2431 static int vega20_update_specified_od8_value(struct smu_context *smu,
2432                                              uint32_t index,
2433                                              uint32_t value)
2434 {
2435         struct smu_table_context *table_context = &smu->smu_table;
2436         OverDriveTable_t *od_table =
2437                 (OverDriveTable_t *)(table_context->overdrive_table);
2438         struct vega20_od8_settings *od8_settings =
2439                 (struct vega20_od8_settings *)smu->od_settings;
2440
2441         switch (index) {
2442         case OD8_SETTING_GFXCLK_FMIN:
2443                 od_table->GfxclkFmin = (uint16_t)value;
2444                 break;
2445
2446         case OD8_SETTING_GFXCLK_FMAX:
2447                 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2448                     value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2449                         return -EINVAL;
2450                 od_table->GfxclkFmax = (uint16_t)value;
2451                 break;
2452
2453         case OD8_SETTING_GFXCLK_FREQ1:
2454                 od_table->GfxclkFreq1 = (uint16_t)value;
2455                 break;
2456
2457         case OD8_SETTING_GFXCLK_VOLTAGE1:
2458                 od_table->GfxclkVolt1 = (uint16_t)value;
2459                 break;
2460
2461         case OD8_SETTING_GFXCLK_FREQ2:
2462                 od_table->GfxclkFreq2 = (uint16_t)value;
2463                 break;
2464
2465         case OD8_SETTING_GFXCLK_VOLTAGE2:
2466                 od_table->GfxclkVolt2 = (uint16_t)value;
2467                 break;
2468
2469         case OD8_SETTING_GFXCLK_FREQ3:
2470                 od_table->GfxclkFreq3 = (uint16_t)value;
2471                 break;
2472
2473         case OD8_SETTING_GFXCLK_VOLTAGE3:
2474                 od_table->GfxclkVolt3 = (uint16_t)value;
2475                 break;
2476
2477         case OD8_SETTING_UCLK_FMAX:
2478                 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2479                     value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2480                         return -EINVAL;
2481                 od_table->UclkFmax = (uint16_t)value;
2482                 break;
2483
2484         case OD8_SETTING_POWER_PERCENTAGE:
2485                 od_table->OverDrivePct = (int16_t)value;
2486                 break;
2487
2488         case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2489                 od_table->FanMaximumRpm = (uint16_t)value;
2490                 break;
2491
2492         case OD8_SETTING_FAN_MIN_SPEED:
2493                 od_table->FanMinimumPwm = (uint16_t)value;
2494                 break;
2495
2496         case OD8_SETTING_FAN_TARGET_TEMP:
2497                 od_table->FanTargetTemperature = (uint16_t)value;
2498                 break;
2499
2500         case OD8_SETTING_OPERATING_TEMP_MAX:
2501                 od_table->MaxOpTemp = (uint16_t)value;
2502                 break;
2503         }
2504
2505         return 0;
2506 }
2507
2508 static int vega20_update_od8_settings(struct smu_context *smu,
2509                                       uint32_t index,
2510                                       uint32_t value)
2511 {
2512         struct smu_table_context *table_context = &smu->smu_table;
2513         int ret;
2514
2515         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
2516                                table_context->overdrive_table, false);
2517         if (ret) {
2518                 pr_err("Failed to export over drive table!\n");
2519                 return ret;
2520         }
2521
2522         ret = vega20_update_specified_od8_value(smu, index, value);
2523         if (ret)
2524                 return ret;
2525
2526         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
2527                                table_context->overdrive_table, true);
2528         if (ret) {
2529                 pr_err("Failed to import over drive table!\n");
2530                 return ret;
2531         }
2532
2533         return 0;
2534 }
2535
2536 static int vega20_set_od_percentage(struct smu_context *smu,
2537                                     enum smu_clk_type clk_type,
2538                                     uint32_t value)
2539 {
2540         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2541         struct vega20_dpm_table *dpm_table = NULL;
2542         struct vega20_dpm_table *golden_table = NULL;
2543         struct vega20_single_dpm_table *single_dpm_table;
2544         struct vega20_single_dpm_table *golden_dpm_table;
2545         uint32_t od_clk, index;
2546         int ret = 0;
2547         int feature_enabled;
2548         PPCLK_e clk_id;
2549
2550         mutex_lock(&(smu->mutex));
2551
2552         dpm_table = smu_dpm->dpm_context;
2553         golden_table = smu_dpm->golden_dpm_context;
2554
2555         switch (clk_type) {
2556         case SMU_OD_SCLK:
2557                 single_dpm_table = &(dpm_table->gfx_table);
2558                 golden_dpm_table = &(golden_table->gfx_table);
2559                 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT);
2560                 clk_id = PPCLK_GFXCLK;
2561                 index = OD8_SETTING_GFXCLK_FMAX;
2562                 break;
2563         case SMU_OD_MCLK:
2564                 single_dpm_table = &(dpm_table->mem_table);
2565                 golden_dpm_table = &(golden_table->mem_table);
2566                 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT);
2567                 clk_id = PPCLK_UCLK;
2568                 index = OD8_SETTING_UCLK_FMAX;
2569                 break;
2570         default:
2571                 ret = -EINVAL;
2572                 break;
2573         }
2574
2575         if (ret)
2576                 goto set_od_failed;
2577
2578         od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2579         od_clk /= 100;
2580         od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2581
2582         ret = vega20_update_od8_settings(smu, index, od_clk);
2583         if (ret) {
2584                 pr_err("[Setoverdrive] failed to set od clk!\n");
2585                 goto set_od_failed;
2586         }
2587
2588         if (feature_enabled) {
2589                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2590                                                   clk_id);
2591                 if (ret) {
2592                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2593                         goto set_od_failed;
2594                 }
2595         } else {
2596                 single_dpm_table->count = 1;
2597                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2598         }
2599
2600         ret = smu_handle_task(smu, smu_dpm->dpm_level,
2601                               AMD_PP_TASK_READJUST_POWER_STATE);
2602
2603 set_od_failed:
2604         mutex_unlock(&(smu->mutex));
2605
2606         return ret;
2607 }
2608
2609 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2610                                      enum PP_OD_DPM_TABLE_COMMAND type,
2611                                      long *input, uint32_t size)
2612 {
2613         struct smu_table_context *table_context = &smu->smu_table;
2614         OverDriveTable_t *od_table =
2615                 (OverDriveTable_t *)(table_context->overdrive_table);
2616         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2617         struct vega20_dpm_table *dpm_table = NULL;
2618         struct vega20_single_dpm_table *single_dpm_table;
2619         struct vega20_od8_settings *od8_settings =
2620                 (struct vega20_od8_settings *)smu->od_settings;
2621         struct pp_clock_levels_with_latency clocks;
2622         int32_t input_index, input_clk, input_vol, i;
2623         int od8_id;
2624         int ret = 0;
2625
2626         dpm_table = smu_dpm->dpm_context;
2627
2628         if (!input) {
2629                 pr_warn("NULL user input for clock and voltage\n");
2630                 return -EINVAL;
2631         }
2632
2633         switch (type) {
2634         case PP_OD_EDIT_SCLK_VDDC_TABLE:
2635                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2636                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2637                         pr_info("Sclk min/max frequency overdrive not supported\n");
2638                         return -EOPNOTSUPP;
2639                 }
2640
2641                 for (i = 0; i < size; i += 2) {
2642                         if (i + 2 > size) {
2643                                 pr_info("invalid number of input parameters %d\n", size);
2644                                 return -EINVAL;
2645                         }
2646
2647                         input_index = input[i];
2648                         input_clk = input[i + 1];
2649
2650                         if (input_index != 0 && input_index != 1) {
2651                                 pr_info("Invalid index %d\n", input_index);
2652                                 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2653                                 return -EINVAL;
2654                         }
2655
2656                         if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2657                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2658                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2659                                         input_clk,
2660                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2661                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2662                                 return -EINVAL;
2663                         }
2664
2665                         if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2666                                 od_table->GfxclkFmin = input_clk;
2667                                 od8_settings->od_gfxclk_update = true;
2668                         } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2669                                 od_table->GfxclkFmax = input_clk;
2670                                 od8_settings->od_gfxclk_update = true;
2671                         }
2672                 }
2673
2674                 break;
2675
2676         case PP_OD_EDIT_MCLK_VDDC_TABLE:
2677                 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2678                         pr_info("Mclk max frequency overdrive not supported\n");
2679                         return -EOPNOTSUPP;
2680                 }
2681
2682                 single_dpm_table = &(dpm_table->mem_table);
2683                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2684                 if (ret) {
2685                         pr_err("Attempt to get memory clk levels Failed!");
2686                         return ret;
2687                 }
2688
2689                 for (i = 0; i < size; i += 2) {
2690                         if (i + 2 > size) {
2691                                 pr_info("invalid number of input parameters %d\n",
2692                                          size);
2693                                 return -EINVAL;
2694                         }
2695
2696                         input_index = input[i];
2697                         input_clk = input[i + 1];
2698
2699                         if (input_index != 1) {
2700                                 pr_info("Invalid index %d\n", input_index);
2701                                 pr_info("Support max Mclk frequency setting only which index by 1\n");
2702                                 return -EINVAL;
2703                         }
2704
2705                         if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2706                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2707                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2708                                         input_clk,
2709                                         clocks.data[0].clocks_in_khz / 1000,
2710                                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2711                                 return -EINVAL;
2712                         }
2713
2714                         if (input_index == 1 && od_table->UclkFmax != input_clk) {
2715                                 od8_settings->od_gfxclk_update = true;
2716                                 od_table->UclkFmax = input_clk;
2717                         }
2718                 }
2719
2720                 break;
2721
2722         case PP_OD_EDIT_VDDC_CURVE:
2723                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2724                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2725                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2726                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2727                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2728                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2729                         pr_info("Voltage curve calibrate not supported\n");
2730                         return -EOPNOTSUPP;
2731                 }
2732
2733                 for (i = 0; i < size; i += 3) {
2734                         if (i + 3 > size) {
2735                                 pr_info("invalid number of input parameters %d\n",
2736                                         size);
2737                                 return -EINVAL;
2738                         }
2739
2740                         input_index = input[i];
2741                         input_clk = input[i + 1];
2742                         input_vol = input[i + 2];
2743
2744                         if (input_index > 2) {
2745                                 pr_info("Setting for point %d is not supported\n",
2746                                         input_index + 1);
2747                                 pr_info("Three supported points index by 0, 1, 2\n");
2748                                 return -EINVAL;
2749                         }
2750
2751                         od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2752                         if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2753                             input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2754                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2755                                         input_clk,
2756                                         od8_settings->od8_settings_array[od8_id].min_value,
2757                                         od8_settings->od8_settings_array[od8_id].max_value);
2758                                 return -EINVAL;
2759                         }
2760
2761                         od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2762                         if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2763                             input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2764                                 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2765                                         input_vol,
2766                                         od8_settings->od8_settings_array[od8_id].min_value,
2767                                         od8_settings->od8_settings_array[od8_id].max_value);
2768                                 return -EINVAL;
2769                         }
2770
2771                         switch (input_index) {
2772                         case 0:
2773                                 od_table->GfxclkFreq1 = input_clk;
2774                                 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2775                                 break;
2776                         case 1:
2777                                 od_table->GfxclkFreq2 = input_clk;
2778                                 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2779                                 break;
2780                         case 2:
2781                                 od_table->GfxclkFreq3 = input_clk;
2782                                 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2783                                 break;
2784                         }
2785                 }
2786
2787                 break;
2788
2789         case PP_OD_RESTORE_DEFAULT_TABLE:
2790                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, false);
2791                 if (ret) {
2792                         pr_err("Failed to export over drive table!\n");
2793                         return ret;
2794                 }
2795
2796                 break;
2797
2798         case PP_OD_COMMIT_DPM_TABLE:
2799                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
2800                 if (ret) {
2801                         pr_err("Failed to import over drive table!\n");
2802                         return ret;
2803                 }
2804
2805                 /* retrieve updated gfxclk table */
2806                 if (od8_settings->od_gfxclk_update) {
2807                         od8_settings->od_gfxclk_update = false;
2808                         single_dpm_table = &(dpm_table->gfx_table);
2809
2810                         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
2811                                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2812                                                                   PPCLK_GFXCLK);
2813                                 if (ret) {
2814                                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2815                                         return ret;
2816                                 }
2817                         } else {
2818                                 single_dpm_table->count = 1;
2819                                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2820                         }
2821                 }
2822
2823                 break;
2824
2825         default:
2826                 return -EINVAL;
2827         }
2828
2829         if (type == PP_OD_COMMIT_DPM_TABLE) {
2830                 mutex_lock(&(smu->mutex));
2831                 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2832                                       AMD_PP_TASK_READJUST_POWER_STATE);
2833                 mutex_unlock(&(smu->mutex));
2834         }
2835
2836         return ret;
2837 }
2838
2839 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
2840 {
2841         if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
2842                 return 0;
2843
2844         if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
2845                 return 0;
2846
2847         return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
2848 }
2849
2850 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
2851 {
2852         if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
2853                 return 0;
2854
2855         if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
2856                 return 0;
2857
2858         return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
2859 }
2860
2861 static bool vega20_is_dpm_running(struct smu_context *smu)
2862 {
2863         int ret = 0;
2864         uint32_t feature_mask[2];
2865         unsigned long feature_enabled;
2866         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2867         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
2868                            ((uint64_t)feature_mask[1] << 32));
2869         return !!(feature_enabled & SMC_DPM_FEATURE);
2870 }
2871
2872 static int vega20_set_thermal_fan_table(struct smu_context *smu)
2873 {
2874         int ret;
2875         struct smu_table_context *table_context = &smu->smu_table;
2876         PPTable_t *pptable = table_context->driver_pptable;
2877
2878         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
2879                         (uint32_t)pptable->FanTargetTemperature);
2880
2881         return ret;
2882 }
2883
2884 static int vega20_get_fan_speed_rpm(struct smu_context *smu,
2885                                     uint32_t *speed)
2886 {
2887         int ret;
2888
2889         ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
2890
2891         if (ret) {
2892                 pr_err("Attempt to get current RPM from SMC Failed!\n");
2893                 return ret;
2894         }
2895
2896         smu_read_smc_arg(smu, speed);
2897
2898         return 0;
2899 }
2900
2901 static int vega20_get_fan_speed_percent(struct smu_context *smu,
2902                                         uint32_t *speed)
2903 {
2904         int ret = 0;
2905         uint32_t current_rpm = 0, percent = 0;
2906         PPTable_t *pptable = smu->smu_table.driver_pptable;
2907
2908         ret = vega20_get_fan_speed_rpm(smu, &current_rpm);
2909         if (ret)
2910                 return ret;
2911
2912         percent = current_rpm * 100 / pptable->FanMaximumRpm;
2913         *speed = percent > 100 ? 100 : percent;
2914
2915         return 0;
2916 }
2917
2918 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
2919 {
2920         uint32_t smu_version;
2921         int ret = 0;
2922         SmuMetrics_t metrics;
2923
2924         if (!value)
2925                 return -EINVAL;
2926
2927         ret = vega20_get_metrics_table(smu, &metrics);
2928         if (ret)
2929                 return ret;
2930
2931         ret = smu_get_smc_version(smu, NULL, &smu_version);
2932         if (ret)
2933                 return ret;
2934
2935         /* For the 40.46 release, they changed the value name */
2936         if (smu_version == 0x282e00)
2937                 *value = metrics.AverageSocketPower << 8;
2938         else
2939                 *value = metrics.CurrSocketPower << 8;
2940
2941         return 0;
2942 }
2943
2944 static int vega20_get_current_activity_percent(struct smu_context *smu,
2945                                                enum amd_pp_sensors sensor,
2946                                                uint32_t *value)
2947 {
2948         int ret = 0;
2949         SmuMetrics_t metrics;
2950
2951         if (!value)
2952                 return -EINVAL;
2953
2954         ret = vega20_get_metrics_table(smu, &metrics);
2955         if (ret)
2956                 return ret;
2957
2958         switch (sensor) {
2959         case AMDGPU_PP_SENSOR_GPU_LOAD:
2960                 *value = metrics.AverageGfxActivity;
2961                 break;
2962         case AMDGPU_PP_SENSOR_MEM_LOAD:
2963                 *value = metrics.AverageUclkActivity;
2964                 break;
2965         default:
2966                 pr_err("Invalid sensor for retrieving clock activity\n");
2967                 return -EINVAL;
2968         }
2969
2970         return 0;
2971 }
2972
2973 static int vega20_thermal_get_temperature(struct smu_context *smu,
2974                                              enum amd_pp_sensors sensor,
2975                                              uint32_t *value)
2976 {
2977         struct amdgpu_device *adev = smu->adev;
2978         SmuMetrics_t metrics;
2979         uint32_t temp = 0;
2980         int ret = 0;
2981
2982         if (!value)
2983                 return -EINVAL;
2984
2985         ret = vega20_get_metrics_table(smu, &metrics);
2986         if (ret)
2987                 return ret;
2988
2989         switch (sensor) {
2990         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2991                 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
2992                 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
2993                                 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
2994
2995                 temp = temp & 0x1ff;
2996                 temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2997
2998                 *value = temp;
2999                 break;
3000         case AMDGPU_PP_SENSOR_EDGE_TEMP:
3001                 *value = metrics.TemperatureEdge *
3002                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3003                 break;
3004         case AMDGPU_PP_SENSOR_MEM_TEMP:
3005                 *value = metrics.TemperatureHBM *
3006                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3007                 break;
3008         default:
3009                 pr_err("Invalid sensor for retrieving temp\n");
3010                 return -EINVAL;
3011         }
3012
3013         return 0;
3014 }
3015 static int vega20_read_sensor(struct smu_context *smu,
3016                                  enum amd_pp_sensors sensor,
3017                                  void *data, uint32_t *size)
3018 {
3019         int ret = 0;
3020         struct smu_table_context *table_context = &smu->smu_table;
3021         PPTable_t *pptable = table_context->driver_pptable;
3022
3023         if(!data || !size)
3024                 return -EINVAL;
3025
3026         mutex_lock(&smu->sensor_lock);
3027         switch (sensor) {
3028         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
3029                 *(uint32_t *)data = pptable->FanMaximumRpm;
3030                 *size = 4;
3031                 break;
3032         case AMDGPU_PP_SENSOR_MEM_LOAD:
3033         case AMDGPU_PP_SENSOR_GPU_LOAD:
3034                 ret = vega20_get_current_activity_percent(smu,
3035                                                 sensor,
3036                                                 (uint32_t *)data);
3037                 *size = 4;
3038                 break;
3039         case AMDGPU_PP_SENSOR_GPU_POWER:
3040                 ret = vega20_get_gpu_power(smu, (uint32_t *)data);
3041                 *size = 4;
3042                 break;
3043         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3044         case AMDGPU_PP_SENSOR_EDGE_TEMP:
3045         case AMDGPU_PP_SENSOR_MEM_TEMP:
3046                 ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
3047                 *size = 4;
3048                 break;
3049         default:
3050                 ret = smu_smc_read_sensor(smu, sensor, data, size);
3051         }
3052         mutex_unlock(&smu->sensor_lock);
3053
3054         return ret;
3055 }
3056
3057 static int vega20_set_watermarks_table(struct smu_context *smu,
3058                                        void *watermarks, struct
3059                                        dm_pp_wm_sets_with_clock_ranges_soc15
3060                                        *clock_ranges)
3061 {
3062         int i;
3063         Watermarks_t *table = watermarks;
3064
3065         if (!table || !clock_ranges)
3066                 return -EINVAL;
3067
3068         if (clock_ranges->num_wm_dmif_sets > 4 ||
3069             clock_ranges->num_wm_mcif_sets > 4)
3070                 return -EINVAL;
3071
3072         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
3073                 table->WatermarkRow[1][i].MinClock =
3074                         cpu_to_le16((uint16_t)
3075                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
3076                         1000));
3077                 table->WatermarkRow[1][i].MaxClock =
3078                         cpu_to_le16((uint16_t)
3079                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
3080                         1000));
3081                 table->WatermarkRow[1][i].MinUclk =
3082                         cpu_to_le16((uint16_t)
3083                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3084                         1000));
3085                 table->WatermarkRow[1][i].MaxUclk =
3086                         cpu_to_le16((uint16_t)
3087                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3088                         1000));
3089                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
3090                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
3091         }
3092
3093         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
3094                 table->WatermarkRow[0][i].MinClock =
3095                         cpu_to_le16((uint16_t)
3096                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
3097                         1000));
3098                 table->WatermarkRow[0][i].MaxClock =
3099                         cpu_to_le16((uint16_t)
3100                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
3101                         1000));
3102                 table->WatermarkRow[0][i].MinUclk =
3103                         cpu_to_le16((uint16_t)
3104                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3105                         1000));
3106                 table->WatermarkRow[0][i].MaxUclk =
3107                         cpu_to_le16((uint16_t)
3108                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3109                         1000));
3110                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
3111                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
3112         }
3113
3114         return 0;
3115 }
3116
3117 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
3118                                                 struct smu_temperature_range *range)
3119 {
3120         struct smu_table_context *table_context = &smu->smu_table;
3121         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
3122         PPTable_t *pptable = smu->smu_table.driver_pptable;
3123
3124         if (!range || !powerplay_table)
3125                 return -EINVAL;
3126
3127         range->max = powerplay_table->usSoftwareShutdownTemp *
3128                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3129         range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
3130                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3131         range->hotspot_crit_max = pptable->ThotspotLimit *
3132                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3133         range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
3134                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3135         range->mem_crit_max = pptable->ThbmLimit *
3136                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3137         range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM) *
3138                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3139
3140
3141         return 0;
3142 }
3143
3144 static const struct pptable_funcs vega20_ppt_funcs = {
3145         .tables_init = vega20_tables_init,
3146         .alloc_dpm_context = vega20_allocate_dpm_context,
3147         .store_powerplay_table = vega20_store_powerplay_table,
3148         .check_powerplay_table = vega20_check_powerplay_table,
3149         .append_powerplay_table = vega20_append_powerplay_table,
3150         .get_smu_msg_index = vega20_get_smu_msg_index,
3151         .get_smu_clk_index = vega20_get_smu_clk_index,
3152         .get_smu_feature_index = vega20_get_smu_feature_index,
3153         .get_smu_table_index = vega20_get_smu_table_index,
3154         .get_smu_power_index = vega20_get_pwr_src_index,
3155         .get_workload_type = vega20_get_workload_type,
3156         .run_afll_btc = vega20_run_btc_afll,
3157         .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
3158         .get_current_power_state = vega20_get_current_power_state,
3159         .set_default_dpm_table = vega20_set_default_dpm_table,
3160         .set_power_state = NULL,
3161         .populate_umd_state_clk = vega20_populate_umd_state_clk,
3162         .print_clk_levels = vega20_print_clk_levels,
3163         .force_clk_levels = vega20_force_clk_levels,
3164         .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
3165         .get_od_percentage = vega20_get_od_percentage,
3166         .get_power_profile_mode = vega20_get_power_profile_mode,
3167         .set_power_profile_mode = vega20_set_power_profile_mode,
3168         .set_od_percentage = vega20_set_od_percentage,
3169         .set_default_od_settings = vega20_set_default_od_settings,
3170         .od_edit_dpm_table = vega20_odn_edit_dpm_table,
3171         .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable,
3172         .dpm_set_vce_enable = vega20_dpm_set_vce_enable,
3173         .read_sensor = vega20_read_sensor,
3174         .pre_display_config_changed = vega20_pre_display_config_changed,
3175         .display_config_changed = vega20_display_config_changed,
3176         .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
3177         .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config,
3178         .force_dpm_limit_value = vega20_force_dpm_limit_value,
3179         .unforce_dpm_levels = vega20_unforce_dpm_levels,
3180         .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
3181         .is_dpm_running = vega20_is_dpm_running,
3182         .set_thermal_fan_table = vega20_set_thermal_fan_table,
3183         .get_fan_speed_percent = vega20_get_fan_speed_percent,
3184         .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
3185         .set_watermarks_table = vega20_set_watermarks_table,
3186         .get_thermal_temperature_range = vega20_get_thermal_temperature_range
3187 };
3188
3189 void vega20_set_ppt_funcs(struct smu_context *smu)
3190 {
3191         struct smu_table_context *smu_table = &smu->smu_table;
3192
3193         smu->ppt_funcs = &vega20_ppt_funcs;
3194         smu_table->table_count = TABLE_COUNT;
3195 }