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