]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drm/amdgpu/smu: add metrics table lock for vega20 (v2)
[linux.git] / drivers / gpu / drm / amd / powerplay / vega20_ppt.c
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #include "pp_debug.h"
25 #include <linux/firmware.h>
26 #include "amdgpu.h"
27 #include "amdgpu_smu.h"
28 #include "smu_internal.h"
29 #include "atomfirmware.h"
30 #include "amdgpu_atomfirmware.h"
31 #include "smu_v11_0.h"
32 #include "smu11_driver_if.h"
33 #include "soc15_common.h"
34 #include "atom.h"
35 #include "power_state.h"
36 #include "vega20_ppt.h"
37 #include "vega20_pptable.h"
38 #include "vega20_ppsmc.h"
39 #include "nbio/nbio_7_4_sh_mask.h"
40 #include "asic_reg/thm/thm_11_0_2_offset.h"
41 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
42
43 #define smnPCIE_LC_SPEED_CNTL                   0x11140290
44 #define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
45
46 #define CTF_OFFSET_EDGE                 5
47 #define CTF_OFFSET_HOTSPOT              5
48 #define CTF_OFFSET_HBM                  5
49
50 #define MSG_MAP(msg) \
51         [SMU_MSG_##msg] = {1, PPSMC_MSG_##msg}
52
53 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
54                          FEATURE_DPM_GFXCLK_MASK | \
55                          FEATURE_DPM_UCLK_MASK | \
56                          FEATURE_DPM_SOCCLK_MASK | \
57                          FEATURE_DPM_UVD_MASK | \
58                          FEATURE_DPM_VCE_MASK | \
59                          FEATURE_DPM_MP0CLK_MASK | \
60                          FEATURE_DPM_LINK_MASK | \
61                          FEATURE_DPM_DCEFCLK_MASK)
62
63 static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] = {
64         MSG_MAP(TestMessage),
65         MSG_MAP(GetSmuVersion),
66         MSG_MAP(GetDriverIfVersion),
67         MSG_MAP(SetAllowedFeaturesMaskLow),
68         MSG_MAP(SetAllowedFeaturesMaskHigh),
69         MSG_MAP(EnableAllSmuFeatures),
70         MSG_MAP(DisableAllSmuFeatures),
71         MSG_MAP(EnableSmuFeaturesLow),
72         MSG_MAP(EnableSmuFeaturesHigh),
73         MSG_MAP(DisableSmuFeaturesLow),
74         MSG_MAP(DisableSmuFeaturesHigh),
75         MSG_MAP(GetEnabledSmuFeaturesLow),
76         MSG_MAP(GetEnabledSmuFeaturesHigh),
77         MSG_MAP(SetWorkloadMask),
78         MSG_MAP(SetPptLimit),
79         MSG_MAP(SetDriverDramAddrHigh),
80         MSG_MAP(SetDriverDramAddrLow),
81         MSG_MAP(SetToolsDramAddrHigh),
82         MSG_MAP(SetToolsDramAddrLow),
83         MSG_MAP(TransferTableSmu2Dram),
84         MSG_MAP(TransferTableDram2Smu),
85         MSG_MAP(UseDefaultPPTable),
86         MSG_MAP(UseBackupPPTable),
87         MSG_MAP(RunBtc),
88         MSG_MAP(RequestI2CBus),
89         MSG_MAP(ReleaseI2CBus),
90         MSG_MAP(SetFloorSocVoltage),
91         MSG_MAP(SoftReset),
92         MSG_MAP(StartBacoMonitor),
93         MSG_MAP(CancelBacoMonitor),
94         MSG_MAP(EnterBaco),
95         MSG_MAP(SetSoftMinByFreq),
96         MSG_MAP(SetSoftMaxByFreq),
97         MSG_MAP(SetHardMinByFreq),
98         MSG_MAP(SetHardMaxByFreq),
99         MSG_MAP(GetMinDpmFreq),
100         MSG_MAP(GetMaxDpmFreq),
101         MSG_MAP(GetDpmFreqByIndex),
102         MSG_MAP(GetDpmClockFreq),
103         MSG_MAP(GetSsVoltageByDpm),
104         MSG_MAP(SetMemoryChannelConfig),
105         MSG_MAP(SetGeminiMode),
106         MSG_MAP(SetGeminiApertureHigh),
107         MSG_MAP(SetGeminiApertureLow),
108         MSG_MAP(SetMinLinkDpmByIndex),
109         MSG_MAP(OverridePcieParameters),
110         MSG_MAP(OverDriveSetPercentage),
111         MSG_MAP(SetMinDeepSleepDcefclk),
112         MSG_MAP(ReenableAcDcInterrupt),
113         MSG_MAP(NotifyPowerSource),
114         MSG_MAP(SetUclkFastSwitch),
115         MSG_MAP(SetUclkDownHyst),
116         MSG_MAP(GetCurrentRpm),
117         MSG_MAP(SetVideoFps),
118         MSG_MAP(SetTjMax),
119         MSG_MAP(SetFanTemperatureTarget),
120         MSG_MAP(PrepareMp1ForUnload),
121         MSG_MAP(DramLogSetDramAddrHigh),
122         MSG_MAP(DramLogSetDramAddrLow),
123         MSG_MAP(DramLogSetDramSize),
124         MSG_MAP(SetFanMaxRpm),
125         MSG_MAP(SetFanMinPwm),
126         MSG_MAP(ConfigureGfxDidt),
127         MSG_MAP(NumOfDisplays),
128         MSG_MAP(RemoveMargins),
129         MSG_MAP(ReadSerialNumTop32),
130         MSG_MAP(ReadSerialNumBottom32),
131         MSG_MAP(SetSystemVirtualDramAddrHigh),
132         MSG_MAP(SetSystemVirtualDramAddrLow),
133         MSG_MAP(WaflTest),
134         MSG_MAP(SetFclkGfxClkRatio),
135         MSG_MAP(AllowGfxOff),
136         MSG_MAP(DisallowGfxOff),
137         MSG_MAP(GetPptLimit),
138         MSG_MAP(GetDcModeMaxDpmFreq),
139         MSG_MAP(GetDebugData),
140         MSG_MAP(SetXgmiMode),
141         MSG_MAP(RunAfllBtc),
142         MSG_MAP(ExitBaco),
143         MSG_MAP(PrepareMp1ForReset),
144         MSG_MAP(PrepareMp1ForShutdown),
145         MSG_MAP(SetMGpuFanBoostLimitRpm),
146         MSG_MAP(GetAVFSVoltageByDpm),
147         MSG_MAP(DFCstateControl),
148 };
149
150 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = {
151         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
152         CLK_MAP(VCLK, PPCLK_VCLK),
153         CLK_MAP(DCLK, PPCLK_DCLK),
154         CLK_MAP(ECLK, PPCLK_ECLK),
155         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
156         CLK_MAP(UCLK, PPCLK_UCLK),
157         CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
158         CLK_MAP(DISPCLK, PPCLK_DISPCLK),
159         CLK_MAP(PIXCLK, PPCLK_PIXCLK),
160         CLK_MAP(PHYCLK, PPCLK_PHYCLK),
161         CLK_MAP(FCLK, PPCLK_FCLK),
162 };
163
164 static struct smu_11_0_cmn2aisc_mapping vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
165         FEA_MAP(DPM_PREFETCHER),
166         FEA_MAP(DPM_GFXCLK),
167         FEA_MAP(DPM_UCLK),
168         FEA_MAP(DPM_SOCCLK),
169         FEA_MAP(DPM_UVD),
170         FEA_MAP(DPM_VCE),
171         FEA_MAP(ULV),
172         FEA_MAP(DPM_MP0CLK),
173         FEA_MAP(DPM_LINK),
174         FEA_MAP(DPM_DCEFCLK),
175         FEA_MAP(DS_GFXCLK),
176         FEA_MAP(DS_SOCCLK),
177         FEA_MAP(DS_LCLK),
178         FEA_MAP(PPT),
179         FEA_MAP(TDC),
180         FEA_MAP(THERMAL),
181         FEA_MAP(GFX_PER_CU_CG),
182         FEA_MAP(RM),
183         FEA_MAP(DS_DCEFCLK),
184         FEA_MAP(ACDC),
185         FEA_MAP(VR0HOT),
186         FEA_MAP(VR1HOT),
187         FEA_MAP(FW_CTF),
188         FEA_MAP(LED_DISPLAY),
189         FEA_MAP(FAN_CONTROL),
190         FEA_MAP(GFX_EDC),
191         FEA_MAP(GFXOFF),
192         FEA_MAP(CG),
193         FEA_MAP(DPM_FCLK),
194         FEA_MAP(DS_FCLK),
195         FEA_MAP(DS_MP1CLK),
196         FEA_MAP(DS_MP0CLK),
197         FEA_MAP(XGMI),
198 };
199
200 static struct smu_11_0_cmn2aisc_mapping vega20_table_map[SMU_TABLE_COUNT] = {
201         TAB_MAP(PPTABLE),
202         TAB_MAP(WATERMARKS),
203         TAB_MAP(AVFS),
204         TAB_MAP(AVFS_PSM_DEBUG),
205         TAB_MAP(AVFS_FUSE_OVERRIDE),
206         TAB_MAP(PMSTATUSLOG),
207         TAB_MAP(SMU_METRICS),
208         TAB_MAP(DRIVER_SMU_CONFIG),
209         TAB_MAP(ACTIVITY_MONITOR_COEFF),
210         TAB_MAP(OVERDRIVE),
211 };
212
213 static struct smu_11_0_cmn2aisc_mapping vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
214         PWR_MAP(AC),
215         PWR_MAP(DC),
216 };
217
218 static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
219         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_DEFAULT_BIT),
220         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
221         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
222         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
223         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
224         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
225         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
226 };
227
228 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
229 {
230         struct smu_11_0_cmn2aisc_mapping mapping;
231
232         if (index >= SMU_TABLE_COUNT)
233                 return -EINVAL;
234
235         mapping = vega20_table_map[index];
236         if (!(mapping.valid_mapping)) {
237                 return -EINVAL;
238         }
239
240         return mapping.map_to;
241 }
242
243 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
244 {
245         struct smu_11_0_cmn2aisc_mapping mapping;
246
247         if (index >= SMU_POWER_SOURCE_COUNT)
248                 return -EINVAL;
249
250         mapping = vega20_pwr_src_map[index];
251         if (!(mapping.valid_mapping)) {
252                 return -EINVAL;
253         }
254
255         return mapping.map_to;
256 }
257
258 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
259 {
260         struct smu_11_0_cmn2aisc_mapping mapping;
261
262         if (index >= SMU_FEATURE_COUNT)
263                 return -EINVAL;
264
265         mapping = vega20_feature_mask_map[index];
266         if (!(mapping.valid_mapping)) {
267                 return -EINVAL;
268         }
269
270         return mapping.map_to;
271 }
272
273 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
274 {
275         struct smu_11_0_cmn2aisc_mapping mapping;
276
277         if (index >= SMU_CLK_COUNT)
278                 return -EINVAL;
279
280         mapping = vega20_clk_map[index];
281         if (!(mapping.valid_mapping)) {
282                 return -EINVAL;
283         }
284
285         return mapping.map_to;
286 }
287
288 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
289 {
290         struct smu_11_0_cmn2aisc_mapping mapping;
291
292         if (index >= SMU_MSG_MAX_COUNT)
293                 return -EINVAL;
294
295         mapping = vega20_message_map[index];
296         if (!(mapping.valid_mapping)) {
297                 return -EINVAL;
298         }
299
300         return mapping.map_to;
301 }
302
303 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
304 {
305         struct smu_11_0_cmn2aisc_mapping mapping;
306
307         if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
308                 return -EINVAL;
309
310         mapping = vega20_workload_map[profile];
311         if (!(mapping.valid_mapping)) {
312                 return -EINVAL;
313         }
314
315         return mapping.map_to;
316 }
317
318 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
319 {
320         struct smu_table_context *smu_table = &smu->smu_table;
321
322         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
323                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
324         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
325                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
326         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
327                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
328         SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
329                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
330         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
331                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
332         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
333                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
334                        AMDGPU_GEM_DOMAIN_VRAM);
335
336         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
337         if (!smu_table->metrics_table)
338                 return -ENOMEM;
339         smu_table->metrics_time = 0;
340
341         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         mutex_lock(&smu->metrics_lock);
1682         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
1683                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
1684                                 (void *)smu_table->metrics_table, false);
1685                 if (ret) {
1686                         pr_info("Failed to export SMU metrics table!\n");
1687                         mutex_unlock(&smu->metrics_lock);
1688                         return ret;
1689                 }
1690                 smu_table->metrics_time = jiffies;
1691         }
1692
1693         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
1694         mutex_unlock(&smu->metrics_lock);
1695
1696         return ret;
1697 }
1698
1699 static int vega20_set_default_od_settings(struct smu_context *smu,
1700                                           bool initialize)
1701 {
1702         struct smu_table_context *table_context = &smu->smu_table;
1703         int ret;
1704
1705         if (initialize) {
1706                 if (table_context->overdrive_table)
1707                         return -EINVAL;
1708
1709                 table_context->overdrive_table = kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL);
1710
1711                 if (!table_context->overdrive_table)
1712                         return -ENOMEM;
1713
1714                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
1715                                        table_context->overdrive_table, false);
1716                 if (ret) {
1717                         pr_err("Failed to export over drive table!\n");
1718                         return ret;
1719                 }
1720
1721                 ret = vega20_set_default_od8_setttings(smu);
1722                 if (ret)
1723                         return ret;
1724         }
1725
1726         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
1727                                table_context->overdrive_table, true);
1728         if (ret) {
1729                 pr_err("Failed to import over drive table!\n");
1730                 return ret;
1731         }
1732
1733         return 0;
1734 }
1735
1736 static int vega20_get_od_percentage(struct smu_context *smu,
1737                                     enum smu_clk_type clk_type)
1738 {
1739         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1740         struct vega20_dpm_table *dpm_table = NULL;
1741         struct vega20_dpm_table *golden_table = NULL;
1742         struct vega20_single_dpm_table *single_dpm_table;
1743         struct vega20_single_dpm_table *golden_dpm_table;
1744         int value, golden_value;
1745
1746         dpm_table = smu_dpm->dpm_context;
1747         golden_table = smu_dpm->golden_dpm_context;
1748
1749         switch (clk_type) {
1750         case SMU_OD_SCLK:
1751                 single_dpm_table = &(dpm_table->gfx_table);
1752                 golden_dpm_table = &(golden_table->gfx_table);
1753                 break;
1754         case SMU_OD_MCLK:
1755                 single_dpm_table = &(dpm_table->mem_table);
1756                 golden_dpm_table = &(golden_table->mem_table);
1757                 break;
1758         default:
1759                 return -EINVAL;
1760                 break;
1761         }
1762
1763         value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value;
1764         golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
1765
1766         value -= golden_value;
1767         value = DIV_ROUND_UP(value * 100, golden_value);
1768
1769         return value;
1770 }
1771
1772 static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
1773 {
1774         DpmActivityMonitorCoeffInt_t activity_monitor;
1775         uint32_t i, size = 0;
1776         int16_t workload_type = 0;
1777         static const char *profile_name[] = {
1778                                         "BOOTUP_DEFAULT",
1779                                         "3D_FULL_SCREEN",
1780                                         "POWER_SAVING",
1781                                         "VIDEO",
1782                                         "VR",
1783                                         "COMPUTE",
1784                                         "CUSTOM"};
1785         static const char *title[] = {
1786                         "PROFILE_INDEX(NAME)",
1787                         "CLOCK_TYPE(NAME)",
1788                         "FPS",
1789                         "UseRlcBusy",
1790                         "MinActiveFreqType",
1791                         "MinActiveFreq",
1792                         "BoosterFreqType",
1793                         "BoosterFreq",
1794                         "PD_Data_limit_c",
1795                         "PD_Data_error_coeff",
1796                         "PD_Data_error_rate_coeff"};
1797         int result = 0;
1798
1799         if (!smu->pm_enabled || !buf)
1800                 return -EINVAL;
1801
1802         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1803                         title[0], title[1], title[2], title[3], title[4], title[5],
1804                         title[6], title[7], title[8], title[9], title[10]);
1805
1806         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1807                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1808                 workload_type = smu_workload_get_type(smu, i);
1809                 if (workload_type < 0)
1810                         return -EINVAL;
1811
1812                 result = smu_update_table(smu,
1813                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1814                                           (void *)(&activity_monitor), false);
1815                 if (result) {
1816                         pr_err("[%s] Failed to get activity monitor!", __func__);
1817                         return result;
1818                 }
1819
1820                 size += sprintf(buf + size, "%2d %14s%s:\n",
1821                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1822
1823                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1824                         " ",
1825                         0,
1826                         "GFXCLK",
1827                         activity_monitor.Gfx_FPS,
1828                         activity_monitor.Gfx_UseRlcBusy,
1829                         activity_monitor.Gfx_MinActiveFreqType,
1830                         activity_monitor.Gfx_MinActiveFreq,
1831                         activity_monitor.Gfx_BoosterFreqType,
1832                         activity_monitor.Gfx_BoosterFreq,
1833                         activity_monitor.Gfx_PD_Data_limit_c,
1834                         activity_monitor.Gfx_PD_Data_error_coeff,
1835                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
1836
1837                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1838                         " ",
1839                         1,
1840                         "SOCCLK",
1841                         activity_monitor.Soc_FPS,
1842                         activity_monitor.Soc_UseRlcBusy,
1843                         activity_monitor.Soc_MinActiveFreqType,
1844                         activity_monitor.Soc_MinActiveFreq,
1845                         activity_monitor.Soc_BoosterFreqType,
1846                         activity_monitor.Soc_BoosterFreq,
1847                         activity_monitor.Soc_PD_Data_limit_c,
1848                         activity_monitor.Soc_PD_Data_error_coeff,
1849                         activity_monitor.Soc_PD_Data_error_rate_coeff);
1850
1851                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1852                         " ",
1853                         2,
1854                         "UCLK",
1855                         activity_monitor.Mem_FPS,
1856                         activity_monitor.Mem_UseRlcBusy,
1857                         activity_monitor.Mem_MinActiveFreqType,
1858                         activity_monitor.Mem_MinActiveFreq,
1859                         activity_monitor.Mem_BoosterFreqType,
1860                         activity_monitor.Mem_BoosterFreq,
1861                         activity_monitor.Mem_PD_Data_limit_c,
1862                         activity_monitor.Mem_PD_Data_error_coeff,
1863                         activity_monitor.Mem_PD_Data_error_rate_coeff);
1864
1865                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1866                         " ",
1867                         3,
1868                         "FCLK",
1869                         activity_monitor.Fclk_FPS,
1870                         activity_monitor.Fclk_UseRlcBusy,
1871                         activity_monitor.Fclk_MinActiveFreqType,
1872                         activity_monitor.Fclk_MinActiveFreq,
1873                         activity_monitor.Fclk_BoosterFreqType,
1874                         activity_monitor.Fclk_BoosterFreq,
1875                         activity_monitor.Fclk_PD_Data_limit_c,
1876                         activity_monitor.Fclk_PD_Data_error_coeff,
1877                         activity_monitor.Fclk_PD_Data_error_rate_coeff);
1878         }
1879
1880         return size;
1881 }
1882
1883 static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1884 {
1885         DpmActivityMonitorCoeffInt_t activity_monitor;
1886         int workload_type = 0, ret = 0;
1887
1888         smu->power_profile_mode = input[size];
1889
1890         if (!smu->pm_enabled)
1891                 return ret;
1892         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1893                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1894                 return -EINVAL;
1895         }
1896
1897         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1898                 ret = smu_update_table(smu,
1899                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1900                                        (void *)(&activity_monitor), false);
1901                 if (ret) {
1902                         pr_err("[%s] Failed to get activity monitor!", __func__);
1903                         return ret;
1904                 }
1905
1906                 switch (input[0]) {
1907                 case 0: /* Gfxclk */
1908                         activity_monitor.Gfx_FPS = input[1];
1909                         activity_monitor.Gfx_UseRlcBusy = input[2];
1910                         activity_monitor.Gfx_MinActiveFreqType = input[3];
1911                         activity_monitor.Gfx_MinActiveFreq = input[4];
1912                         activity_monitor.Gfx_BoosterFreqType = input[5];
1913                         activity_monitor.Gfx_BoosterFreq = input[6];
1914                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
1915                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1916                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1917                         break;
1918                 case 1: /* Socclk */
1919                         activity_monitor.Soc_FPS = input[1];
1920                         activity_monitor.Soc_UseRlcBusy = input[2];
1921                         activity_monitor.Soc_MinActiveFreqType = input[3];
1922                         activity_monitor.Soc_MinActiveFreq = input[4];
1923                         activity_monitor.Soc_BoosterFreqType = input[5];
1924                         activity_monitor.Soc_BoosterFreq = input[6];
1925                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1926                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1927                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1928                         break;
1929                 case 2: /* Uclk */
1930                         activity_monitor.Mem_FPS = input[1];
1931                         activity_monitor.Mem_UseRlcBusy = input[2];
1932                         activity_monitor.Mem_MinActiveFreqType = input[3];
1933                         activity_monitor.Mem_MinActiveFreq = input[4];
1934                         activity_monitor.Mem_BoosterFreqType = input[5];
1935                         activity_monitor.Mem_BoosterFreq = input[6];
1936                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1937                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1938                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1939                         break;
1940                 case 3: /* Fclk */
1941                         activity_monitor.Fclk_FPS = input[1];
1942                         activity_monitor.Fclk_UseRlcBusy = input[2];
1943                         activity_monitor.Fclk_MinActiveFreqType = input[3];
1944                         activity_monitor.Fclk_MinActiveFreq = input[4];
1945                         activity_monitor.Fclk_BoosterFreqType = input[5];
1946                         activity_monitor.Fclk_BoosterFreq = input[6];
1947                         activity_monitor.Fclk_PD_Data_limit_c = input[7];
1948                         activity_monitor.Fclk_PD_Data_error_coeff = input[8];
1949                         activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
1950                         break;
1951                 }
1952
1953                 ret = smu_update_table(smu,
1954                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1955                                        (void *)(&activity_monitor), true);
1956                 if (ret) {
1957                         pr_err("[%s] Failed to set activity monitor!", __func__);
1958                         return ret;
1959                 }
1960         }
1961
1962         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1963         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1964         if (workload_type < 0)
1965                 return -EINVAL;
1966         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1967                                     1 << workload_type);
1968
1969         return ret;
1970 }
1971
1972 static int
1973 vega20_get_profiling_clk_mask(struct smu_context *smu,
1974                               enum amd_dpm_forced_level level,
1975                               uint32_t *sclk_mask,
1976                               uint32_t *mclk_mask,
1977                               uint32_t *soc_mask)
1978 {
1979         struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
1980         struct vega20_single_dpm_table *gfx_dpm_table;
1981         struct vega20_single_dpm_table *mem_dpm_table;
1982         struct vega20_single_dpm_table *soc_dpm_table;
1983
1984         if (!smu->smu_dpm.dpm_context)
1985                 return -EINVAL;
1986
1987         gfx_dpm_table = &dpm_table->gfx_table;
1988         mem_dpm_table = &dpm_table->mem_table;
1989         soc_dpm_table = &dpm_table->soc_table;
1990
1991         *sclk_mask = 0;
1992         *mclk_mask = 0;
1993         *soc_mask  = 0;
1994
1995         if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1996             mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
1997             soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
1998                 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
1999                 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2000                 *soc_mask  = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2001         }
2002
2003         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2004                 *sclk_mask = 0;
2005         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2006                 *mclk_mask = 0;
2007         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2008                 *sclk_mask = gfx_dpm_table->count - 1;
2009                 *mclk_mask = mem_dpm_table->count - 1;
2010                 *soc_mask  = soc_dpm_table->count - 1;
2011         }
2012
2013         return 0;
2014 }
2015
2016 static int
2017 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu,
2018                                      struct vega20_single_dpm_table *dpm_table)
2019 {
2020         int ret = 0;
2021         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2022         if (!smu_dpm_ctx->dpm_context)
2023                 return -EINVAL;
2024
2025         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2026                 if (dpm_table->count <= 0) {
2027                         pr_err("[%s] Dpm table has no entry!", __func__);
2028                                 return -EINVAL;
2029                 }
2030
2031                 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) {
2032                         pr_err("[%s] Dpm table has too many entries!", __func__);
2033                                 return -EINVAL;
2034                 }
2035
2036                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2037                 ret = smu_send_smc_msg_with_param(smu,
2038                                 SMU_MSG_SetHardMinByFreq,
2039                                 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level);
2040                 if (ret) {
2041                         pr_err("[%s] Set hard min uclk failed!", __func__);
2042                                 return ret;
2043                 }
2044         }
2045
2046         return ret;
2047 }
2048
2049 static int vega20_pre_display_config_changed(struct smu_context *smu)
2050 {
2051         int ret = 0;
2052         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2053
2054         if (!smu->smu_dpm.dpm_context)
2055                 return -EINVAL;
2056
2057         smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
2058         ret = vega20_set_uclk_to_highest_dpm_level(smu,
2059                                                    &dpm_table->mem_table);
2060         if (ret)
2061                 pr_err("Failed to set uclk to highest dpm level");
2062         return ret;
2063 }
2064
2065 static int vega20_display_config_changed(struct smu_context *smu)
2066 {
2067         int ret = 0;
2068
2069         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2070             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
2071                 ret = smu_write_watermarks_table(smu);
2072                 if (ret) {
2073                         pr_err("Failed to update WMTABLE!");
2074                         return ret;
2075                 }
2076                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
2077         }
2078
2079         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2080             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
2081             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
2082                 smu_send_smc_msg_with_param(smu,
2083                                             SMU_MSG_NumOfDisplays,
2084                                             smu->display_config->num_display);
2085         }
2086
2087         return ret;
2088 }
2089
2090 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu)
2091 {
2092         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2093         struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context);
2094         struct vega20_single_dpm_table *dpm_table;
2095         bool vblank_too_short = false;
2096         bool disable_mclk_switching;
2097         uint32_t i, latency;
2098
2099         disable_mclk_switching = ((1 < smu->display_config->num_display) &&
2100                                   !smu->display_config->multi_monitor_in_sync) || vblank_too_short;
2101         latency = smu->display_config->dce_tolerable_mclk_in_active_latency;
2102
2103         /* gfxclk */
2104         dpm_table = &(dpm_ctx->gfx_table);
2105         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2106         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2107         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2108         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2109
2110                 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
2111                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2112                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
2113                 }
2114
2115                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2116                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2117                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2118                 }
2119
2120                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2121                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2122                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2123                 }
2124
2125         /* memclk */
2126         dpm_table = &(dpm_ctx->mem_table);
2127         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2128         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2129         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2130         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2131
2132                 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
2133                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2134                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
2135                 }
2136
2137                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2138                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2139                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2140                 }
2141
2142                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2143                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2144                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2145                 }
2146
2147         /* honour DAL's UCLK Hardmin */
2148         if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100))
2149                 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100;
2150
2151         /* Hardmin is dependent on displayconfig */
2152         if (disable_mclk_switching) {
2153                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2154                 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) {
2155                         if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) {
2156                                 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) {
2157                                         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
2158                                         break;
2159                                 }
2160                         }
2161                 }
2162         }
2163
2164         if (smu->display_config->nb_pstate_switch_disable)
2165                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2166
2167         /* vclk */
2168         dpm_table = &(dpm_ctx->vclk_table);
2169         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2170         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2171         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2172         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2173
2174                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2175                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2176                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2177                 }
2178
2179                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2180                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2181                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2182                 }
2183
2184         /* dclk */
2185         dpm_table = &(dpm_ctx->dclk_table);
2186         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2187         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2188         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2189         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2190
2191                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2192                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2193                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
2194                 }
2195
2196                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2197                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2198                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2199                 }
2200
2201         /* socclk */
2202         dpm_table = &(dpm_ctx->soc_table);
2203         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2204         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2205         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2206         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2207
2208                 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
2209                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2210                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
2211                 }
2212
2213                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2214                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2215                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2216                 }
2217
2218         /* eclk */
2219         dpm_table = &(dpm_ctx->eclk_table);
2220         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2221         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2222         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2223         dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2224
2225                 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
2226                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2227                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
2228                 }
2229
2230                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2231                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2232                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2233                 }
2234         return 0;
2235 }
2236
2237 static int
2238 vega20_notify_smc_display_config(struct smu_context *smu)
2239 {
2240         struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context;
2241         struct vega20_single_dpm_table *memtable = &dpm_table->mem_table;
2242         struct smu_clocks min_clocks = {0};
2243         struct pp_display_clock_request clock_req;
2244         int ret = 0;
2245
2246         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
2247         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
2248         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
2249
2250         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
2251                 clock_req.clock_type = amd_pp_dcef_clock;
2252                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
2253                 if (!smu_v11_0_display_clock_voltage_request(smu, &clock_req)) {
2254                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
2255                                 ret = smu_send_smc_msg_with_param(smu,
2256                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
2257                                                                   min_clocks.dcef_clock_in_sr/100);
2258                                 if (ret) {
2259                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
2260                                         return ret;
2261                                 }
2262                         }
2263                 } else {
2264                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2265                 }
2266         }
2267
2268         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2269                 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100;
2270                 ret = smu_send_smc_msg_with_param(smu,
2271                                                   SMU_MSG_SetHardMinByFreq,
2272                                                   (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level);
2273                 if (ret) {
2274                         pr_err("[%s] Set hard min uclk failed!", __func__);
2275                         return ret;
2276                 }
2277         }
2278
2279         return 0;
2280 }
2281
2282 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table)
2283 {
2284         uint32_t i;
2285
2286         for (i = 0; i < table->count; i++) {
2287                 if (table->dpm_levels[i].enabled)
2288                         break;
2289         }
2290         if (i >= table->count) {
2291                 i = 0;
2292                 table->dpm_levels[i].enabled = true;
2293         }
2294
2295         return i;
2296 }
2297
2298 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table)
2299 {
2300         int i = 0;
2301
2302         if (!table) {
2303                 pr_err("[%s] DPM Table does not exist!", __func__);
2304                 return 0;
2305         }
2306         if (table->count <= 0) {
2307                 pr_err("[%s] DPM Table has no entry!", __func__);
2308                 return 0;
2309         }
2310         if (table->count > MAX_REGULAR_DPM_NUMBER) {
2311                 pr_err("[%s] DPM Table has too many entries!", __func__);
2312                 return MAX_REGULAR_DPM_NUMBER - 1;
2313         }
2314
2315         for (i = table->count - 1; i >= 0; i--) {
2316                 if (table->dpm_levels[i].enabled)
2317                         break;
2318         }
2319         if (i < 0) {
2320                 i = 0;
2321                 table->dpm_levels[i].enabled = true;
2322         }
2323
2324         return i;
2325 }
2326
2327 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest)
2328 {
2329         uint32_t soft_level;
2330         int ret = 0;
2331         struct vega20_dpm_table *dpm_table =
2332                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2333
2334         if (highest)
2335                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2336         else
2337                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2338
2339         dpm_table->gfx_table.dpm_state.soft_min_level =
2340                 dpm_table->gfx_table.dpm_state.soft_max_level =
2341                 dpm_table->gfx_table.dpm_levels[soft_level].value;
2342
2343         if (highest)
2344                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2345         else
2346                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2347
2348         dpm_table->mem_table.dpm_state.soft_min_level =
2349                 dpm_table->mem_table.dpm_state.soft_max_level =
2350                 dpm_table->mem_table.dpm_levels[soft_level].value;
2351
2352         if (highest)
2353                 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2354         else
2355                 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2356
2357         dpm_table->soc_table.dpm_state.soft_min_level =
2358                 dpm_table->soc_table.dpm_state.soft_max_level =
2359                 dpm_table->soc_table.dpm_levels[soft_level].value;
2360
2361         ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2362         if (ret) {
2363                 pr_err("Failed to upload boot level to %s!\n",
2364                                 highest ? "highest" : "lowest");
2365                 return ret;
2366         }
2367
2368         ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2369         if (ret) {
2370                 pr_err("Failed to upload dpm max level to %s!\n!",
2371                                 highest ? "highest" : "lowest");
2372                 return ret;
2373         }
2374
2375         return ret;
2376 }
2377
2378 static int vega20_unforce_dpm_levels(struct smu_context *smu)
2379 {
2380         uint32_t soft_min_level, soft_max_level;
2381         int ret = 0;
2382         struct vega20_dpm_table *dpm_table =
2383                 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context;
2384
2385         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table));
2386         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table));
2387         dpm_table->gfx_table.dpm_state.soft_min_level =
2388                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2389         dpm_table->gfx_table.dpm_state.soft_max_level =
2390                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2391
2392         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table));
2393         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table));
2394         dpm_table->mem_table.dpm_state.soft_min_level =
2395                 dpm_table->gfx_table.dpm_levels[soft_min_level].value;
2396         dpm_table->mem_table.dpm_state.soft_max_level =
2397                 dpm_table->gfx_table.dpm_levels[soft_max_level].value;
2398
2399         soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table));
2400         soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table));
2401         dpm_table->soc_table.dpm_state.soft_min_level =
2402                 dpm_table->soc_table.dpm_levels[soft_min_level].value;
2403         dpm_table->soc_table.dpm_state.soft_max_level =
2404                 dpm_table->soc_table.dpm_levels[soft_max_level].value;
2405
2406         ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF);
2407         if (ret) {
2408                 pr_err("Failed to upload DPM Bootup Levels!");
2409                 return ret;
2410         }
2411
2412         ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF);
2413         if (ret) {
2414                 pr_err("Failed to upload DPM Max Levels!");
2415                 return ret;
2416         }
2417
2418         return ret;
2419 }
2420
2421 static int vega20_update_specified_od8_value(struct smu_context *smu,
2422                                              uint32_t index,
2423                                              uint32_t value)
2424 {
2425         struct smu_table_context *table_context = &smu->smu_table;
2426         OverDriveTable_t *od_table =
2427                 (OverDriveTable_t *)(table_context->overdrive_table);
2428         struct vega20_od8_settings *od8_settings =
2429                 (struct vega20_od8_settings *)smu->od_settings;
2430
2431         switch (index) {
2432         case OD8_SETTING_GFXCLK_FMIN:
2433                 od_table->GfxclkFmin = (uint16_t)value;
2434                 break;
2435
2436         case OD8_SETTING_GFXCLK_FMAX:
2437                 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value ||
2438                     value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value)
2439                         return -EINVAL;
2440                 od_table->GfxclkFmax = (uint16_t)value;
2441                 break;
2442
2443         case OD8_SETTING_GFXCLK_FREQ1:
2444                 od_table->GfxclkFreq1 = (uint16_t)value;
2445                 break;
2446
2447         case OD8_SETTING_GFXCLK_VOLTAGE1:
2448                 od_table->GfxclkVolt1 = (uint16_t)value;
2449                 break;
2450
2451         case OD8_SETTING_GFXCLK_FREQ2:
2452                 od_table->GfxclkFreq2 = (uint16_t)value;
2453                 break;
2454
2455         case OD8_SETTING_GFXCLK_VOLTAGE2:
2456                 od_table->GfxclkVolt2 = (uint16_t)value;
2457                 break;
2458
2459         case OD8_SETTING_GFXCLK_FREQ3:
2460                 od_table->GfxclkFreq3 = (uint16_t)value;
2461                 break;
2462
2463         case OD8_SETTING_GFXCLK_VOLTAGE3:
2464                 od_table->GfxclkVolt3 = (uint16_t)value;
2465                 break;
2466
2467         case OD8_SETTING_UCLK_FMAX:
2468                 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value ||
2469                     value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value)
2470                         return -EINVAL;
2471                 od_table->UclkFmax = (uint16_t)value;
2472                 break;
2473
2474         case OD8_SETTING_POWER_PERCENTAGE:
2475                 od_table->OverDrivePct = (int16_t)value;
2476                 break;
2477
2478         case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
2479                 od_table->FanMaximumRpm = (uint16_t)value;
2480                 break;
2481
2482         case OD8_SETTING_FAN_MIN_SPEED:
2483                 od_table->FanMinimumPwm = (uint16_t)value;
2484                 break;
2485
2486         case OD8_SETTING_FAN_TARGET_TEMP:
2487                 od_table->FanTargetTemperature = (uint16_t)value;
2488                 break;
2489
2490         case OD8_SETTING_OPERATING_TEMP_MAX:
2491                 od_table->MaxOpTemp = (uint16_t)value;
2492                 break;
2493         }
2494
2495         return 0;
2496 }
2497
2498 static int vega20_update_od8_settings(struct smu_context *smu,
2499                                       uint32_t index,
2500                                       uint32_t value)
2501 {
2502         struct smu_table_context *table_context = &smu->smu_table;
2503         int ret;
2504
2505         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
2506                                table_context->overdrive_table, false);
2507         if (ret) {
2508                 pr_err("Failed to export over drive table!\n");
2509                 return ret;
2510         }
2511
2512         ret = vega20_update_specified_od8_value(smu, index, value);
2513         if (ret)
2514                 return ret;
2515
2516         ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0,
2517                                table_context->overdrive_table, true);
2518         if (ret) {
2519                 pr_err("Failed to import over drive table!\n");
2520                 return ret;
2521         }
2522
2523         return 0;
2524 }
2525
2526 static int vega20_set_od_percentage(struct smu_context *smu,
2527                                     enum smu_clk_type clk_type,
2528                                     uint32_t value)
2529 {
2530         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2531         struct vega20_dpm_table *dpm_table = NULL;
2532         struct vega20_dpm_table *golden_table = NULL;
2533         struct vega20_single_dpm_table *single_dpm_table;
2534         struct vega20_single_dpm_table *golden_dpm_table;
2535         uint32_t od_clk, index;
2536         int ret = 0;
2537         int feature_enabled;
2538         PPCLK_e clk_id;
2539
2540         dpm_table = smu_dpm->dpm_context;
2541         golden_table = smu_dpm->golden_dpm_context;
2542
2543         switch (clk_type) {
2544         case SMU_OD_SCLK:
2545                 single_dpm_table = &(dpm_table->gfx_table);
2546                 golden_dpm_table = &(golden_table->gfx_table);
2547                 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT);
2548                 clk_id = PPCLK_GFXCLK;
2549                 index = OD8_SETTING_GFXCLK_FMAX;
2550                 break;
2551         case SMU_OD_MCLK:
2552                 single_dpm_table = &(dpm_table->mem_table);
2553                 golden_dpm_table = &(golden_table->mem_table);
2554                 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT);
2555                 clk_id = PPCLK_UCLK;
2556                 index = OD8_SETTING_UCLK_FMAX;
2557                 break;
2558         default:
2559                 ret = -EINVAL;
2560                 break;
2561         }
2562
2563         if (ret)
2564                 goto set_od_failed;
2565
2566         od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
2567         od_clk /= 100;
2568         od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
2569
2570         ret = vega20_update_od8_settings(smu, index, od_clk);
2571         if (ret) {
2572                 pr_err("[Setoverdrive] failed to set od clk!\n");
2573                 goto set_od_failed;
2574         }
2575
2576         if (feature_enabled) {
2577                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2578                                                   clk_id);
2579                 if (ret) {
2580                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2581                         goto set_od_failed;
2582                 }
2583         } else {
2584                 single_dpm_table->count = 1;
2585                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2586         }
2587
2588         ret = smu_handle_task(smu, smu_dpm->dpm_level,
2589                               AMD_PP_TASK_READJUST_POWER_STATE,
2590                               false);
2591
2592 set_od_failed:
2593         return ret;
2594 }
2595
2596 static int vega20_odn_edit_dpm_table(struct smu_context *smu,
2597                                      enum PP_OD_DPM_TABLE_COMMAND type,
2598                                      long *input, uint32_t size)
2599 {
2600         struct smu_table_context *table_context = &smu->smu_table;
2601         OverDriveTable_t *od_table =
2602                 (OverDriveTable_t *)(table_context->overdrive_table);
2603         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2604         struct vega20_dpm_table *dpm_table = NULL;
2605         struct vega20_single_dpm_table *single_dpm_table;
2606         struct vega20_od8_settings *od8_settings =
2607                 (struct vega20_od8_settings *)smu->od_settings;
2608         struct pp_clock_levels_with_latency clocks;
2609         int32_t input_index, input_clk, input_vol, i;
2610         int od8_id;
2611         int ret = 0;
2612
2613         dpm_table = smu_dpm->dpm_context;
2614
2615         if (!input) {
2616                 pr_warn("NULL user input for clock and voltage\n");
2617                 return -EINVAL;
2618         }
2619
2620         switch (type) {
2621         case PP_OD_EDIT_SCLK_VDDC_TABLE:
2622                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2623                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2624                         pr_info("Sclk min/max frequency overdrive not supported\n");
2625                         return -EOPNOTSUPP;
2626                 }
2627
2628                 for (i = 0; i < size; i += 2) {
2629                         if (i + 2 > size) {
2630                                 pr_info("invalid number of input parameters %d\n", size);
2631                                 return -EINVAL;
2632                         }
2633
2634                         input_index = input[i];
2635                         input_clk = input[i + 1];
2636
2637                         if (input_index != 0 && input_index != 1) {
2638                                 pr_info("Invalid index %d\n", input_index);
2639                                 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n");
2640                                 return -EINVAL;
2641                         }
2642
2643                         if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value ||
2644                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) {
2645                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2646                                         input_clk,
2647                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
2648                                         od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
2649                                 return -EINVAL;
2650                         }
2651
2652                         if (input_index == 0 && od_table->GfxclkFmin != input_clk) {
2653                                 od_table->GfxclkFmin = input_clk;
2654                                 od8_settings->od_gfxclk_update = true;
2655                         } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) {
2656                                 od_table->GfxclkFmax = input_clk;
2657                                 od8_settings->od_gfxclk_update = true;
2658                         }
2659                 }
2660
2661                 break;
2662
2663         case PP_OD_EDIT_MCLK_VDDC_TABLE:
2664                 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
2665                         pr_info("Mclk max frequency overdrive not supported\n");
2666                         return -EOPNOTSUPP;
2667                 }
2668
2669                 single_dpm_table = &(dpm_table->mem_table);
2670                 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
2671                 if (ret) {
2672                         pr_err("Attempt to get memory clk levels Failed!");
2673                         return ret;
2674                 }
2675
2676                 for (i = 0; i < size; i += 2) {
2677                         if (i + 2 > size) {
2678                                 pr_info("invalid number of input parameters %d\n",
2679                                          size);
2680                                 return -EINVAL;
2681                         }
2682
2683                         input_index = input[i];
2684                         input_clk = input[i + 1];
2685
2686                         if (input_index != 1) {
2687                                 pr_info("Invalid index %d\n", input_index);
2688                                 pr_info("Support max Mclk frequency setting only which index by 1\n");
2689                                 return -EINVAL;
2690                         }
2691
2692                         if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2693                             input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) {
2694                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2695                                         input_clk,
2696                                         clocks.data[0].clocks_in_khz / 1000,
2697                                         od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
2698                                 return -EINVAL;
2699                         }
2700
2701                         if (input_index == 1 && od_table->UclkFmax != input_clk) {
2702                                 od8_settings->od_gfxclk_update = true;
2703                                 od_table->UclkFmax = input_clk;
2704                         }
2705                 }
2706
2707                 break;
2708
2709         case PP_OD_EDIT_VDDC_CURVE:
2710                 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2711                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2712                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2713                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2714                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2715                       od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2716                         pr_info("Voltage curve calibrate not supported\n");
2717                         return -EOPNOTSUPP;
2718                 }
2719
2720                 for (i = 0; i < size; i += 3) {
2721                         if (i + 3 > size) {
2722                                 pr_info("invalid number of input parameters %d\n",
2723                                         size);
2724                                 return -EINVAL;
2725                         }
2726
2727                         input_index = input[i];
2728                         input_clk = input[i + 1];
2729                         input_vol = input[i + 2];
2730
2731                         if (input_index > 2) {
2732                                 pr_info("Setting for point %d is not supported\n",
2733                                         input_index + 1);
2734                                 pr_info("Three supported points index by 0, 1, 2\n");
2735                                 return -EINVAL;
2736                         }
2737
2738                         od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2739                         if (input_clk < od8_settings->od8_settings_array[od8_id].min_value ||
2740                             input_clk > od8_settings->od8_settings_array[od8_id].max_value) {
2741                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2742                                         input_clk,
2743                                         od8_settings->od8_settings_array[od8_id].min_value,
2744                                         od8_settings->od8_settings_array[od8_id].max_value);
2745                                 return -EINVAL;
2746                         }
2747
2748                         od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2749                         if (input_vol < od8_settings->od8_settings_array[od8_id].min_value ||
2750                             input_vol > od8_settings->od8_settings_array[od8_id].max_value) {
2751                                 pr_info("clock voltage %d is not within allowed range [%d- %d]\n",
2752                                         input_vol,
2753                                         od8_settings->od8_settings_array[od8_id].min_value,
2754                                         od8_settings->od8_settings_array[od8_id].max_value);
2755                                 return -EINVAL;
2756                         }
2757
2758                         switch (input_index) {
2759                         case 0:
2760                                 od_table->GfxclkFreq1 = input_clk;
2761                                 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2762                                 break;
2763                         case 1:
2764                                 od_table->GfxclkFreq2 = input_clk;
2765                                 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2766                                 break;
2767                         case 2:
2768                                 od_table->GfxclkFreq3 = input_clk;
2769                                 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2770                                 break;
2771                         }
2772                 }
2773
2774                 break;
2775
2776         case PP_OD_RESTORE_DEFAULT_TABLE:
2777                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, false);
2778                 if (ret) {
2779                         pr_err("Failed to export over drive table!\n");
2780                         return ret;
2781                 }
2782
2783                 break;
2784
2785         case PP_OD_COMMIT_DPM_TABLE:
2786                 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
2787                 if (ret) {
2788                         pr_err("Failed to import over drive table!\n");
2789                         return ret;
2790                 }
2791
2792                 /* retrieve updated gfxclk table */
2793                 if (od8_settings->od_gfxclk_update) {
2794                         od8_settings->od_gfxclk_update = false;
2795                         single_dpm_table = &(dpm_table->gfx_table);
2796
2797                         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
2798                                 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2799                                                                   PPCLK_GFXCLK);
2800                                 if (ret) {
2801                                         pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2802                                         return ret;
2803                                 }
2804                         } else {
2805                                 single_dpm_table->count = 1;
2806                                 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2807                         }
2808                 }
2809
2810                 break;
2811
2812         default:
2813                 return -EINVAL;
2814         }
2815
2816         if (type == PP_OD_COMMIT_DPM_TABLE) {
2817                 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2818                                       AMD_PP_TASK_READJUST_POWER_STATE,
2819                                       false);
2820         }
2821
2822         return ret;
2823 }
2824
2825 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
2826 {
2827         if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
2828                 return 0;
2829
2830         if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
2831                 return 0;
2832
2833         return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
2834 }
2835
2836 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
2837 {
2838         if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
2839                 return 0;
2840
2841         if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
2842                 return 0;
2843
2844         return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
2845 }
2846
2847 static bool vega20_is_dpm_running(struct smu_context *smu)
2848 {
2849         int ret = 0;
2850         uint32_t feature_mask[2];
2851         unsigned long feature_enabled;
2852         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2853         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
2854                            ((uint64_t)feature_mask[1] << 32));
2855         return !!(feature_enabled & SMC_DPM_FEATURE);
2856 }
2857
2858 static int vega20_set_thermal_fan_table(struct smu_context *smu)
2859 {
2860         int ret;
2861         struct smu_table_context *table_context = &smu->smu_table;
2862         PPTable_t *pptable = table_context->driver_pptable;
2863
2864         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
2865                         (uint32_t)pptable->FanTargetTemperature);
2866
2867         return ret;
2868 }
2869
2870 static int vega20_get_fan_speed_rpm(struct smu_context *smu,
2871                                     uint32_t *speed)
2872 {
2873         int ret;
2874
2875         ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
2876
2877         if (ret) {
2878                 pr_err("Attempt to get current RPM from SMC Failed!\n");
2879                 return ret;
2880         }
2881
2882         smu_read_smc_arg(smu, speed);
2883
2884         return 0;
2885 }
2886
2887 static int vega20_get_fan_speed_percent(struct smu_context *smu,
2888                                         uint32_t *speed)
2889 {
2890         int ret = 0;
2891         uint32_t current_rpm = 0, percent = 0;
2892         PPTable_t *pptable = smu->smu_table.driver_pptable;
2893
2894         ret = vega20_get_fan_speed_rpm(smu, &current_rpm);
2895         if (ret)
2896                 return ret;
2897
2898         percent = current_rpm * 100 / pptable->FanMaximumRpm;
2899         *speed = percent > 100 ? 100 : percent;
2900
2901         return 0;
2902 }
2903
2904 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
2905 {
2906         uint32_t smu_version;
2907         int ret = 0;
2908         SmuMetrics_t metrics;
2909
2910         if (!value)
2911                 return -EINVAL;
2912
2913         ret = vega20_get_metrics_table(smu, &metrics);
2914         if (ret)
2915                 return ret;
2916
2917         ret = smu_get_smc_version(smu, NULL, &smu_version);
2918         if (ret)
2919                 return ret;
2920
2921         /* For the 40.46 release, they changed the value name */
2922         if (smu_version == 0x282e00)
2923                 *value = metrics.AverageSocketPower << 8;
2924         else
2925                 *value = metrics.CurrSocketPower << 8;
2926
2927         return 0;
2928 }
2929
2930 static int vega20_get_current_activity_percent(struct smu_context *smu,
2931                                                enum amd_pp_sensors sensor,
2932                                                uint32_t *value)
2933 {
2934         int ret = 0;
2935         SmuMetrics_t metrics;
2936
2937         if (!value)
2938                 return -EINVAL;
2939
2940         ret = vega20_get_metrics_table(smu, &metrics);
2941         if (ret)
2942                 return ret;
2943
2944         switch (sensor) {
2945         case AMDGPU_PP_SENSOR_GPU_LOAD:
2946                 *value = metrics.AverageGfxActivity;
2947                 break;
2948         case AMDGPU_PP_SENSOR_MEM_LOAD:
2949                 *value = metrics.AverageUclkActivity;
2950                 break;
2951         default:
2952                 pr_err("Invalid sensor for retrieving clock activity\n");
2953                 return -EINVAL;
2954         }
2955
2956         return 0;
2957 }
2958
2959 static int vega20_thermal_get_temperature(struct smu_context *smu,
2960                                              enum amd_pp_sensors sensor,
2961                                              uint32_t *value)
2962 {
2963         struct amdgpu_device *adev = smu->adev;
2964         SmuMetrics_t metrics;
2965         uint32_t temp = 0;
2966         int ret = 0;
2967
2968         if (!value)
2969                 return -EINVAL;
2970
2971         ret = vega20_get_metrics_table(smu, &metrics);
2972         if (ret)
2973                 return ret;
2974
2975         switch (sensor) {
2976         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2977                 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
2978                 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
2979                                 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
2980
2981                 temp = temp & 0x1ff;
2982                 temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2983
2984                 *value = temp;
2985                 break;
2986         case AMDGPU_PP_SENSOR_EDGE_TEMP:
2987                 *value = metrics.TemperatureEdge *
2988                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2989                 break;
2990         case AMDGPU_PP_SENSOR_MEM_TEMP:
2991                 *value = metrics.TemperatureHBM *
2992                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2993                 break;
2994         default:
2995                 pr_err("Invalid sensor for retrieving temp\n");
2996                 return -EINVAL;
2997         }
2998
2999         return 0;
3000 }
3001 static int vega20_read_sensor(struct smu_context *smu,
3002                                  enum amd_pp_sensors sensor,
3003                                  void *data, uint32_t *size)
3004 {
3005         int ret = 0;
3006         struct smu_table_context *table_context = &smu->smu_table;
3007         PPTable_t *pptable = table_context->driver_pptable;
3008
3009         if(!data || !size)
3010                 return -EINVAL;
3011
3012         mutex_lock(&smu->sensor_lock);
3013         switch (sensor) {
3014         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
3015                 *(uint32_t *)data = pptable->FanMaximumRpm;
3016                 *size = 4;
3017                 break;
3018         case AMDGPU_PP_SENSOR_MEM_LOAD:
3019         case AMDGPU_PP_SENSOR_GPU_LOAD:
3020                 ret = vega20_get_current_activity_percent(smu,
3021                                                 sensor,
3022                                                 (uint32_t *)data);
3023                 *size = 4;
3024                 break;
3025         case AMDGPU_PP_SENSOR_GPU_POWER:
3026                 ret = vega20_get_gpu_power(smu, (uint32_t *)data);
3027                 *size = 4;
3028                 break;
3029         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3030         case AMDGPU_PP_SENSOR_EDGE_TEMP:
3031         case AMDGPU_PP_SENSOR_MEM_TEMP:
3032                 ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
3033                 *size = 4;
3034                 break;
3035         default:
3036                 ret = smu_v11_0_read_sensor(smu, sensor, data, size);
3037         }
3038         mutex_unlock(&smu->sensor_lock);
3039
3040         return ret;
3041 }
3042
3043 static int vega20_set_watermarks_table(struct smu_context *smu,
3044                                        void *watermarks, struct
3045                                        dm_pp_wm_sets_with_clock_ranges_soc15
3046                                        *clock_ranges)
3047 {
3048         int i;
3049         Watermarks_t *table = watermarks;
3050
3051         if (!table || !clock_ranges)
3052                 return -EINVAL;
3053
3054         if (clock_ranges->num_wm_dmif_sets > 4 ||
3055             clock_ranges->num_wm_mcif_sets > 4)
3056                 return -EINVAL;
3057
3058         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
3059                 table->WatermarkRow[1][i].MinClock =
3060                         cpu_to_le16((uint16_t)
3061                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
3062                         1000));
3063                 table->WatermarkRow[1][i].MaxClock =
3064                         cpu_to_le16((uint16_t)
3065                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
3066                         1000));
3067                 table->WatermarkRow[1][i].MinUclk =
3068                         cpu_to_le16((uint16_t)
3069                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3070                         1000));
3071                 table->WatermarkRow[1][i].MaxUclk =
3072                         cpu_to_le16((uint16_t)
3073                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3074                         1000));
3075                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
3076                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
3077         }
3078
3079         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
3080                 table->WatermarkRow[0][i].MinClock =
3081                         cpu_to_le16((uint16_t)
3082                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
3083                         1000));
3084                 table->WatermarkRow[0][i].MaxClock =
3085                         cpu_to_le16((uint16_t)
3086                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
3087                         1000));
3088                 table->WatermarkRow[0][i].MinUclk =
3089                         cpu_to_le16((uint16_t)
3090                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3091                         1000));
3092                 table->WatermarkRow[0][i].MaxUclk =
3093                         cpu_to_le16((uint16_t)
3094                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3095                         1000));
3096                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
3097                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
3098         }
3099
3100         return 0;
3101 }
3102
3103 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
3104                                                 struct smu_temperature_range *range)
3105 {
3106         struct smu_table_context *table_context = &smu->smu_table;
3107         ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
3108         PPTable_t *pptable = smu->smu_table.driver_pptable;
3109
3110         if (!range || !powerplay_table)
3111                 return -EINVAL;
3112
3113         range->max = powerplay_table->usSoftwareShutdownTemp *
3114                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3115         range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
3116                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3117         range->hotspot_crit_max = pptable->ThotspotLimit *
3118                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3119         range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
3120                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3121         range->mem_crit_max = pptable->ThbmLimit *
3122                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3123         range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM) *
3124                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3125
3126
3127         return 0;
3128 }
3129
3130 static int vega20_set_df_cstate(struct smu_context *smu,
3131                                 enum pp_df_cstate state)
3132 {
3133         uint32_t smu_version;
3134         int ret;
3135
3136         ret = smu_get_smc_version(smu, NULL, &smu_version);
3137         if (ret) {
3138                 pr_err("Failed to get smu version!\n");
3139                 return ret;
3140         }
3141
3142         /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
3143         if (smu_version < 0x283200) {
3144                 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
3145                 return -EINVAL;
3146         }
3147
3148         return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state);
3149 }
3150
3151 static int vega20_update_pcie_parameters(struct smu_context *smu,
3152                                      uint32_t pcie_gen_cap,
3153                                      uint32_t pcie_width_cap)
3154 {
3155         PPTable_t *pptable = smu->smu_table.driver_pptable;
3156         int ret, i;
3157         uint32_t smu_pcie_arg;
3158
3159         for (i = 0; i < NUM_LINK_LEVELS; i++) {
3160                 smu_pcie_arg = (i << 16) |
3161                         ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
3162                                 (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
3163                                         pptable->PcieLaneCount[i] : pcie_width_cap);
3164                 ret = smu_send_smc_msg_with_param(smu,
3165                                           SMU_MSG_OverridePcieParameters,
3166                                           smu_pcie_arg);
3167         }
3168
3169         return ret;
3170 }
3171
3172
3173 static const struct pptable_funcs vega20_ppt_funcs = {
3174         .tables_init = vega20_tables_init,
3175         .alloc_dpm_context = vega20_allocate_dpm_context,
3176         .store_powerplay_table = vega20_store_powerplay_table,
3177         .check_powerplay_table = vega20_check_powerplay_table,
3178         .append_powerplay_table = vega20_append_powerplay_table,
3179         .get_smu_msg_index = vega20_get_smu_msg_index,
3180         .get_smu_clk_index = vega20_get_smu_clk_index,
3181         .get_smu_feature_index = vega20_get_smu_feature_index,
3182         .get_smu_table_index = vega20_get_smu_table_index,
3183         .get_smu_power_index = vega20_get_pwr_src_index,
3184         .get_workload_type = vega20_get_workload_type,
3185         .run_btc = vega20_run_btc_afll,
3186         .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
3187         .get_current_power_state = vega20_get_current_power_state,
3188         .set_default_dpm_table = vega20_set_default_dpm_table,
3189         .set_power_state = NULL,
3190         .populate_umd_state_clk = vega20_populate_umd_state_clk,
3191         .print_clk_levels = vega20_print_clk_levels,
3192         .force_clk_levels = vega20_force_clk_levels,
3193         .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
3194         .get_od_percentage = vega20_get_od_percentage,
3195         .get_power_profile_mode = vega20_get_power_profile_mode,
3196         .set_power_profile_mode = vega20_set_power_profile_mode,
3197         .set_od_percentage = vega20_set_od_percentage,
3198         .set_default_od_settings = vega20_set_default_od_settings,
3199         .od_edit_dpm_table = vega20_odn_edit_dpm_table,
3200         .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable,
3201         .dpm_set_vce_enable = vega20_dpm_set_vce_enable,
3202         .read_sensor = vega20_read_sensor,
3203         .pre_display_config_changed = vega20_pre_display_config_changed,
3204         .display_config_changed = vega20_display_config_changed,
3205         .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
3206         .notify_smc_display_config = vega20_notify_smc_display_config,
3207         .force_dpm_limit_value = vega20_force_dpm_limit_value,
3208         .unforce_dpm_levels = vega20_unforce_dpm_levels,
3209         .get_profiling_clk_mask = vega20_get_profiling_clk_mask,
3210         .is_dpm_running = vega20_is_dpm_running,
3211         .set_thermal_fan_table = vega20_set_thermal_fan_table,
3212         .get_fan_speed_percent = vega20_get_fan_speed_percent,
3213         .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
3214         .set_watermarks_table = vega20_set_watermarks_table,
3215         .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
3216         .set_df_cstate = vega20_set_df_cstate,
3217         .update_pcie_parameters = vega20_update_pcie_parameters,
3218         .init_microcode = smu_v11_0_init_microcode,
3219         .load_microcode = smu_v11_0_load_microcode,
3220         .init_smc_tables = smu_v11_0_init_smc_tables,
3221         .fini_smc_tables = smu_v11_0_fini_smc_tables,
3222         .init_power = smu_v11_0_init_power,
3223         .fini_power = smu_v11_0_fini_power,
3224         .check_fw_status = smu_v11_0_check_fw_status,
3225         .setup_pptable = smu_v11_0_setup_pptable,
3226         .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
3227         .get_clk_info_from_vbios = smu_v11_0_get_clk_info_from_vbios,
3228         .check_pptable = smu_v11_0_check_pptable,
3229         .parse_pptable = smu_v11_0_parse_pptable,
3230         .populate_smc_tables = smu_v11_0_populate_smc_pptable,
3231         .check_fw_version = smu_v11_0_check_fw_version,
3232         .write_pptable = smu_v11_0_write_pptable,
3233         .set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep,
3234         .set_tool_table_location = smu_v11_0_set_tool_table_location,
3235         .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
3236         .system_features_control = smu_v11_0_system_features_control,
3237         .send_smc_msg_with_param = smu_v11_0_send_msg_with_param,
3238         .read_smc_arg = smu_v11_0_read_arg,
3239         .init_display_count = smu_v11_0_init_display_count,
3240         .set_allowed_mask = smu_v11_0_set_allowed_mask,
3241         .get_enabled_mask = smu_v11_0_get_enabled_mask,
3242         .notify_display_change = smu_v11_0_notify_display_change,
3243         .set_power_limit = smu_v11_0_set_power_limit,
3244         .get_current_clk_freq = smu_v11_0_get_current_clk_freq,
3245         .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
3246         .start_thermal_control = smu_v11_0_start_thermal_control,
3247         .stop_thermal_control = smu_v11_0_stop_thermal_control,
3248         .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
3249         .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
3250         .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
3251         .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
3252         .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
3253         .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
3254         .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
3255         .gfx_off_control = smu_v11_0_gfx_off_control,
3256         .register_irq_handler = smu_v11_0_register_irq_handler,
3257         .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
3258         .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
3259         .baco_is_support= smu_v11_0_baco_is_support,
3260         .baco_get_state = smu_v11_0_baco_get_state,
3261         .baco_set_state = smu_v11_0_baco_set_state,
3262         .baco_enter = smu_v11_0_baco_enter,
3263         .baco_exit = smu_v11_0_baco_exit,
3264         .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
3265         .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
3266         .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
3267 };
3268
3269 void vega20_set_ppt_funcs(struct smu_context *smu)
3270 {
3271         smu->ppt_funcs = &vega20_ppt_funcs;
3272 }