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