1 /* $NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $ */
2
3 /*
4 * Copyright 2019 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $");
28
29 #include "pp_debug.h"
30 #include <linux/firmware.h>
31 #include "amdgpu.h"
32 #include "amdgpu_smu.h"
33 #include "smu_internal.h"
34 #include "atomfirmware.h"
35 #include "amdgpu_atomfirmware.h"
36 #include "smu_v11_0.h"
37 #include "smu11_driver_if.h"
38 #include "soc15_common.h"
39 #include "atom.h"
40 #include "power_state.h"
41 #include "vega20_ppt.h"
42 #include "vega20_pptable.h"
43 #include "vega20_ppsmc.h"
44 #include "nbio/nbio_7_4_sh_mask.h"
45 #include "asic_reg/thm/thm_11_0_2_offset.h"
46 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
47
48 #include <linux/nbsd-namespace.h>
49
50 #define smnPCIE_LC_SPEED_CNTL 0x11140290
51 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
52
53 #define CTF_OFFSET_EDGE 5
54 #define CTF_OFFSET_HOTSPOT 5
55 #define CTF_OFFSET_HBM 5
56
57 #define MSG_MAP(msg) \
58 [SMU_MSG_##msg] = {1, PPSMC_MSG_##msg}
59
60 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \
61 FEATURE_DPM_GFXCLK_MASK | \
62 FEATURE_DPM_UCLK_MASK | \
63 FEATURE_DPM_SOCCLK_MASK | \
64 FEATURE_DPM_UVD_MASK | \
65 FEATURE_DPM_VCE_MASK | \
66 FEATURE_DPM_MP0CLK_MASK | \
67 FEATURE_DPM_LINK_MASK | \
68 FEATURE_DPM_DCEFCLK_MASK)
69
70 static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] = {
71 MSG_MAP(TestMessage),
72 MSG_MAP(GetSmuVersion),
73 MSG_MAP(GetDriverIfVersion),
74 MSG_MAP(SetAllowedFeaturesMaskLow),
75 MSG_MAP(SetAllowedFeaturesMaskHigh),
76 MSG_MAP(EnableAllSmuFeatures),
77 MSG_MAP(DisableAllSmuFeatures),
78 MSG_MAP(EnableSmuFeaturesLow),
79 MSG_MAP(EnableSmuFeaturesHigh),
80 MSG_MAP(DisableSmuFeaturesLow),
81 MSG_MAP(DisableSmuFeaturesHigh),
82 MSG_MAP(GetEnabledSmuFeaturesLow),
83 MSG_MAP(GetEnabledSmuFeaturesHigh),
84 MSG_MAP(SetWorkloadMask),
85 MSG_MAP(SetPptLimit),
86 MSG_MAP(SetDriverDramAddrHigh),
87 MSG_MAP(SetDriverDramAddrLow),
88 MSG_MAP(SetToolsDramAddrHigh),
89 MSG_MAP(SetToolsDramAddrLow),
90 MSG_MAP(TransferTableSmu2Dram),
91 MSG_MAP(TransferTableDram2Smu),
92 MSG_MAP(UseDefaultPPTable),
93 MSG_MAP(UseBackupPPTable),
94 MSG_MAP(RunBtc),
95 MSG_MAP(RequestI2CBus),
96 MSG_MAP(ReleaseI2CBus),
97 MSG_MAP(SetFloorSocVoltage),
98 MSG_MAP(SoftReset),
99 MSG_MAP(StartBacoMonitor),
100 MSG_MAP(CancelBacoMonitor),
101 MSG_MAP(EnterBaco),
102 MSG_MAP(SetSoftMinByFreq),
103 MSG_MAP(SetSoftMaxByFreq),
104 MSG_MAP(SetHardMinByFreq),
105 MSG_MAP(SetHardMaxByFreq),
106 MSG_MAP(GetMinDpmFreq),
107 MSG_MAP(GetMaxDpmFreq),
108 MSG_MAP(GetDpmFreqByIndex),
109 MSG_MAP(GetDpmClockFreq),
110 MSG_MAP(GetSsVoltageByDpm),
111 MSG_MAP(SetMemoryChannelConfig),
112 MSG_MAP(SetGeminiMode),
113 MSG_MAP(SetGeminiApertureHigh),
114 MSG_MAP(SetGeminiApertureLow),
115 MSG_MAP(SetMinLinkDpmByIndex),
116 MSG_MAP(OverridePcieParameters),
117 MSG_MAP(OverDriveSetPercentage),
118 MSG_MAP(SetMinDeepSleepDcefclk),
119 MSG_MAP(ReenableAcDcInterrupt),
120 MSG_MAP(NotifyPowerSource),
121 MSG_MAP(SetUclkFastSwitch),
122 MSG_MAP(SetUclkDownHyst),
123 MSG_MAP(GetCurrentRpm),
124 MSG_MAP(SetVideoFps),
125 MSG_MAP(SetTjMax),
126 MSG_MAP(SetFanTemperatureTarget),
127 MSG_MAP(PrepareMp1ForUnload),
128 MSG_MAP(DramLogSetDramAddrHigh),
129 MSG_MAP(DramLogSetDramAddrLow),
130 MSG_MAP(DramLogSetDramSize),
131 MSG_MAP(SetFanMaxRpm),
132 MSG_MAP(SetFanMinPwm),
133 MSG_MAP(ConfigureGfxDidt),
134 MSG_MAP(NumOfDisplays),
135 MSG_MAP(RemoveMargins),
136 MSG_MAP(ReadSerialNumTop32),
137 MSG_MAP(ReadSerialNumBottom32),
138 MSG_MAP(SetSystemVirtualDramAddrHigh),
139 MSG_MAP(SetSystemVirtualDramAddrLow),
140 MSG_MAP(WaflTest),
141 MSG_MAP(SetFclkGfxClkRatio),
142 MSG_MAP(AllowGfxOff),
143 MSG_MAP(DisallowGfxOff),
144 MSG_MAP(GetPptLimit),
145 MSG_MAP(GetDcModeMaxDpmFreq),
146 MSG_MAP(GetDebugData),
147 MSG_MAP(SetXgmiMode),
148 MSG_MAP(RunAfllBtc),
149 MSG_MAP(ExitBaco),
150 MSG_MAP(PrepareMp1ForReset),
151 MSG_MAP(PrepareMp1ForShutdown),
152 MSG_MAP(SetMGpuFanBoostLimitRpm),
153 MSG_MAP(GetAVFSVoltageByDpm),
154 MSG_MAP(DFCstateControl),
155 };
156
157 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = {
158 CLK_MAP(GFXCLK, PPCLK_GFXCLK),
159 CLK_MAP(VCLK, PPCLK_VCLK),
160 CLK_MAP(DCLK, PPCLK_DCLK),
161 CLK_MAP(ECLK, PPCLK_ECLK),
162 CLK_MAP(SOCCLK, PPCLK_SOCCLK),
163 CLK_MAP(UCLK, PPCLK_UCLK),
164 CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
165 CLK_MAP(DISPCLK, PPCLK_DISPCLK),
166 CLK_MAP(PIXCLK, PPCLK_PIXCLK),
167 CLK_MAP(PHYCLK, PPCLK_PHYCLK),
168 CLK_MAP(FCLK, PPCLK_FCLK),
169 };
170
171 static struct smu_11_0_cmn2aisc_mapping vega20_feature_mask_map[SMU_FEATURE_COUNT] = {
172 FEA_MAP(DPM_PREFETCHER),
173 FEA_MAP(DPM_GFXCLK),
174 FEA_MAP(DPM_UCLK),
175 FEA_MAP(DPM_SOCCLK),
176 FEA_MAP(DPM_UVD),
177 FEA_MAP(DPM_VCE),
178 FEA_MAP(ULV),
179 FEA_MAP(DPM_MP0CLK),
180 FEA_MAP(DPM_LINK),
181 FEA_MAP(DPM_DCEFCLK),
182 FEA_MAP(DS_GFXCLK),
183 FEA_MAP(DS_SOCCLK),
184 FEA_MAP(DS_LCLK),
185 FEA_MAP(PPT),
186 FEA_MAP(TDC),
187 FEA_MAP(THERMAL),
188 FEA_MAP(GFX_PER_CU_CG),
189 FEA_MAP(RM),
190 FEA_MAP(DS_DCEFCLK),
191 FEA_MAP(ACDC),
192 FEA_MAP(VR0HOT),
193 FEA_MAP(VR1HOT),
194 FEA_MAP(FW_CTF),
195 FEA_MAP(LED_DISPLAY),
196 FEA_MAP(FAN_CONTROL),
197 FEA_MAP(GFX_EDC),
198 FEA_MAP(GFXOFF),
199 FEA_MAP(CG),
200 FEA_MAP(DPM_FCLK),
201 FEA_MAP(DS_FCLK),
202 FEA_MAP(DS_MP1CLK),
203 FEA_MAP(DS_MP0CLK),
204 FEA_MAP(XGMI),
205 };
206
207 static struct smu_11_0_cmn2aisc_mapping vega20_table_map[SMU_TABLE_COUNT] = {
208 TAB_MAP(PPTABLE),
209 TAB_MAP(WATERMARKS),
210 TAB_MAP(AVFS),
211 TAB_MAP(AVFS_PSM_DEBUG),
212 TAB_MAP(AVFS_FUSE_OVERRIDE),
213 TAB_MAP(PMSTATUSLOG),
214 TAB_MAP(SMU_METRICS),
215 TAB_MAP(DRIVER_SMU_CONFIG),
216 TAB_MAP(ACTIVITY_MONITOR_COEFF),
217 TAB_MAP(OVERDRIVE),
218 };
219
220 static struct smu_11_0_cmn2aisc_mapping vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
221 PWR_MAP(AC),
222 PWR_MAP(DC),
223 };
224
225 static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
226 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_DEFAULT_BIT),
227 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
228 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
229 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
230 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
231 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
232 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
233 };
234
vega20_get_smu_table_index(struct smu_context * smc,uint32_t index)235 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
236 {
237 struct smu_11_0_cmn2aisc_mapping mapping;
238
239 if (index >= SMU_TABLE_COUNT)
240 return -EINVAL;
241
242 mapping = vega20_table_map[index];
243 if (!(mapping.valid_mapping)) {
244 return -EINVAL;
245 }
246
247 return mapping.map_to;
248 }
249
vega20_get_pwr_src_index(struct smu_context * smc,uint32_t index)250 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
251 {
252 struct smu_11_0_cmn2aisc_mapping mapping;
253
254 if (index >= SMU_POWER_SOURCE_COUNT)
255 return -EINVAL;
256
257 mapping = vega20_pwr_src_map[index];
258 if (!(mapping.valid_mapping)) {
259 return -EINVAL;
260 }
261
262 return mapping.map_to;
263 }
264
vega20_get_smu_feature_index(struct smu_context * smc,uint32_t index)265 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
266 {
267 struct smu_11_0_cmn2aisc_mapping mapping;
268
269 if (index >= SMU_FEATURE_COUNT)
270 return -EINVAL;
271
272 mapping = vega20_feature_mask_map[index];
273 if (!(mapping.valid_mapping)) {
274 return -EINVAL;
275 }
276
277 return mapping.map_to;
278 }
279
vega20_get_smu_clk_index(struct smu_context * smc,uint32_t index)280 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
281 {
282 struct smu_11_0_cmn2aisc_mapping mapping;
283
284 if (index >= SMU_CLK_COUNT)
285 return -EINVAL;
286
287 mapping = vega20_clk_map[index];
288 if (!(mapping.valid_mapping)) {
289 return -EINVAL;
290 }
291
292 return mapping.map_to;
293 }
294
vega20_get_smu_msg_index(struct smu_context * smc,uint32_t index)295 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
296 {
297 struct smu_11_0_cmn2aisc_mapping mapping;
298
299 if (index >= SMU_MSG_MAX_COUNT)
300 return -EINVAL;
301
302 mapping = vega20_message_map[index];
303 if (!(mapping.valid_mapping)) {
304 return -EINVAL;
305 }
306
307 return mapping.map_to;
308 }
309
vega20_get_workload_type(struct smu_context * smu,enum PP_SMC_POWER_PROFILE profile)310 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
311 {
312 struct smu_11_0_cmn2aisc_mapping mapping;
313
314 if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
315 return -EINVAL;
316
317 mapping = vega20_workload_map[profile];
318 if (!(mapping.valid_mapping)) {
319 return -EINVAL;
320 }
321
322 return mapping.map_to;
323 }
324
vega20_tables_init(struct smu_context * smu,struct smu_table * tables)325 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables)
326 {
327 struct smu_table_context *smu_table = &smu->smu_table;
328
329 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
330 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
331 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
332 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
333 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
334 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
335 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
336 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
337 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
338 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
339 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
340 sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
341 AMDGPU_GEM_DOMAIN_VRAM);
342
343 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
344 if (!smu_table->metrics_table)
345 return -ENOMEM;
346 smu_table->metrics_time = 0;
347
348 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
349 if (!smu_table->watermarks_table)
350 return -ENOMEM;
351
352 return 0;
353 }
354
vega20_allocate_dpm_context(struct smu_context * smu)355 static int vega20_allocate_dpm_context(struct smu_context *smu)
356 {
357 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
358
359 if (smu_dpm->dpm_context)
360 return -EINVAL;
361
362 smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
363 GFP_KERNEL);
364 if (!smu_dpm->dpm_context)
365 return -ENOMEM;
366
367 if (smu_dpm->golden_dpm_context)
368 return -EINVAL;
369
370 smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table),
371 GFP_KERNEL);
372 if (!smu_dpm->golden_dpm_context)
373 return -ENOMEM;
374
375 smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);
376
377 smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
378 GFP_KERNEL);
379 if (!smu_dpm->dpm_current_power_state)
380 return -ENOMEM;
381
382 smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
383 GFP_KERNEL);
384 if (!smu_dpm->dpm_request_power_state)
385 return -ENOMEM;
386
387 return 0;
388 }
389
vega20_setup_od8_information(struct smu_context * smu)390 static int vega20_setup_od8_information(struct smu_context *smu)
391 {
392 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
393 struct smu_table_context *table_context = &smu->smu_table;
394 struct vega20_od8_settings *od8_settings = (struct vega20_od8_settings *)smu->od_settings;
395
396 uint32_t od_feature_count, od_feature_array_size,
397 od_setting_count, od_setting_array_size;
398
399 if (!table_context->power_play_table)
400 return -EINVAL;
401
402 powerplay_table = table_context->power_play_table;
403
404 if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
405 /* Setup correct ODFeatureCount, and store ODFeatureArray from
406 * powerplay table to od_feature_capabilities */
407 od_feature_count =
408 (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
409 ATOM_VEGA20_ODFEATURE_COUNT) ?
410 ATOM_VEGA20_ODFEATURE_COUNT :
411 le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
412
413 od_feature_array_size = sizeof(uint8_t) * od_feature_count;
414
415 if (od8_settings->od_feature_capabilities)
416 return -EINVAL;
417
418 od8_settings->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities,
419 od_feature_array_size,
420 GFP_KERNEL);
421 if (!od8_settings->od_feature_capabilities)
422 return -ENOMEM;
423
424 /* Setup correct ODSettingCount, and store ODSettingArray from
425 * powerplay table to od_settings_max and od_setting_min */
426 od_setting_count =
427 (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
428 ATOM_VEGA20_ODSETTING_COUNT) ?
429 ATOM_VEGA20_ODSETTING_COUNT :
430 le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
431
432 od_setting_array_size = sizeof(uint32_t) * od_setting_count;
433
434 if (od8_settings->od_settings_max)
435 return -EINVAL;
436
437 od8_settings->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax,
438 od_setting_array_size,
439 GFP_KERNEL);
440
441 if (!od8_settings->od_settings_max) {
442 kfree(od8_settings->od_feature_capabilities);
443 od8_settings->od_feature_capabilities = NULL;
444 return -ENOMEM;
445 }
446
447 if (od8_settings->od_settings_min)
448 return -EINVAL;
449
450 od8_settings->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin,
451 od_setting_array_size,
452 GFP_KERNEL);
453
454 if (!od8_settings->od_settings_min) {
455 kfree(od8_settings->od_feature_capabilities);
456 od8_settings->od_feature_capabilities = NULL;
457 kfree(od8_settings->od_settings_max);
458 od8_settings->od_settings_max = NULL;
459 return -ENOMEM;
460 }
461 }
462
463 return 0;
464 }
465
vega20_store_powerplay_table(struct smu_context * smu)466 static int vega20_store_powerplay_table(struct smu_context *smu)
467 {
468 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
469 struct smu_table_context *table_context = &smu->smu_table;
470
471 if (!table_context->power_play_table)
472 return -EINVAL;
473
474 powerplay_table = table_context->power_play_table;
475
476 memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
477 sizeof(PPTable_t));
478
479 table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
480
481 return 0;
482 }
483
vega20_append_powerplay_table(struct smu_context * smu)484 static int vega20_append_powerplay_table(struct smu_context *smu)
485 {
486 struct smu_table_context *table_context = &smu->smu_table;
487 PPTable_t *smc_pptable = table_context->driver_pptable;
488 struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
489 int index, i, ret;
490
491 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
492 smc_dpm_info);
493
494 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
495 (uint8_t **)&smc_dpm_table);
496 if (ret)
497 return ret;
498
499 smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
500 smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
501
502 smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
503 smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
504 smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
505 smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
506
507 smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
508 smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
509 smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
510
511 smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
512 smc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
513 smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
514
515 smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
516 smc_pptable->SocOffset = smc_dpm_table->socoffset;
517 smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
518
519 smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
520 smc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
521 smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
522
523 smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
524 smc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
525 smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
526
527 smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
528 smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
529 smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
530 smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
531
532 smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
533 smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
534 smc_pptable->Padding1 = smc_dpm_table->padding1;
535 smc_pptable->Padding2 = smc_dpm_table->padding2;
536
537 smc_pptable->LedPin0 = smc_dpm_table->ledpin0;
538 smc_pptable->LedPin1 = smc_dpm_table->ledpin1;
539 smc_pptable->LedPin2 = smc_dpm_table->ledpin2;
540
541 smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
542 smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
543 smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
544
545 smc_pptable->UclkSpreadEnabled = 0;
546 smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
547 smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
548
549 smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
550 smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
551 smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
552
553 smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
554 smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
555 smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
556
557 for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
558 smc_pptable->I2cControllers[i].Enabled =
559 smc_dpm_table->i2ccontrollers[i].enabled;
560 smc_pptable->I2cControllers[i].SlaveAddress =
561 smc_dpm_table->i2ccontrollers[i].slaveaddress;
562 smc_pptable->I2cControllers[i].ControllerPort =
563 smc_dpm_table->i2ccontrollers[i].controllerport;
564 smc_pptable->I2cControllers[i].ThermalThrottler =
565 smc_dpm_table->i2ccontrollers[i].thermalthrottler;
566 smc_pptable->I2cControllers[i].I2cProtocol =
567 smc_dpm_table->i2ccontrollers[i].i2cprotocol;
568 smc_pptable->I2cControllers[i].I2cSpeed =
569 smc_dpm_table->i2ccontrollers[i].i2cspeed;
570 }
571
572 return 0;
573 }
574
vega20_check_powerplay_table(struct smu_context * smu)575 static int vega20_check_powerplay_table(struct smu_context *smu)
576 {
577 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL;
578 struct smu_table_context *table_context = &smu->smu_table;
579
580 powerplay_table = table_context->power_play_table;
581
582 if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) {
583 pr_err("Unsupported PPTable format!");
584 return -EINVAL;
585 }
586
587 if (!powerplay_table->sHeader.structuresize) {
588 pr_err("Invalid PowerPlay Table!");
589 return -EINVAL;
590 }
591
592 return 0;
593 }
594
vega20_run_btc_afll(struct smu_context * smu)595 static int vega20_run_btc_afll(struct smu_context *smu)
596 {
597 return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
598 }
599
600 #define FEATURE_MASK(feature) (1ULL << feature)
601 static int
vega20_get_allowed_feature_mask(struct smu_context * smu,uint32_t * feature_mask,uint32_t num)602 vega20_get_allowed_feature_mask(struct smu_context *smu,
603 uint32_t *feature_mask, uint32_t num)
604 {
605 if (num > 2)
606 return -EINVAL;
607
608 memset(feature_mask, 0, sizeof(uint32_t) * num);
609
610 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
611 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
612 | FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
613 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
614 | FEATURE_MASK(FEATURE_DPM_UVD_BIT)
615 | FEATURE_MASK(FEATURE_DPM_VCE_BIT)
616 | FEATURE_MASK(FEATURE_ULV_BIT)
617 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
618 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
619 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
620 | FEATURE_MASK(FEATURE_PPT_BIT)
621 | FEATURE_MASK(FEATURE_TDC_BIT)
622 | FEATURE_MASK(FEATURE_THERMAL_BIT)
623 | FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT)
624 | FEATURE_MASK(FEATURE_RM_BIT)
625 | FEATURE_MASK(FEATURE_ACDC_BIT)
626 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
627 | FEATURE_MASK(FEATURE_VR1HOT_BIT)
628 | FEATURE_MASK(FEATURE_FW_CTF_BIT)
629 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
630 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
631 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
632 | FEATURE_MASK(FEATURE_GFXOFF_BIT)
633 | FEATURE_MASK(FEATURE_CG_BIT)
634 | FEATURE_MASK(FEATURE_DPM_FCLK_BIT)
635 | FEATURE_MASK(FEATURE_XGMI_BIT);
636 return 0;
637 }
638
639 static enum
vega20_get_current_power_state(struct smu_context * smu)640 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
641 {
642 enum amd_pm_state_type pm_type;
643 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
644
645 if (!smu_dpm_ctx->dpm_context ||
646 !smu_dpm_ctx->dpm_current_power_state)
647 return -EINVAL;
648
649 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
650 case SMU_STATE_UI_LABEL_BATTERY:
651 pm_type = POWER_STATE_TYPE_BATTERY;
652 break;
653 case SMU_STATE_UI_LABEL_BALLANCED:
654 pm_type = POWER_STATE_TYPE_BALANCED;
655 break;
656 case SMU_STATE_UI_LABEL_PERFORMANCE:
657 pm_type = POWER_STATE_TYPE_PERFORMANCE;
658 break;
659 default:
660 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
661 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
662 else
663 pm_type = POWER_STATE_TYPE_DEFAULT;
664 break;
665 }
666
667 return pm_type;
668 }
669
670 static int
vega20_set_single_dpm_table(struct smu_context * smu,struct vega20_single_dpm_table * single_dpm_table,PPCLK_e clk_id)671 vega20_set_single_dpm_table(struct smu_context *smu,
672 struct vega20_single_dpm_table *single_dpm_table,
673 PPCLK_e clk_id)
674 {
675 int ret = 0;
676 uint32_t i, num_of_levels = 0, clk;
677
678 ret = smu_send_smc_msg_with_param(smu,
679 SMU_MSG_GetDpmFreqByIndex,
680 (clk_id << 16 | 0xFF));
681 if (ret) {
682 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!");
683 return ret;
684 }
685
686 smu_read_smc_arg(smu, &num_of_levels);
687 if (!num_of_levels) {
688 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!");
689 return -EINVAL;
690 }
691
692 single_dpm_table->count = num_of_levels;
693
694 for (i = 0; i < num_of_levels; i++) {
695 ret = smu_send_smc_msg_with_param(smu,
696 SMU_MSG_GetDpmFreqByIndex,
697 (clk_id << 16 | i));
698 if (ret) {
699 pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!");
700 return ret;
701 }
702 smu_read_smc_arg(smu, &clk);
703 if (!clk) {
704 pr_err("[GetDpmFreqByIndex] clk value is invalid!");
705 return -EINVAL;
706 }
707 single_dpm_table->dpm_levels[i].value = clk;
708 single_dpm_table->dpm_levels[i].enabled = true;
709 }
710 return 0;
711 }
712
vega20_init_single_dpm_state(struct vega20_dpm_state * dpm_state)713 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state)
714 {
715 dpm_state->soft_min_level = 0x0;
716 dpm_state->soft_max_level = 0xffff;
717 dpm_state->hard_min_level = 0x0;
718 dpm_state->hard_max_level = 0xffff;
719 }
720
vega20_set_default_dpm_table(struct smu_context * smu)721 static int vega20_set_default_dpm_table(struct smu_context *smu)
722 {
723 int ret;
724
725 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
726 struct vega20_dpm_table *dpm_table = NULL;
727 struct vega20_single_dpm_table *single_dpm_table;
728
729 dpm_table = smu_dpm->dpm_context;
730
731 /* socclk */
732 single_dpm_table = &(dpm_table->soc_table);
733
734 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
735 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
736 PPCLK_SOCCLK);
737 if (ret) {
738 pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!");
739 return ret;
740 }
741 } else {
742 single_dpm_table->count = 1;
743 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
744 }
745 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
746
747 /* gfxclk */
748 single_dpm_table = &(dpm_table->gfx_table);
749
750 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
751 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
752 PPCLK_GFXCLK);
753 if (ret) {
754 pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!");
755 return ret;
756 }
757 } else {
758 single_dpm_table->count = 1;
759 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
760 }
761 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
762
763 /* memclk */
764 single_dpm_table = &(dpm_table->mem_table);
765
766 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
767 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
768 PPCLK_UCLK);
769 if (ret) {
770 pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!");
771 return ret;
772 }
773 } else {
774 single_dpm_table->count = 1;
775 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
776 }
777 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
778
779 /* eclk */
780 single_dpm_table = &(dpm_table->eclk_table);
781
782 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) {
783 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK);
784 if (ret) {
785 pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!");
786 return ret;
787 }
788 } else {
789 single_dpm_table->count = 1;
790 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100;
791 }
792 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
793
794 /* vclk */
795 single_dpm_table = &(dpm_table->vclk_table);
796
797 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
798 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK);
799 if (ret) {
800 pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!");
801 return ret;
802 }
803 } else {
804 single_dpm_table->count = 1;
805 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
806 }
807 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
808
809 /* dclk */
810 single_dpm_table = &(dpm_table->dclk_table);
811
812 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
813 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK);
814 if (ret) {
815 pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!");
816 return ret;
817 }
818 } else {
819 single_dpm_table->count = 1;
820 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
821 }
822 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
823
824 /* dcefclk */
825 single_dpm_table = &(dpm_table->dcef_table);
826
827 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
828 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
829 PPCLK_DCEFCLK);
830 if (ret) {
831 pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!");
832 return ret;
833 }
834 } else {
835 single_dpm_table->count = 1;
836 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
837 }
838 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
839
840 /* pixclk */
841 single_dpm_table = &(dpm_table->pixel_table);
842
843 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
844 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
845 PPCLK_PIXCLK);
846 if (ret) {
847 pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!");
848 return ret;
849 }
850 } else {
851 single_dpm_table->count = 0;
852 }
853 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
854
855 /* dispclk */
856 single_dpm_table = &(dpm_table->display_table);
857
858 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
859 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
860 PPCLK_DISPCLK);
861 if (ret) {
862 pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!");
863 return ret;
864 }
865 } else {
866 single_dpm_table->count = 0;
867 }
868 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
869
870 /* phyclk */
871 single_dpm_table = &(dpm_table->phy_table);
872
873 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
874 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
875 PPCLK_PHYCLK);
876 if (ret) {
877 pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!");
878 return ret;
879 }
880 } else {
881 single_dpm_table->count = 0;
882 }
883 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
884
885 /* fclk */
886 single_dpm_table = &(dpm_table->fclk_table);
887
888 if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) {
889 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
890 PPCLK_FCLK);
891 if (ret) {
892 pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!");
893 return ret;
894 }
895 } else {
896 single_dpm_table->count = 0;
897 }
898 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state));
899
900 memcpy(smu_dpm->golden_dpm_context, dpm_table,
901 sizeof(struct vega20_dpm_table));
902
903 return 0;
904 }
905
vega20_populate_umd_state_clk(struct smu_context * smu)906 static int vega20_populate_umd_state_clk(struct smu_context *smu)
907 {
908 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
909 struct vega20_dpm_table *dpm_table = NULL;
910 struct vega20_single_dpm_table *gfx_table = NULL;
911 struct vega20_single_dpm_table *mem_table = NULL;
912
913 dpm_table = smu_dpm->dpm_context;
914 gfx_table = &(dpm_table->gfx_table);
915 mem_table = &(dpm_table->mem_table);
916
917 smu->pstate_sclk = gfx_table->dpm_levels[0].value;
918 smu->pstate_mclk = mem_table->dpm_levels[0].value;
919
920 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
921 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
922 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
923 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
924 }
925
926 smu->pstate_sclk = smu->pstate_sclk * 100;
927 smu->pstate_mclk = smu->pstate_mclk * 100;
928
929 return 0;
930 }
931
vega20_get_clk_table(struct smu_context * smu,struct pp_clock_levels_with_latency * clocks,struct vega20_single_dpm_table * dpm_table)932 static int vega20_get_clk_table(struct smu_context *smu,
933 struct pp_clock_levels_with_latency *clocks,
934 struct vega20_single_dpm_table *dpm_table)
935 {
936 int i, count;
937
938 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
939 clocks->num_levels = count;
940
941 for (i = 0; i < count; i++) {
942 clocks->data[i].clocks_in_khz =
943 dpm_table->dpm_levels[i].value * 1000;
944 clocks->data[i].latency_in_us = 0;
945 }
946
947 return 0;
948 }
949
vega20_print_clk_levels(struct smu_context * smu,enum smu_clk_type type,char * buf)950 static int vega20_print_clk_levels(struct smu_context *smu,
951 enum smu_clk_type type, char *buf)
952 {
953 int i, now, size = 0;
954 int ret = 0;
955 uint32_t gen_speed, lane_width;
956 struct amdgpu_device *adev = smu->adev;
957 struct pp_clock_levels_with_latency clocks;
958 struct vega20_single_dpm_table *single_dpm_table;
959 struct smu_table_context *table_context = &smu->smu_table;
960 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
961 struct vega20_dpm_table *dpm_table = NULL;
962 struct vega20_od8_settings *od8_settings =
963 (struct vega20_od8_settings *)smu->od_settings;
964 OverDriveTable_t *od_table =
965 (OverDriveTable_t *)(table_context->overdrive_table);
966 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
967
968 dpm_table = smu_dpm->dpm_context;
969
970 switch (type) {
971 case SMU_SCLK:
972 ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now);
973 if (ret) {
974 pr_err("Attempt to get current gfx clk Failed!");
975 return ret;
976 }
977
978 single_dpm_table = &(dpm_table->gfx_table);
979 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
980 if (ret) {
981 pr_err("Attempt to get gfx clk levels Failed!");
982 return ret;
983 }
984
985 for (i = 0; i < clocks.num_levels; i++)
986 size += sprintf(buf + size, "%d: %uMhz %s\n", i,
987 clocks.data[i].clocks_in_khz / 1000,
988 (clocks.data[i].clocks_in_khz == now * 10)
989 ? "*" : "");
990 break;
991
992 case SMU_MCLK:
993 ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now);
994 if (ret) {
995 pr_err("Attempt to get current mclk Failed!");
996 return ret;
997 }
998
999 single_dpm_table = &(dpm_table->mem_table);
1000 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1001 if (ret) {
1002 pr_err("Attempt to get memory clk levels Failed!");
1003 return ret;
1004 }
1005
1006 for (i = 0; i < clocks.num_levels; i++)
1007 size += sprintf(buf + size, "%d: %uMhz %s\n",
1008 i, clocks.data[i].clocks_in_khz / 1000,
1009 (clocks.data[i].clocks_in_khz == now * 10)
1010 ? "*" : "");
1011 break;
1012
1013 case SMU_SOCCLK:
1014 ret = smu_get_current_clk_freq(smu, SMU_SOCCLK, &now);
1015 if (ret) {
1016 pr_err("Attempt to get current socclk Failed!");
1017 return ret;
1018 }
1019
1020 single_dpm_table = &(dpm_table->soc_table);
1021 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1022 if (ret) {
1023 pr_err("Attempt to get socclk levels Failed!");
1024 return ret;
1025 }
1026
1027 for (i = 0; i < clocks.num_levels; i++)
1028 size += sprintf(buf + size, "%d: %uMhz %s\n",
1029 i, clocks.data[i].clocks_in_khz / 1000,
1030 (clocks.data[i].clocks_in_khz == now * 10)
1031 ? "*" : "");
1032 break;
1033
1034 case SMU_FCLK:
1035 ret = smu_get_current_clk_freq(smu, SMU_FCLK, &now);
1036 if (ret) {
1037 pr_err("Attempt to get current fclk Failed!");
1038 return ret;
1039 }
1040
1041 single_dpm_table = &(dpm_table->fclk_table);
1042 for (i = 0; i < single_dpm_table->count; i++)
1043 size += sprintf(buf + size, "%d: %uMhz %s\n",
1044 i, single_dpm_table->dpm_levels[i].value,
1045 (single_dpm_table->dpm_levels[i].value == now / 100)
1046 ? "*" : "");
1047 break;
1048
1049 case SMU_DCEFCLK:
1050 ret = smu_get_current_clk_freq(smu, SMU_DCEFCLK, &now);
1051 if (ret) {
1052 pr_err("Attempt to get current dcefclk Failed!");
1053 return ret;
1054 }
1055
1056 single_dpm_table = &(dpm_table->dcef_table);
1057 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1058 if (ret) {
1059 pr_err("Attempt to get dcefclk levels Failed!");
1060 return ret;
1061 }
1062
1063 for (i = 0; i < clocks.num_levels; i++)
1064 size += sprintf(buf + size, "%d: %uMhz %s\n",
1065 i, clocks.data[i].clocks_in_khz / 1000,
1066 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
1067 break;
1068
1069 case SMU_PCIE:
1070 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
1071 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
1072 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
1073 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
1074 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
1075 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
1076 for (i = 0; i < NUM_LINK_LEVELS; i++)
1077 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
1078 (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," :
1079 (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," :
1080 (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," :
1081 (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "",
1082 (pptable->PcieLaneCount[i] == 1) ? "x1" :
1083 (pptable->PcieLaneCount[i] == 2) ? "x2" :
1084 (pptable->PcieLaneCount[i] == 3) ? "x4" :
1085 (pptable->PcieLaneCount[i] == 4) ? "x8" :
1086 (pptable->PcieLaneCount[i] == 5) ? "x12" :
1087 (pptable->PcieLaneCount[i] == 6) ? "x16" : "",
1088 pptable->LclkFreq[i],
1089 (gen_speed == pptable->PcieGenSpeed[i]) &&
1090 (lane_width == pptable->PcieLaneCount[i]) ?
1091 "*" : "");
1092 break;
1093
1094 case SMU_OD_SCLK:
1095 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1096 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1097 size = sprintf(buf, "%s:\n", "OD_SCLK");
1098 size += sprintf(buf + size, "0: %10uMhz\n",
1099 od_table->GfxclkFmin);
1100 size += sprintf(buf + size, "1: %10uMhz\n",
1101 od_table->GfxclkFmax);
1102 }
1103
1104 break;
1105
1106 case SMU_OD_MCLK:
1107 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1108 size = sprintf(buf, "%s:\n", "OD_MCLK");
1109 size += sprintf(buf + size, "1: %10uMhz\n",
1110 od_table->UclkFmax);
1111 }
1112
1113 break;
1114
1115 case SMU_OD_VDDC_CURVE:
1116 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1117 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1118 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1119 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1120 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1121 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1122 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
1123 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
1124 od_table->GfxclkFreq1,
1125 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
1126 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
1127 od_table->GfxclkFreq2,
1128 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
1129 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
1130 od_table->GfxclkFreq3,
1131 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
1132 }
1133
1134 break;
1135
1136 case SMU_OD_RANGE:
1137 size = sprintf(buf, "%s:\n", "OD_RANGE");
1138
1139 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id &&
1140 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) {
1141 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
1142 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value,
1143 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value);
1144 }
1145
1146 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) {
1147 single_dpm_table = &(dpm_table->mem_table);
1148 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table);
1149 if (ret) {
1150 pr_err("Attempt to get memory clk levels Failed!");
1151 return ret;
1152 }
1153
1154 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
1155 clocks.data[0].clocks_in_khz / 1000,
1156 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value);
1157 }
1158
1159 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
1160 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
1161 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
1162 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
1163 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
1164 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
1165 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1166 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value,
1167 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value);
1168 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1169 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
1170 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
1171 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1172 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value,
1173 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value);
1174 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1175 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
1176 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
1177 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1178 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value,
1179 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value);
1180 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1181 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
1182 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
1183 }
1184
1185 break;
1186
1187 default:
1188 break;
1189 }
1190 return size;
1191 }
1192
vega20_upload_dpm_level(struct smu_context * smu,bool max,uint32_t feature_mask)1193 static int vega20_upload_dpm_level(struct smu_context *smu, bool max,
1194 uint32_t feature_mask)
1195 {
1196 struct vega20_dpm_table *dpm_table;
1197 struct vega20_single_dpm_table *single_dpm_table;
1198 uint32_t freq;
1199 int ret = 0;
1200
1201 dpm_table = smu->smu_dpm.dpm_context;
1202
1203 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
1204 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1205 single_dpm_table = &(dpm_table->gfx_table);
1206 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1207 single_dpm_table->dpm_state.soft_min_level;
1208 ret = smu_send_smc_msg_with_param(smu,
1209 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1210 (PPCLK_GFXCLK << 16) | (freq & 0xffff));
1211 if (ret) {
1212 pr_err("Failed to set soft %s gfxclk !\n",
1213 max ? "max" : "min");
1214 return ret;
1215 }
1216 }
1217
1218 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
1219 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1220 single_dpm_table = &(dpm_table->mem_table);
1221 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1222 single_dpm_table->dpm_state.soft_min_level;
1223 ret = smu_send_smc_msg_with_param(smu,
1224 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1225 (PPCLK_UCLK << 16) | (freq & 0xffff));
1226 if (ret) {
1227 pr_err("Failed to set soft %s memclk !\n",
1228 max ? "max" : "min");
1229 return ret;
1230 }
1231 }
1232
1233 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
1234 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1235 single_dpm_table = &(dpm_table->soc_table);
1236 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1237 single_dpm_table->dpm_state.soft_min_level;
1238 ret = smu_send_smc_msg_with_param(smu,
1239 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1240 (PPCLK_SOCCLK << 16) | (freq & 0xffff));
1241 if (ret) {
1242 pr_err("Failed to set soft %s socclk !\n",
1243 max ? "max" : "min");
1244 return ret;
1245 }
1246 }
1247
1248 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) &&
1249 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1250 single_dpm_table = &(dpm_table->fclk_table);
1251 freq = max ? single_dpm_table->dpm_state.soft_max_level :
1252 single_dpm_table->dpm_state.soft_min_level;
1253 ret = smu_send_smc_msg_with_param(smu,
1254 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
1255 (PPCLK_FCLK << 16) | (freq & 0xffff));
1256 if (ret) {
1257 pr_err("Failed to set soft %s fclk !\n",
1258 max ? "max" : "min");
1259 return ret;
1260 }
1261 }
1262
1263 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
1264 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1265 single_dpm_table = &(dpm_table->dcef_table);
1266 freq = single_dpm_table->dpm_state.hard_min_level;
1267 if (!max) {
1268 ret = smu_send_smc_msg_with_param(smu,
1269 SMU_MSG_SetHardMinByFreq,
1270 (PPCLK_DCEFCLK << 16) | (freq & 0xffff));
1271 if (ret) {
1272 pr_err("Failed to set hard min dcefclk !\n");
1273 return ret;
1274 }
1275 }
1276 }
1277
1278 return ret;
1279 }
1280
vega20_force_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t mask)1281 static int vega20_force_clk_levels(struct smu_context *smu,
1282 enum smu_clk_type clk_type, uint32_t mask)
1283 {
1284 struct vega20_dpm_table *dpm_table;
1285 struct vega20_single_dpm_table *single_dpm_table;
1286 uint32_t soft_min_level, soft_max_level, hard_min_level;
1287 int ret = 0;
1288
1289 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1290 soft_max_level = mask ? (fls(mask) - 1) : 0;
1291
1292 dpm_table = smu->smu_dpm.dpm_context;
1293
1294 switch (clk_type) {
1295 case SMU_SCLK:
1296 single_dpm_table = &(dpm_table->gfx_table);
1297
1298 if (soft_max_level >= single_dpm_table->count) {
1299 pr_err("Clock level specified %d is over max allowed %d\n",
1300 soft_max_level, single_dpm_table->count - 1);
1301 ret = -EINVAL;
1302 break;
1303 }
1304
1305 single_dpm_table->dpm_state.soft_min_level =
1306 single_dpm_table->dpm_levels[soft_min_level].value;
1307 single_dpm_table->dpm_state.soft_max_level =
1308 single_dpm_table->dpm_levels[soft_max_level].value;
1309
1310 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK);
1311 if (ret) {
1312 pr_err("Failed to upload boot level to lowest!\n");
1313 break;
1314 }
1315
1316 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK);
1317 if (ret)
1318 pr_err("Failed to upload dpm max level to highest!\n");
1319
1320 break;
1321
1322 case SMU_MCLK:
1323 single_dpm_table = &(dpm_table->mem_table);
1324
1325 if (soft_max_level >= single_dpm_table->count) {
1326 pr_err("Clock level specified %d is over max allowed %d\n",
1327 soft_max_level, single_dpm_table->count - 1);
1328 ret = -EINVAL;
1329 break;
1330 }
1331
1332 single_dpm_table->dpm_state.soft_min_level =
1333 single_dpm_table->dpm_levels[soft_min_level].value;
1334 single_dpm_table->dpm_state.soft_max_level =
1335 single_dpm_table->dpm_levels[soft_max_level].value;
1336
1337 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK);
1338 if (ret) {
1339 pr_err("Failed to upload boot level to lowest!\n");
1340 break;
1341 }
1342
1343 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK);
1344 if (ret)
1345 pr_err("Failed to upload dpm max level to highest!\n");
1346
1347 break;
1348
1349 case SMU_SOCCLK:
1350 single_dpm_table = &(dpm_table->soc_table);
1351
1352 if (soft_max_level >= single_dpm_table->count) {
1353 pr_err("Clock level specified %d is over max allowed %d\n",
1354 soft_max_level, single_dpm_table->count - 1);
1355 ret = -EINVAL;
1356 break;
1357 }
1358
1359 single_dpm_table->dpm_state.soft_min_level =
1360 single_dpm_table->dpm_levels[soft_min_level].value;
1361 single_dpm_table->dpm_state.soft_max_level =
1362 single_dpm_table->dpm_levels[soft_max_level].value;
1363
1364 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK);
1365 if (ret) {
1366 pr_err("Failed to upload boot level to lowest!\n");
1367 break;
1368 }
1369
1370 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK);
1371 if (ret)
1372 pr_err("Failed to upload dpm max level to highest!\n");
1373
1374 break;
1375
1376 case SMU_FCLK:
1377 single_dpm_table = &(dpm_table->fclk_table);
1378
1379 if (soft_max_level >= single_dpm_table->count) {
1380 pr_err("Clock level specified %d is over max allowed %d\n",
1381 soft_max_level, single_dpm_table->count - 1);
1382 ret = -EINVAL;
1383 break;
1384 }
1385
1386 single_dpm_table->dpm_state.soft_min_level =
1387 single_dpm_table->dpm_levels[soft_min_level].value;
1388 single_dpm_table->dpm_state.soft_max_level =
1389 single_dpm_table->dpm_levels[soft_max_level].value;
1390
1391 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK);
1392 if (ret) {
1393 pr_err("Failed to upload boot level to lowest!\n");
1394 break;
1395 }
1396
1397 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK);
1398 if (ret)
1399 pr_err("Failed to upload dpm max level to highest!\n");
1400
1401 break;
1402
1403 case SMU_DCEFCLK:
1404 hard_min_level = soft_min_level;
1405 single_dpm_table = &(dpm_table->dcef_table);
1406
1407 if (hard_min_level >= single_dpm_table->count) {
1408 pr_err("Clock level specified %d is over max allowed %d\n",
1409 hard_min_level, single_dpm_table->count - 1);
1410 ret = -EINVAL;
1411 break;
1412 }
1413
1414 single_dpm_table->dpm_state.hard_min_level =
1415 single_dpm_table->dpm_levels[hard_min_level].value;
1416
1417 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK);
1418 if (ret)
1419 pr_err("Failed to upload boot level to lowest!\n");
1420
1421 break;
1422
1423 case SMU_PCIE:
1424 if (soft_min_level >= NUM_LINK_LEVELS ||
1425 soft_max_level >= NUM_LINK_LEVELS) {
1426 ret = -EINVAL;
1427 break;
1428 }
1429
1430 ret = smu_send_smc_msg_with_param(smu,
1431 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level);
1432 if (ret)
1433 pr_err("Failed to set min link dpm level!\n");
1434
1435 break;
1436
1437 default:
1438 break;
1439 }
1440
1441 return ret;
1442 }
1443
vega20_get_clock_by_type_with_latency(struct smu_context * smu,enum smu_clk_type clk_type,struct pp_clock_levels_with_latency * clocks)1444 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu,
1445 enum smu_clk_type clk_type,
1446 struct pp_clock_levels_with_latency *clocks)
1447 {
1448 int ret;
1449 struct vega20_single_dpm_table *single_dpm_table;
1450 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1451 struct vega20_dpm_table *dpm_table = NULL;
1452
1453 dpm_table = smu_dpm->dpm_context;
1454
1455 switch (clk_type) {
1456 case SMU_GFXCLK:
1457 single_dpm_table = &(dpm_table->gfx_table);
1458 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1459 break;
1460 case SMU_MCLK:
1461 single_dpm_table = &(dpm_table->mem_table);
1462 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1463 break;
1464 case SMU_DCEFCLK:
1465 single_dpm_table = &(dpm_table->dcef_table);
1466 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1467 break;
1468 case SMU_SOCCLK:
1469 single_dpm_table = &(dpm_table->soc_table);
1470 ret = vega20_get_clk_table(smu, clocks, single_dpm_table);
1471 break;
1472 default:
1473 ret = -EINVAL;
1474 }
1475
1476 return ret;
1477 }
1478
vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context * smu,uint32_t * voltage,uint32_t freq)1479 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1480 uint32_t *voltage,
1481 uint32_t freq)
1482 {
1483 int ret;
1484
1485 ret = smu_send_smc_msg_with_param(smu,
1486 SMU_MSG_GetAVFSVoltageByDpm,
1487 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1488 if (ret) {
1489 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1490 return ret;
1491 }
1492
1493 smu_read_smc_arg(smu, voltage);
1494 *voltage = *voltage / VOLTAGE_SCALE;
1495
1496 return 0;
1497 }
1498
vega20_set_default_od8_setttings(struct smu_context * smu)1499 static int vega20_set_default_od8_setttings(struct smu_context *smu)
1500 {
1501 struct smu_table_context *table_context = &smu->smu_table;
1502 OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table);
1503 struct vega20_od8_settings *od8_settings = NULL;
1504 PPTable_t *smc_pptable = table_context->driver_pptable;
1505 int i, ret;
1506
1507 if (smu->od_settings)
1508 return -EINVAL;
1509
1510 od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL);
1511
1512 if (!od8_settings)
1513 return -ENOMEM;
1514
1515 smu->od_settings = (void *)od8_settings;
1516
1517 ret = vega20_setup_od8_information(smu);
1518 if (ret) {
1519 pr_err("Retrieve board OD limits failed!\n");
1520 return ret;
1521 }
1522
1523 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
1524 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1525 od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1526 od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1527 (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1528 od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) {
1529 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1530 OD8_GFXCLK_LIMITS;
1531 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1532 OD8_GFXCLK_LIMITS;
1533 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1534 od_table->GfxclkFmin;
1535 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1536 od_table->GfxclkFmax;
1537 }
1538
1539 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1540 (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1541 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) &&
1542 (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1543 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) &&
1544 (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <=
1545 od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) {
1546 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1547 OD8_GFXCLK_CURVE;
1548 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1549 OD8_GFXCLK_CURVE;
1550 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1551 OD8_GFXCLK_CURVE;
1552 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1553 OD8_GFXCLK_CURVE;
1554 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1555 OD8_GFXCLK_CURVE;
1556 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1557 OD8_GFXCLK_CURVE;
1558
1559 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1560 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2;
1561 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1562 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1563 od_table->GfxclkFreq1;
1564 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1565 od_table->GfxclkFreq2;
1566 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1567 od_table->GfxclkFreq3;
1568
1569 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1570 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value,
1571 od_table->GfxclkFreq1);
1572 if (ret)
1573 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0;
1574 od_table->GfxclkVolt1 =
1575 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1576 * VOLTAGE_SCALE;
1577 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1578 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value,
1579 od_table->GfxclkFreq2);
1580 if (ret)
1581 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0;
1582 od_table->GfxclkVolt2 =
1583 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1584 * VOLTAGE_SCALE;
1585 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu,
1586 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value,
1587 od_table->GfxclkFreq3);
1588 if (ret)
1589 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0;
1590 od_table->GfxclkVolt3 =
1591 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1592 * VOLTAGE_SCALE;
1593 }
1594 }
1595
1596 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1597 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1598 od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1599 od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1600 (od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1601 od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX])) {
1602 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id =
1603 OD8_UCLK_MAX;
1604 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1605 od_table->UclkFmax;
1606 }
1607 }
1608
1609 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1610 od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1611 od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1612 od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1613 od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) {
1614 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id =
1615 OD8_POWER_LIMIT;
1616 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1617 od_table->OverDrivePct;
1618 }
1619
1620 if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) {
1621 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1622 od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1623 od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1624 (od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1625 od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) {
1626 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1627 OD8_ACOUSTIC_LIMIT_SCLK;
1628 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1629 od_table->FanMaximumRpm;
1630 }
1631
1632 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1633 od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1634 od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1635 (od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1636 od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) {
1637 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1638 OD8_FAN_SPEED_MIN;
1639 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1640 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100;
1641 }
1642 }
1643
1644 if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) {
1645 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1646 od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1647 od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1648 (od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1649 od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) {
1650 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1651 OD8_TEMPERATURE_FAN;
1652 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1653 od_table->FanTargetTemperature;
1654 }
1655
1656 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1657 od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1658 od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1659 (od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1660 od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) {
1661 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1662 OD8_TEMPERATURE_SYSTEM;
1663 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1664 od_table->MaxOpTemp;
1665 }
1666 }
1667
1668 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1669 if (od8_settings->od8_settings_array[i].feature_id) {
1670 od8_settings->od8_settings_array[i].min_value =
1671 od8_settings->od_settings_min[i];
1672 od8_settings->od8_settings_array[i].max_value =
1673 od8_settings->od_settings_max[i];
1674 od8_settings->od8_settings_array[i].current_value =
1675 od8_settings->od8_settings_array[i].default_value;
1676 } else {
1677 od8_settings->od8_settings_array[i].min_value = 0;
1678 od8_settings->od8_settings_array[i].max_value = 0;
1679 od8_settings->od8_settings_array[i].current_value = 0;
1680 }
1681 }
1682
1683 return 0;
1684 }
1685
vega20_get_metrics_table(struct smu_context * smu,SmuMetrics_t * metrics_table)1686 static int vega20_get_metrics_table(struct smu_context *smu,
1687 SmuMetrics_t *metrics_table)
1688 {
1689 struct smu_table_context *smu_table= &smu->smu_table;
1690 int ret = 0;
1691
1692 mutex_lock(&smu->metrics_lock);
1693 if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
1694 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
1695 (void *)smu_table->metrics_table, false);
1696 if (ret) {
1697 pr_info("Failed to export SMU metrics table!\n");
1698 mutex_unlock(&smu->metrics_lock);
1699 return ret;
1700 }
1701 smu_table->metrics_time = jiffies;
1702 }
1703
1704 memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
1705 mutex_unlock(&smu->metrics_lock);
1706
1707 return ret;
1708 }
1709
vega20_set_default_od_settings(struct smu_context * smu,bool initialize)1710 static int vega20_set_default_od_settings(struct smu_context *smu,
1711 bool initialize)
1712 {
1713 struct smu_table_context *table_context = &smu->smu_table;
1714 int ret;
1715
1716 ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t));
1717 if (ret)
1718 return ret;
1719
1720 if (initialize) {
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
vega20_get_od_percentage(struct smu_context * smu,enum smu_clk_type clk_type)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
vega20_get_power_profile_mode(struct smu_context * smu,char * buf)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
vega20_set_power_profile_mode(struct smu_context * smu,long * input,uint32_t size)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
vega20_get_profiling_clk_mask(struct smu_context * smu,enum amd_dpm_forced_level level,uint32_t * sclk_mask,uint32_t * mclk_mask,uint32_t * soc_mask)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
vega20_set_uclk_to_highest_dpm_level(struct smu_context * smu,struct vega20_single_dpm_table * dpm_table)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
vega20_pre_display_config_changed(struct smu_context * smu)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
vega20_display_config_changed(struct smu_context * smu)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
vega20_apply_clocks_adjust_rules(struct smu_context * smu)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
vega20_notify_smc_display_config(struct smu_context * smu)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
vega20_find_lowest_dpm_level(struct vega20_single_dpm_table * table)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
vega20_find_highest_dpm_level(struct vega20_single_dpm_table * table)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
vega20_force_dpm_limit_value(struct smu_context * smu,bool highest)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
vega20_unforce_dpm_levels(struct smu_context * smu)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
vega20_update_specified_od8_value(struct smu_context * smu,uint32_t index,uint32_t value)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
vega20_update_od8_settings(struct smu_context * smu,uint32_t index,uint32_t value)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
vega20_set_od_percentage(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t value)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
vega20_odn_edit_dpm_table(struct smu_context * smu,enum PP_OD_DPM_TABLE_COMMAND type,long * input,uint32_t size)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 if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) {
2778 pr_err("Overdrive table was not initialized!\n");
2779 return -EINVAL;
2780 }
2781 memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
2782 break;
2783
2784 case PP_OD_COMMIT_DPM_TABLE:
2785 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
2786 if (ret) {
2787 pr_err("Failed to import over drive table!\n");
2788 return ret;
2789 }
2790
2791 /* retrieve updated gfxclk table */
2792 if (od8_settings->od_gfxclk_update) {
2793 od8_settings->od_gfxclk_update = false;
2794 single_dpm_table = &(dpm_table->gfx_table);
2795
2796 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
2797 ret = vega20_set_single_dpm_table(smu, single_dpm_table,
2798 PPCLK_GFXCLK);
2799 if (ret) {
2800 pr_err("[Setoverdrive] failed to refresh dpm table!\n");
2801 return ret;
2802 }
2803 } else {
2804 single_dpm_table->count = 1;
2805 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
2806 }
2807 }
2808
2809 break;
2810
2811 default:
2812 return -EINVAL;
2813 }
2814
2815 if (type == PP_OD_COMMIT_DPM_TABLE) {
2816 ret = smu_handle_task(smu, smu_dpm->dpm_level,
2817 AMD_PP_TASK_READJUST_POWER_STATE,
2818 false);
2819 }
2820
2821 return ret;
2822 }
2823
vega20_dpm_set_uvd_enable(struct smu_context * smu,bool enable)2824 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
2825 {
2826 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT))
2827 return 0;
2828
2829 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT))
2830 return 0;
2831
2832 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable);
2833 }
2834
vega20_dpm_set_vce_enable(struct smu_context * smu,bool enable)2835 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable)
2836 {
2837 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT))
2838 return 0;
2839
2840 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT))
2841 return 0;
2842
2843 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable);
2844 }
2845
vega20_is_dpm_running(struct smu_context * smu)2846 static bool vega20_is_dpm_running(struct smu_context *smu)
2847 {
2848 int ret __unused = 0;
2849 uint32_t feature_mask[2];
2850 unsigned long feature_enabled;
2851 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
2852 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
2853 ((uint64_t)feature_mask[1] << 32));
2854 return !!(feature_enabled & SMC_DPM_FEATURE);
2855 }
2856
vega20_set_thermal_fan_table(struct smu_context * smu)2857 static int vega20_set_thermal_fan_table(struct smu_context *smu)
2858 {
2859 int ret;
2860 struct smu_table_context *table_context = &smu->smu_table;
2861 PPTable_t *pptable = table_context->driver_pptable;
2862
2863 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
2864 (uint32_t)pptable->FanTargetTemperature);
2865
2866 return ret;
2867 }
2868
vega20_get_fan_speed_rpm(struct smu_context * smu,uint32_t * speed)2869 static int vega20_get_fan_speed_rpm(struct smu_context *smu,
2870 uint32_t *speed)
2871 {
2872 int ret;
2873
2874 ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
2875
2876 if (ret) {
2877 pr_err("Attempt to get current RPM from SMC Failed!\n");
2878 return ret;
2879 }
2880
2881 smu_read_smc_arg(smu, speed);
2882
2883 return 0;
2884 }
2885
vega20_get_fan_speed_percent(struct smu_context * smu,uint32_t * speed)2886 static int vega20_get_fan_speed_percent(struct smu_context *smu,
2887 uint32_t *speed)
2888 {
2889 int ret = 0;
2890 uint32_t current_rpm = 0, percent = 0;
2891 PPTable_t *pptable = smu->smu_table.driver_pptable;
2892
2893 ret = vega20_get_fan_speed_rpm(smu, ¤t_rpm);
2894 if (ret)
2895 return ret;
2896
2897 percent = current_rpm * 100 / pptable->FanMaximumRpm;
2898 *speed = percent > 100 ? 100 : percent;
2899
2900 return 0;
2901 }
2902
vega20_get_gpu_power(struct smu_context * smu,uint32_t * value)2903 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
2904 {
2905 uint32_t smu_version;
2906 int ret = 0;
2907 SmuMetrics_t metrics;
2908
2909 if (!value)
2910 return -EINVAL;
2911
2912 ret = vega20_get_metrics_table(smu, &metrics);
2913 if (ret)
2914 return ret;
2915
2916 ret = smu_get_smc_version(smu, NULL, &smu_version);
2917 if (ret)
2918 return ret;
2919
2920 /* For the 40.46 release, they changed the value name */
2921 if (smu_version == 0x282e00)
2922 *value = metrics.AverageSocketPower << 8;
2923 else
2924 *value = metrics.CurrSocketPower << 8;
2925
2926 return 0;
2927 }
2928
vega20_get_current_activity_percent(struct smu_context * smu,enum amd_pp_sensors sensor,uint32_t * value)2929 static int vega20_get_current_activity_percent(struct smu_context *smu,
2930 enum amd_pp_sensors sensor,
2931 uint32_t *value)
2932 {
2933 int ret = 0;
2934 SmuMetrics_t metrics;
2935
2936 if (!value)
2937 return -EINVAL;
2938
2939 ret = vega20_get_metrics_table(smu, &metrics);
2940 if (ret)
2941 return ret;
2942
2943 switch (sensor) {
2944 case AMDGPU_PP_SENSOR_GPU_LOAD:
2945 *value = metrics.AverageGfxActivity;
2946 break;
2947 case AMDGPU_PP_SENSOR_MEM_LOAD:
2948 *value = metrics.AverageUclkActivity;
2949 break;
2950 default:
2951 pr_err("Invalid sensor for retrieving clock activity\n");
2952 return -EINVAL;
2953 }
2954
2955 return 0;
2956 }
2957
vega20_thermal_get_temperature(struct smu_context * smu,enum amd_pp_sensors sensor,uint32_t * value)2958 static int vega20_thermal_get_temperature(struct smu_context *smu,
2959 enum amd_pp_sensors sensor,
2960 uint32_t *value)
2961 {
2962 struct amdgpu_device *adev = smu->adev;
2963 SmuMetrics_t metrics;
2964 uint32_t temp = 0;
2965 int ret = 0;
2966
2967 if (!value)
2968 return -EINVAL;
2969
2970 ret = vega20_get_metrics_table(smu, &metrics);
2971 if (ret)
2972 return ret;
2973
2974 switch (sensor) {
2975 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2976 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
2977 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
2978 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
2979
2980 temp = temp & 0x1ff;
2981 temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2982
2983 *value = temp;
2984 break;
2985 case AMDGPU_PP_SENSOR_EDGE_TEMP:
2986 *value = metrics.TemperatureEdge *
2987 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2988 break;
2989 case AMDGPU_PP_SENSOR_MEM_TEMP:
2990 *value = metrics.TemperatureHBM *
2991 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2992 break;
2993 default:
2994 pr_err("Invalid sensor for retrieving temp\n");
2995 return -EINVAL;
2996 }
2997
2998 return 0;
2999 }
vega20_read_sensor(struct smu_context * smu,enum amd_pp_sensors sensor,void * data,uint32_t * size)3000 static int vega20_read_sensor(struct smu_context *smu,
3001 enum amd_pp_sensors sensor,
3002 void *data, uint32_t *size)
3003 {
3004 int ret = 0;
3005 struct smu_table_context *table_context = &smu->smu_table;
3006 PPTable_t *pptable = table_context->driver_pptable;
3007
3008 if(!data || !size)
3009 return -EINVAL;
3010
3011 mutex_lock(&smu->sensor_lock);
3012 switch (sensor) {
3013 case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
3014 *(uint32_t *)data = pptable->FanMaximumRpm;
3015 *size = 4;
3016 break;
3017 case AMDGPU_PP_SENSOR_MEM_LOAD:
3018 case AMDGPU_PP_SENSOR_GPU_LOAD:
3019 ret = vega20_get_current_activity_percent(smu,
3020 sensor,
3021 (uint32_t *)data);
3022 *size = 4;
3023 break;
3024 case AMDGPU_PP_SENSOR_GPU_POWER:
3025 ret = vega20_get_gpu_power(smu, (uint32_t *)data);
3026 *size = 4;
3027 break;
3028 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3029 case AMDGPU_PP_SENSOR_EDGE_TEMP:
3030 case AMDGPU_PP_SENSOR_MEM_TEMP:
3031 ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data);
3032 *size = 4;
3033 break;
3034 default:
3035 ret = smu_v11_0_read_sensor(smu, sensor, data, size);
3036 }
3037 mutex_unlock(&smu->sensor_lock);
3038
3039 return ret;
3040 }
3041
vega20_set_watermarks_table(struct smu_context * smu,void * watermarks,struct dm_pp_wm_sets_with_clock_ranges_soc15 * clock_ranges)3042 static int vega20_set_watermarks_table(struct smu_context *smu,
3043 void *watermarks, struct
3044 dm_pp_wm_sets_with_clock_ranges_soc15
3045 *clock_ranges)
3046 {
3047 int i;
3048 Watermarks_t *table = watermarks;
3049
3050 if (!table || !clock_ranges)
3051 return -EINVAL;
3052
3053 if (clock_ranges->num_wm_dmif_sets > 4 ||
3054 clock_ranges->num_wm_mcif_sets > 4)
3055 return -EINVAL;
3056
3057 for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
3058 table->WatermarkRow[1][i].MinClock =
3059 cpu_to_le16((uint16_t)
3060 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
3061 1000));
3062 table->WatermarkRow[1][i].MaxClock =
3063 cpu_to_le16((uint16_t)
3064 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
3065 1000));
3066 table->WatermarkRow[1][i].MinUclk =
3067 cpu_to_le16((uint16_t)
3068 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3069 1000));
3070 table->WatermarkRow[1][i].MaxUclk =
3071 cpu_to_le16((uint16_t)
3072 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3073 1000));
3074 table->WatermarkRow[1][i].WmSetting = (uint8_t)
3075 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
3076 }
3077
3078 for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
3079 table->WatermarkRow[0][i].MinClock =
3080 cpu_to_le16((uint16_t)
3081 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
3082 1000));
3083 table->WatermarkRow[0][i].MaxClock =
3084 cpu_to_le16((uint16_t)
3085 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
3086 1000));
3087 table->WatermarkRow[0][i].MinUclk =
3088 cpu_to_le16((uint16_t)
3089 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
3090 1000));
3091 table->WatermarkRow[0][i].MaxUclk =
3092 cpu_to_le16((uint16_t)
3093 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
3094 1000));
3095 table->WatermarkRow[0][i].WmSetting = (uint8_t)
3096 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
3097 }
3098
3099 return 0;
3100 }
3101
vega20_get_thermal_temperature_range(struct smu_context * smu,struct smu_temperature_range * range)3102 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
3103 struct smu_temperature_range *range)
3104 {
3105 struct smu_table_context *table_context = &smu->smu_table;
3106 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
3107 PPTable_t *pptable = smu->smu_table.driver_pptable;
3108
3109 if (!range || !powerplay_table)
3110 return -EINVAL;
3111
3112 range->max = powerplay_table->usSoftwareShutdownTemp *
3113 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3114 range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
3115 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3116 range->hotspot_crit_max = pptable->ThotspotLimit *
3117 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3118 range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
3119 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3120 range->mem_crit_max = pptable->ThbmLimit *
3121 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3122 range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM) *
3123 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
3124
3125
3126 return 0;
3127 }
3128
vega20_set_df_cstate(struct smu_context * smu,enum pp_df_cstate state)3129 static int vega20_set_df_cstate(struct smu_context *smu,
3130 enum pp_df_cstate state)
3131 {
3132 uint32_t smu_version;
3133 int ret;
3134
3135 ret = smu_get_smc_version(smu, NULL, &smu_version);
3136 if (ret) {
3137 pr_err("Failed to get smu version!\n");
3138 return ret;
3139 }
3140
3141 /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
3142 if (smu_version < 0x283200) {
3143 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
3144 return -EINVAL;
3145 }
3146
3147 return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state);
3148 }
3149
vega20_update_pcie_parameters(struct smu_context * smu,uint32_t pcie_gen_cap,uint32_t pcie_width_cap)3150 static int vega20_update_pcie_parameters(struct smu_context *smu,
3151 uint32_t pcie_gen_cap,
3152 uint32_t pcie_width_cap)
3153 {
3154 PPTable_t *pptable = smu->smu_table.driver_pptable;
3155 int ret, i;
3156 uint32_t smu_pcie_arg;
3157
3158 for (i = 0; i < NUM_LINK_LEVELS; i++) {
3159 smu_pcie_arg = (i << 16) |
3160 ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
3161 (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
3162 pptable->PcieLaneCount[i] : pcie_width_cap);
3163 ret = smu_send_smc_msg_with_param(smu,
3164 SMU_MSG_OverridePcieParameters,
3165 smu_pcie_arg);
3166 }
3167
3168 return ret;
3169 }
3170
3171
3172 static const struct pptable_funcs vega20_ppt_funcs = {
3173 .tables_init = vega20_tables_init,
3174 .alloc_dpm_context = vega20_allocate_dpm_context,
3175 .store_powerplay_table = vega20_store_powerplay_table,
3176 .check_powerplay_table = vega20_check_powerplay_table,
3177 .append_powerplay_table = vega20_append_powerplay_table,
3178 .get_smu_msg_index = vega20_get_smu_msg_index,
3179 .get_smu_clk_index = vega20_get_smu_clk_index,
3180 .get_smu_feature_index = vega20_get_smu_feature_index,
3181 .get_smu_table_index = vega20_get_smu_table_index,
3182 .get_smu_power_index = vega20_get_pwr_src_index,
3183 .get_workload_type = vega20_get_workload_type,
3184 .run_btc = vega20_run_btc_afll,
3185 .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
3186 .get_current_power_state = vega20_get_current_power_state,
3187 .set_default_dpm_table = vega20_set_default_dpm_table,
3188 .set_power_state = NULL,
3189 .populate_umd_state_clk = vega20_populate_umd_state_clk,
3190 .print_clk_levels = vega20_print_clk_levels,
3191 .force_clk_levels = vega20_force_clk_levels,
3192 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
3193 .get_od_percentage = vega20_get_od_percentage,
3194 .get_power_profile_mode = vega20_get_power_profile_mode,
3195 .set_power_profile_mode = vega20_set_power_profile_mode,
3196 .set_performance_level = smu_v11_0_set_performance_level,
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_driver_table_location = smu_v11_0_set_driver_table_location,
3235 .set_tool_table_location = smu_v11_0_set_tool_table_location,
3236 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
3237 .system_features_control = smu_v11_0_system_features_control,
3238 .send_smc_msg_with_param = smu_v11_0_send_msg_with_param,
3239 .read_smc_arg = smu_v11_0_read_arg,
3240 .init_display_count = smu_v11_0_init_display_count,
3241 .set_allowed_mask = smu_v11_0_set_allowed_mask,
3242 .get_enabled_mask = smu_v11_0_get_enabled_mask,
3243 .notify_display_change = smu_v11_0_notify_display_change,
3244 .set_power_limit = smu_v11_0_set_power_limit,
3245 .get_current_clk_freq = smu_v11_0_get_current_clk_freq,
3246 .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
3247 .start_thermal_control = smu_v11_0_start_thermal_control,
3248 .stop_thermal_control = smu_v11_0_stop_thermal_control,
3249 .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
3250 .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
3251 .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
3252 .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
3253 .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
3254 .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
3255 .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
3256 .gfx_off_control = smu_v11_0_gfx_off_control,
3257 .register_irq_handler = smu_v11_0_register_irq_handler,
3258 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
3259 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
3260 .baco_is_support= smu_v11_0_baco_is_support,
3261 .baco_get_state = smu_v11_0_baco_get_state,
3262 .baco_set_state = smu_v11_0_baco_set_state,
3263 .baco_enter = smu_v11_0_baco_enter,
3264 .baco_exit = smu_v11_0_baco_exit,
3265 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
3266 .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
3267 .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
3268 };
3269
vega20_set_ppt_funcs(struct smu_context * smu)3270 void vega20_set_ppt_funcs(struct smu_context *smu)
3271 {
3272 smu->ppt_funcs = &vega20_ppt_funcs;
3273 }
3274