Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / amd / powerplay / navi10_ppt.c
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #include "pp_debug.h"
25 #include <linux/firmware.h>
26 #include <linux/pci.h>
27 #include "amdgpu.h"
28 #include "amdgpu_smu.h"
29 #include "atomfirmware.h"
30 #include "amdgpu_atomfirmware.h"
31 #include "smu_v11_0.h"
32 #include "smu11_driver_if_navi10.h"
33 #include "soc15_common.h"
34 #include "atom.h"
35 #include "navi10_ppt.h"
36 #include "smu_v11_0_pptable.h"
37 #include "smu_v11_0_ppsmc.h"
38
39 #include "asic_reg/mp/mp_11_0_sh_mask.h"
40
41 #define FEATURE_MASK(feature) (1ULL << feature)
42 #define SMC_DPM_FEATURE ( \
43         FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
44         FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
45         FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT)   | \
46         FEATURE_MASK(FEATURE_DPM_UCLK_BIT)       | \
47         FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
48         FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)     | \
49         FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
50         FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
51
52 #define MSG_MAP(msg, index) \
53         [SMU_MSG_##msg] = {1, (index)}
54
55 static struct smu_11_0_cmn2aisc_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
56         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
57         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
58         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
59         MSG_MAP(SetAllowedFeaturesMaskLow,      PPSMC_MSG_SetAllowedFeaturesMaskLow),
60         MSG_MAP(SetAllowedFeaturesMaskHigh,     PPSMC_MSG_SetAllowedFeaturesMaskHigh),
61         MSG_MAP(EnableAllSmuFeatures,           PPSMC_MSG_EnableAllSmuFeatures),
62         MSG_MAP(DisableAllSmuFeatures,          PPSMC_MSG_DisableAllSmuFeatures),
63         MSG_MAP(EnableSmuFeaturesLow,           PPSMC_MSG_EnableSmuFeaturesLow),
64         MSG_MAP(EnableSmuFeaturesHigh,          PPSMC_MSG_EnableSmuFeaturesHigh),
65         MSG_MAP(DisableSmuFeaturesLow,          PPSMC_MSG_DisableSmuFeaturesLow),
66         MSG_MAP(DisableSmuFeaturesHigh,         PPSMC_MSG_DisableSmuFeaturesHigh),
67         MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetEnabledSmuFeaturesLow),
68         MSG_MAP(GetEnabledSmuFeaturesHigh,      PPSMC_MSG_GetEnabledSmuFeaturesHigh),
69         MSG_MAP(SetWorkloadMask,                PPSMC_MSG_SetWorkloadMask),
70         MSG_MAP(SetPptLimit,                    PPSMC_MSG_SetPptLimit),
71         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
72         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
73         MSG_MAP(SetToolsDramAddrHigh,           PPSMC_MSG_SetToolsDramAddrHigh),
74         MSG_MAP(SetToolsDramAddrLow,            PPSMC_MSG_SetToolsDramAddrLow),
75         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
76         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
77         MSG_MAP(UseDefaultPPTable,              PPSMC_MSG_UseDefaultPPTable),
78         MSG_MAP(UseBackupPPTable,               PPSMC_MSG_UseBackupPPTable),
79         MSG_MAP(RunBtc,                         PPSMC_MSG_RunBtc),
80         MSG_MAP(EnterBaco,                      PPSMC_MSG_EnterBaco),
81         MSG_MAP(SetSoftMinByFreq,               PPSMC_MSG_SetSoftMinByFreq),
82         MSG_MAP(SetSoftMaxByFreq,               PPSMC_MSG_SetSoftMaxByFreq),
83         MSG_MAP(SetHardMinByFreq,               PPSMC_MSG_SetHardMinByFreq),
84         MSG_MAP(SetHardMaxByFreq,               PPSMC_MSG_SetHardMaxByFreq),
85         MSG_MAP(GetMinDpmFreq,                  PPSMC_MSG_GetMinDpmFreq),
86         MSG_MAP(GetMaxDpmFreq,                  PPSMC_MSG_GetMaxDpmFreq),
87         MSG_MAP(GetDpmFreqByIndex,              PPSMC_MSG_GetDpmFreqByIndex),
88         MSG_MAP(SetMemoryChannelConfig,         PPSMC_MSG_SetMemoryChannelConfig),
89         MSG_MAP(SetGeminiMode,                  PPSMC_MSG_SetGeminiMode),
90         MSG_MAP(SetGeminiApertureHigh,          PPSMC_MSG_SetGeminiApertureHigh),
91         MSG_MAP(SetGeminiApertureLow,           PPSMC_MSG_SetGeminiApertureLow),
92         MSG_MAP(OverridePcieParameters,         PPSMC_MSG_OverridePcieParameters),
93         MSG_MAP(SetMinDeepSleepDcefclk,         PPSMC_MSG_SetMinDeepSleepDcefclk),
94         MSG_MAP(ReenableAcDcInterrupt,          PPSMC_MSG_ReenableAcDcInterrupt),
95         MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource),
96         MSG_MAP(SetUclkFastSwitch,              PPSMC_MSG_SetUclkFastSwitch),
97         MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
98         MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload),
99         MSG_MAP(DramLogSetDramAddrHigh,         PPSMC_MSG_DramLogSetDramAddrHigh),
100         MSG_MAP(DramLogSetDramAddrLow,          PPSMC_MSG_DramLogSetDramAddrLow),
101         MSG_MAP(DramLogSetDramSize,             PPSMC_MSG_DramLogSetDramSize),
102         MSG_MAP(ConfigureGfxDidt,               PPSMC_MSG_ConfigureGfxDidt),
103         MSG_MAP(NumOfDisplays,                  PPSMC_MSG_NumOfDisplays),
104         MSG_MAP(SetSystemVirtualDramAddrHigh,   PPSMC_MSG_SetSystemVirtualDramAddrHigh),
105         MSG_MAP(SetSystemVirtualDramAddrLow,    PPSMC_MSG_SetSystemVirtualDramAddrLow),
106         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff),
107         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff),
108         MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit),
109         MSG_MAP(GetDcModeMaxDpmFreq,            PPSMC_MSG_GetDcModeMaxDpmFreq),
110         MSG_MAP(GetDebugData,                   PPSMC_MSG_GetDebugData),
111         MSG_MAP(ExitBaco,                       PPSMC_MSG_ExitBaco),
112         MSG_MAP(PrepareMp1ForReset,             PPSMC_MSG_PrepareMp1ForReset),
113         MSG_MAP(PrepareMp1ForShutdown,          PPSMC_MSG_PrepareMp1ForShutdown),
114         MSG_MAP(PowerUpVcn,             PPSMC_MSG_PowerUpVcn),
115         MSG_MAP(PowerDownVcn,           PPSMC_MSG_PowerDownVcn),
116         MSG_MAP(PowerUpJpeg,            PPSMC_MSG_PowerUpJpeg),
117         MSG_MAP(PowerDownJpeg,          PPSMC_MSG_PowerDownJpeg),
118         MSG_MAP(BacoAudioD3PME,         PPSMC_MSG_BacoAudioD3PME),
119         MSG_MAP(ArmD3,                  PPSMC_MSG_ArmD3),
120 };
121
122 static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
123         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
124         CLK_MAP(SCLK,   PPCLK_GFXCLK),
125         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
126         CLK_MAP(FCLK, PPCLK_SOCCLK),
127         CLK_MAP(UCLK, PPCLK_UCLK),
128         CLK_MAP(MCLK, PPCLK_UCLK),
129         CLK_MAP(DCLK, PPCLK_DCLK),
130         CLK_MAP(VCLK, PPCLK_VCLK),
131         CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
132         CLK_MAP(DISPCLK, PPCLK_DISPCLK),
133         CLK_MAP(PIXCLK, PPCLK_PIXCLK),
134         CLK_MAP(PHYCLK, PPCLK_PHYCLK),
135 };
136
137 static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
138         FEA_MAP(DPM_PREFETCHER),
139         FEA_MAP(DPM_GFXCLK),
140         FEA_MAP(DPM_GFX_PACE),
141         FEA_MAP(DPM_UCLK),
142         FEA_MAP(DPM_SOCCLK),
143         FEA_MAP(DPM_MP0CLK),
144         FEA_MAP(DPM_LINK),
145         FEA_MAP(DPM_DCEFCLK),
146         FEA_MAP(MEM_VDDCI_SCALING),
147         FEA_MAP(MEM_MVDD_SCALING),
148         FEA_MAP(DS_GFXCLK),
149         FEA_MAP(DS_SOCCLK),
150         FEA_MAP(DS_LCLK),
151         FEA_MAP(DS_DCEFCLK),
152         FEA_MAP(DS_UCLK),
153         FEA_MAP(GFX_ULV),
154         FEA_MAP(FW_DSTATE),
155         FEA_MAP(GFXOFF),
156         FEA_MAP(BACO),
157         FEA_MAP(VCN_PG),
158         FEA_MAP(JPEG_PG),
159         FEA_MAP(USB_PG),
160         FEA_MAP(RSMU_SMN_CG),
161         FEA_MAP(PPT),
162         FEA_MAP(TDC),
163         FEA_MAP(GFX_EDC),
164         FEA_MAP(APCC_PLUS),
165         FEA_MAP(GTHR),
166         FEA_MAP(ACDC),
167         FEA_MAP(VR0HOT),
168         FEA_MAP(VR1HOT),
169         FEA_MAP(FW_CTF),
170         FEA_MAP(FAN_CONTROL),
171         FEA_MAP(THERMAL),
172         FEA_MAP(GFX_DCS),
173         FEA_MAP(RM),
174         FEA_MAP(LED_DISPLAY),
175         FEA_MAP(GFX_SS),
176         FEA_MAP(OUT_OF_BAND_MONITOR),
177         FEA_MAP(TEMP_DEPENDENT_VMIN),
178         FEA_MAP(MMHUB_PG),
179         FEA_MAP(ATHUB_PG),
180 };
181
182 static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = {
183         TAB_MAP(PPTABLE),
184         TAB_MAP(WATERMARKS),
185         TAB_MAP(AVFS),
186         TAB_MAP(AVFS_PSM_DEBUG),
187         TAB_MAP(AVFS_FUSE_OVERRIDE),
188         TAB_MAP(PMSTATUSLOG),
189         TAB_MAP(SMU_METRICS),
190         TAB_MAP(DRIVER_SMU_CONFIG),
191         TAB_MAP(ACTIVITY_MONITOR_COEFF),
192         TAB_MAP(OVERDRIVE),
193         TAB_MAP(I2C_COMMANDS),
194         TAB_MAP(PACE),
195 };
196
197 static struct smu_11_0_cmn2aisc_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
198         PWR_MAP(AC),
199         PWR_MAP(DC),
200 };
201
202 static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
203         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_PPLIB_DEFAULT_BIT),
204         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
205         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
206         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
207         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
208         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
209         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
210 };
211
212 static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
213 {
214         struct smu_11_0_cmn2aisc_mapping mapping;
215
216         if (index >= SMU_MSG_MAX_COUNT)
217                 return -EINVAL;
218
219         mapping = navi10_message_map[index];
220         if (!(mapping.valid_mapping)) {
221                 return -EINVAL;
222         }
223
224         return mapping.map_to;
225 }
226
227 static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
228 {
229         struct smu_11_0_cmn2aisc_mapping mapping;
230
231         if (index >= SMU_CLK_COUNT)
232                 return -EINVAL;
233
234         mapping = navi10_clk_map[index];
235         if (!(mapping.valid_mapping)) {
236                 return -EINVAL;
237         }
238
239         return mapping.map_to;
240 }
241
242 static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
243 {
244         struct smu_11_0_cmn2aisc_mapping mapping;
245
246         if (index >= SMU_FEATURE_COUNT)
247                 return -EINVAL;
248
249         mapping = navi10_feature_mask_map[index];
250         if (!(mapping.valid_mapping)) {
251                 return -EINVAL;
252         }
253
254         return mapping.map_to;
255 }
256
257 static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
258 {
259         struct smu_11_0_cmn2aisc_mapping mapping;
260
261         if (index >= SMU_TABLE_COUNT)
262                 return -EINVAL;
263
264         mapping = navi10_table_map[index];
265         if (!(mapping.valid_mapping)) {
266                 return -EINVAL;
267         }
268
269         return mapping.map_to;
270 }
271
272 static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
273 {
274         struct smu_11_0_cmn2aisc_mapping mapping;
275
276         if (index >= SMU_POWER_SOURCE_COUNT)
277                 return -EINVAL;
278
279         mapping = navi10_pwr_src_map[index];
280         if (!(mapping.valid_mapping)) {
281                 return -EINVAL;
282         }
283
284         return mapping.map_to;
285 }
286
287
288 static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
289 {
290         struct smu_11_0_cmn2aisc_mapping mapping;
291
292         if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
293                 return -EINVAL;
294
295         mapping = navi10_workload_map[profile];
296         if (!(mapping.valid_mapping)) {
297                 return -EINVAL;
298         }
299
300         return mapping.map_to;
301 }
302
303 static bool is_asic_secure(struct smu_context *smu)
304 {
305         struct amdgpu_device *adev = smu->adev;
306         bool is_secure = true;
307         uint32_t mp0_fw_intf;
308
309         mp0_fw_intf = RREG32_PCIE(MP0_Public |
310                                    (smnMP0_FW_INTF & 0xffffffff));
311
312         if (!(mp0_fw_intf & (1 << 19)))
313                 is_secure = false;
314
315         return is_secure;
316 }
317
318 static int
319 navi10_get_allowed_feature_mask(struct smu_context *smu,
320                                   uint32_t *feature_mask, uint32_t num)
321 {
322         struct amdgpu_device *adev = smu->adev;
323
324         if (num > 2)
325                 return -EINVAL;
326
327         memset(feature_mask, 0, sizeof(uint32_t) * num);
328
329         *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
330                                 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
331                                 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
332                                 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
333                                 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
334                                 | FEATURE_MASK(FEATURE_GFX_ULV_BIT)
335                                 | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
336                                 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
337                                 | FEATURE_MASK(FEATURE_PPT_BIT)
338                                 | FEATURE_MASK(FEATURE_TDC_BIT)
339                                 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
340                                 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
341                                 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
342                                 | FEATURE_MASK(FEATURE_THERMAL_BIT)
343                                 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
344                                 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
345                                 | FEATURE_MASK(FEATURE_DS_GFXCLK_BIT)
346                                 | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
347                                 | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
348                                 | FEATURE_MASK(FEATURE_BACO_BIT)
349                                 | FEATURE_MASK(FEATURE_ACDC_BIT)
350                                 | FEATURE_MASK(FEATURE_GFX_SS_BIT)
351                                 | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
352                                 | FEATURE_MASK(FEATURE_FW_CTF_BIT);
353
354         if (adev->pm.pp_feature & PP_MCLK_DPM_MASK)
355                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
356                                 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
357                                 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
358
359         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
360                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
361                 /* TODO: remove it once fw fix the bug */
362                 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
363         }
364
365         if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
366                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
367
368         if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
369                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
370
371         if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
372                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT)
373                                 | FEATURE_MASK(FEATURE_JPEG_PG_BIT);
374
375         /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */
376         if (is_asic_secure(smu)) {
377                 /* only for navi10 A0 */
378                 if ((adev->asic_type == CHIP_NAVI10) &&
379                         (adev->rev_id == 0)) {
380                         *(uint64_t *)feature_mask &=
381                                         ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
382                                           | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
383                                           | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT));
384                         *(uint64_t *)feature_mask &=
385                                         ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
386                 }
387         }
388
389         return 0;
390 }
391
392 static int navi10_check_powerplay_table(struct smu_context *smu)
393 {
394         return 0;
395 }
396
397 static int navi10_append_powerplay_table(struct smu_context *smu)
398 {
399         struct amdgpu_device *adev = smu->adev;
400         struct smu_table_context *table_context = &smu->smu_table;
401         PPTable_t *smc_pptable = table_context->driver_pptable;
402         struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
403         int index, ret;
404
405         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
406                                            smc_dpm_info);
407
408         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
409                                       (uint8_t **)&smc_dpm_table);
410         if (ret)
411                 return ret;
412
413         memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers,
414                sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS);
415
416         /* SVI2 Board Parameters */
417         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->MaxVoltageStepGfx;
418         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->MaxVoltageStepSoc;
419         smc_pptable->VddGfxVrMapping = smc_dpm_table->VddGfxVrMapping;
420         smc_pptable->VddSocVrMapping = smc_dpm_table->VddSocVrMapping;
421         smc_pptable->VddMem0VrMapping = smc_dpm_table->VddMem0VrMapping;
422         smc_pptable->VddMem1VrMapping = smc_dpm_table->VddMem1VrMapping;
423         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->GfxUlvPhaseSheddingMask;
424         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->SocUlvPhaseSheddingMask;
425         smc_pptable->ExternalSensorPresent = smc_dpm_table->ExternalSensorPresent;
426         smc_pptable->Padding8_V = smc_dpm_table->Padding8_V;
427
428         /* Telemetry Settings */
429         smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent;
430         smc_pptable->GfxOffset = smc_dpm_table->GfxOffset;
431         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->Padding_TelemetryGfx;
432         smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent;
433         smc_pptable->SocOffset = smc_dpm_table->SocOffset;
434         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->Padding_TelemetrySoc;
435         smc_pptable->Mem0MaxCurrent = smc_dpm_table->Mem0MaxCurrent;
436         smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset;
437         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->Padding_TelemetryMem0;
438         smc_pptable->Mem1MaxCurrent = smc_dpm_table->Mem1MaxCurrent;
439         smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset;
440         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->Padding_TelemetryMem1;
441
442         /* GPIO Settings */
443         smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio;
444         smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity;
445         smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio;
446         smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity;
447         smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio;
448         smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity;
449         smc_pptable->GthrGpio = smc_dpm_table->GthrGpio;
450         smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity;
451
452         /* LED Display Settings */
453         smc_pptable->LedPin0 = smc_dpm_table->LedPin0;
454         smc_pptable->LedPin1 = smc_dpm_table->LedPin1;
455         smc_pptable->LedPin2 = smc_dpm_table->LedPin2;
456         smc_pptable->padding8_4 = smc_dpm_table->padding8_4;
457
458         /* GFXCLK PLL Spread Spectrum */
459         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->PllGfxclkSpreadEnabled;
460         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->PllGfxclkSpreadPercent;
461         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->PllGfxclkSpreadFreq;
462
463         /* GFXCLK DFLL Spread Spectrum */
464         smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table->DfllGfxclkSpreadEnabled;
465         smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table->DfllGfxclkSpreadPercent;
466         smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table->DfllGfxclkSpreadFreq;
467
468         /* UCLK Spread Spectrum */
469         smc_pptable->UclkSpreadEnabled = smc_dpm_table->UclkSpreadEnabled;
470         smc_pptable->UclkSpreadPercent = smc_dpm_table->UclkSpreadPercent;
471         smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq;
472
473         /* SOCCLK Spread Spectrum */
474         smc_pptable->SoclkSpreadEnabled = smc_dpm_table->SoclkSpreadEnabled;
475         smc_pptable->SocclkSpreadPercent = smc_dpm_table->SocclkSpreadPercent;
476         smc_pptable->SocclkSpreadFreq = smc_dpm_table->SocclkSpreadFreq;
477
478         /* Total board power */
479         smc_pptable->TotalBoardPower = smc_dpm_table->TotalBoardPower;
480         smc_pptable->BoardPadding = smc_dpm_table->BoardPadding;
481
482         /* Mvdd Svi2 Div Ratio Setting */
483         smc_pptable->MvddRatio = smc_dpm_table->MvddRatio;
484
485         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
486                 /* TODO: remove it once SMU fw fix it */
487                 smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
488         }
489
490         return 0;
491 }
492
493 static int navi10_store_powerplay_table(struct smu_context *smu)
494 {
495         struct smu_11_0_powerplay_table *powerplay_table = NULL;
496         struct smu_table_context *table_context = &smu->smu_table;
497         struct smu_baco_context *smu_baco = &smu->smu_baco;
498
499         if (!table_context->power_play_table)
500                 return -EINVAL;
501
502         powerplay_table = table_context->power_play_table;
503
504         memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
505                sizeof(PPTable_t));
506
507         table_context->thermal_controller_type = powerplay_table->thermal_controller_type;
508
509         mutex_lock(&smu_baco->mutex);
510         if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
511             powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO)
512                 smu_baco->platform_support = true;
513         mutex_unlock(&smu_baco->mutex);
514
515         return 0;
516 }
517
518 static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
519 {
520         struct smu_table_context *smu_table = &smu->smu_table;
521
522         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
523                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
524         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
525                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
526         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
527                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
528         SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
529                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
530         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
531                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
532         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
533                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
534                        AMDGPU_GEM_DOMAIN_VRAM);
535
536         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
537         if (!smu_table->metrics_table)
538                 return -ENOMEM;
539         smu_table->metrics_time = 0;
540
541         return 0;
542 }
543
544 static int navi10_get_metrics_table(struct smu_context *smu,
545                                     SmuMetrics_t *metrics_table)
546 {
547         struct smu_table_context *smu_table= &smu->smu_table;
548         int ret = 0;
549
550         mutex_lock(&smu->metrics_lock);
551         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) {
552                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
553                                 (void *)smu_table->metrics_table, false);
554                 if (ret) {
555                         pr_info("Failed to export SMU metrics table!\n");
556                         mutex_unlock(&smu->metrics_lock);
557                         return ret;
558                 }
559                 smu_table->metrics_time = jiffies;
560         }
561
562         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
563         mutex_unlock(&smu->metrics_lock);
564
565         return ret;
566 }
567
568 static int navi10_allocate_dpm_context(struct smu_context *smu)
569 {
570         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
571
572         if (smu_dpm->dpm_context)
573                 return -EINVAL;
574
575         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
576                                        GFP_KERNEL);
577         if (!smu_dpm->dpm_context)
578                 return -ENOMEM;
579
580         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
581
582         return 0;
583 }
584
585 static int navi10_set_default_dpm_table(struct smu_context *smu)
586 {
587         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
588         struct smu_table_context *table_context = &smu->smu_table;
589         struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
590         PPTable_t *driver_ppt = NULL;
591
592         driver_ppt = table_context->driver_pptable;
593
594         dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0];
595         dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1];
596
597         dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0];
598         dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1];
599
600         dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0];
601         dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1];
602
603         dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0];
604         dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1];
605
606         dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0];
607         dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1];
608
609         dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0];
610         dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1];
611
612         dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0];
613         dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1];
614
615         dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0];
616         dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1];
617
618         dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0];
619         dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1];
620
621         return 0;
622 }
623
624 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
625 {
626         struct smu_power_context *smu_power = &smu->smu_power;
627         struct smu_power_gate *power_gate = &smu_power->power_gate;
628         int ret = 0;
629
630         if (enable) {
631                 /* vcn dpm on is a prerequisite for vcn power gate messages */
632                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
633                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
634                         if (ret)
635                                 return ret;
636                 }
637                 power_gate->vcn_gated = false;
638         } else {
639                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
640                         ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
641                         if (ret)
642                                 return ret;
643                 }
644                 power_gate->vcn_gated = true;
645         }
646
647         return ret;
648 }
649
650 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
651                                        enum smu_clk_type clk_type,
652                                        uint32_t *value)
653 {
654         int ret = 0, clk_id = 0;
655         SmuMetrics_t metrics;
656
657         ret = navi10_get_metrics_table(smu, &metrics);
658         if (ret)
659                 return ret;
660
661         clk_id = smu_clk_get_index(smu, clk_type);
662         if (clk_id < 0)
663                 return clk_id;
664
665         *value = metrics.CurrClock[clk_id];
666
667         return ret;
668 }
669
670 static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
671 {
672         PPTable_t *pptable = smu->smu_table.driver_pptable;
673         DpmDescriptor_t *dpm_desc = NULL;
674         uint32_t clk_index = 0;
675
676         clk_index = smu_clk_get_index(smu, clk_type);
677         dpm_desc = &pptable->DpmDescriptor[clk_index];
678
679         /* 0 - Fine grained DPM, 1 - Discrete DPM */
680         return dpm_desc->SnapToDiscrete == 0 ? true : false;
681 }
682
683 static int navi10_print_clk_levels(struct smu_context *smu,
684                         enum smu_clk_type clk_type, char *buf)
685 {
686         int i, size = 0, ret = 0;
687         uint32_t cur_value = 0, value = 0, count = 0;
688         uint32_t freq_values[3] = {0};
689         uint32_t mark_index = 0;
690
691         switch (clk_type) {
692         case SMU_GFXCLK:
693         case SMU_SCLK:
694         case SMU_SOCCLK:
695         case SMU_MCLK:
696         case SMU_UCLK:
697         case SMU_FCLK:
698         case SMU_DCEFCLK:
699                 ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
700                 if (ret)
701                         return size;
702
703                 /* 10KHz -> MHz */
704                 cur_value = cur_value / 100;
705
706                 ret = smu_get_dpm_level_count(smu, clk_type, &count);
707                 if (ret)
708                         return size;
709
710                 if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
711                         for (i = 0; i < count; i++) {
712                                 ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
713                                 if (ret)
714                                         return size;
715
716                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
717                                                 cur_value == value ? "*" : "");
718                         }
719                 } else {
720                         ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
721                         if (ret)
722                                 return size;
723                         ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
724                         if (ret)
725                                 return size;
726
727                         freq_values[1] = cur_value;
728                         mark_index = cur_value == freq_values[0] ? 0 :
729                                      cur_value == freq_values[2] ? 2 : 1;
730                         if (mark_index != 1)
731                                 freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
732
733                         for (i = 0; i < 3; i++) {
734                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
735                                                 i == mark_index ? "*" : "");
736                         }
737
738                 }
739                 break;
740         default:
741                 break;
742         }
743
744         return size;
745 }
746
747 static int navi10_force_clk_levels(struct smu_context *smu,
748                                    enum smu_clk_type clk_type, uint32_t mask)
749 {
750
751         int ret = 0, size = 0;
752         uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
753
754         soft_min_level = mask ? (ffs(mask) - 1) : 0;
755         soft_max_level = mask ? (fls(mask) - 1) : 0;
756
757         switch (clk_type) {
758         case SMU_GFXCLK:
759         case SMU_SCLK:
760         case SMU_SOCCLK:
761         case SMU_MCLK:
762         case SMU_UCLK:
763         case SMU_DCEFCLK:
764         case SMU_FCLK:
765                 /* There is only 2 levels for fine grained DPM */
766                 if (navi10_is_support_fine_grained_dpm(smu, clk_type)) {
767                         soft_max_level = (soft_max_level >= 1 ? 1 : 0);
768                         soft_min_level = (soft_min_level >= 1 ? 1 : 0);
769                 }
770
771                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
772                 if (ret)
773                         return size;
774
775                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
776                 if (ret)
777                         return size;
778
779                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
780                 if (ret)
781                         return size;
782                 break;
783         default:
784                 break;
785         }
786
787         return size;
788 }
789
790 static int navi10_populate_umd_state_clk(struct smu_context *smu)
791 {
792         int ret = 0;
793         uint32_t min_sclk_freq = 0, min_mclk_freq = 0;
794
795         ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL);
796         if (ret)
797                 return ret;
798
799         smu->pstate_sclk = min_sclk_freq * 100;
800
801         ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL);
802         if (ret)
803                 return ret;
804
805         smu->pstate_mclk = min_mclk_freq * 100;
806
807         return ret;
808 }
809
810 static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
811                                                  enum smu_clk_type clk_type,
812                                                  struct pp_clock_levels_with_latency *clocks)
813 {
814         int ret = 0, i = 0;
815         uint32_t level_count = 0, freq = 0;
816
817         switch (clk_type) {
818         case SMU_GFXCLK:
819         case SMU_DCEFCLK:
820         case SMU_SOCCLK:
821                 ret = smu_get_dpm_level_count(smu, clk_type, &level_count);
822                 if (ret)
823                         return ret;
824
825                 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
826                 clocks->num_levels = level_count;
827
828                 for (i = 0; i < level_count; i++) {
829                         ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq);
830                         if (ret)
831                                 return ret;
832
833                         clocks->data[i].clocks_in_khz = freq * 1000;
834                         clocks->data[i].latency_in_us = 0;
835                 }
836                 break;
837         default:
838                 break;
839         }
840
841         return ret;
842 }
843
844 static int navi10_pre_display_config_changed(struct smu_context *smu)
845 {
846         int ret = 0;
847         uint32_t max_freq = 0;
848
849         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
850         if (ret)
851                 return ret;
852
853         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
854                 ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq);
855                 if (ret)
856                         return ret;
857                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq);
858                 if (ret)
859                         return ret;
860         }
861
862         return ret;
863 }
864
865 static int navi10_display_config_changed(struct smu_context *smu)
866 {
867         int ret = 0;
868
869         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
870             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
871                 ret = smu_write_watermarks_table(smu);
872                 if (ret)
873                         return ret;
874
875                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
876         }
877
878         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
879             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
880             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
881                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
882                                                   smu->display_config->num_display);
883                 if (ret)
884                         return ret;
885         }
886
887         return ret;
888 }
889
890 static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest)
891 {
892         int ret = 0, i = 0;
893         uint32_t min_freq, max_freq, force_freq;
894         enum smu_clk_type clk_type;
895
896         enum smu_clk_type clks[] = {
897                 SMU_GFXCLK,
898                 SMU_MCLK,
899                 SMU_SOCCLK,
900         };
901
902         for (i = 0; i < ARRAY_SIZE(clks); i++) {
903                 clk_type = clks[i];
904                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
905                 if (ret)
906                         return ret;
907
908                 force_freq = highest ? max_freq : min_freq;
909                 ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
910                 if (ret)
911                         return ret;
912         }
913
914         return ret;
915 }
916
917 static int navi10_unforce_dpm_levels(struct smu_context *smu)
918 {
919         int ret = 0, i = 0;
920         uint32_t min_freq, max_freq;
921         enum smu_clk_type clk_type;
922
923         enum smu_clk_type clks[] = {
924                 SMU_GFXCLK,
925                 SMU_MCLK,
926                 SMU_SOCCLK,
927         };
928
929         for (i = 0; i < ARRAY_SIZE(clks); i++) {
930                 clk_type = clks[i];
931                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
932                 if (ret)
933                         return ret;
934
935                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
936                 if (ret)
937                         return ret;
938         }
939
940         return ret;
941 }
942
943 static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
944 {
945         int ret = 0;
946         SmuMetrics_t metrics;
947
948         if (!value)
949                 return -EINVAL;
950
951         ret = navi10_get_metrics_table(smu, &metrics);
952         if (ret)
953                 return ret;
954
955         *value = metrics.AverageSocketPower << 8;
956
957         return 0;
958 }
959
960 static int navi10_get_current_activity_percent(struct smu_context *smu,
961                                                enum amd_pp_sensors sensor,
962                                                uint32_t *value)
963 {
964         int ret = 0;
965         SmuMetrics_t metrics;
966
967         if (!value)
968                 return -EINVAL;
969
970         ret = navi10_get_metrics_table(smu, &metrics);
971         if (ret)
972                 return ret;
973
974         switch (sensor) {
975         case AMDGPU_PP_SENSOR_GPU_LOAD:
976                 *value = metrics.AverageGfxActivity;
977                 break;
978         case AMDGPU_PP_SENSOR_MEM_LOAD:
979                 *value = metrics.AverageUclkActivity;
980                 break;
981         default:
982                 pr_err("Invalid sensor for retrieving clock activity\n");
983                 return -EINVAL;
984         }
985
986         return 0;
987 }
988
989 static bool navi10_is_dpm_running(struct smu_context *smu)
990 {
991         int ret = 0;
992         uint32_t feature_mask[2];
993         unsigned long feature_enabled;
994         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
995         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
996                            ((uint64_t)feature_mask[1] << 32));
997         return !!(feature_enabled & SMC_DPM_FEATURE);
998 }
999
1000 static int navi10_get_fan_speed_rpm(struct smu_context *smu,
1001                                     uint32_t *speed)
1002 {
1003         SmuMetrics_t metrics;
1004         int ret = 0;
1005
1006         if (!speed)
1007                 return -EINVAL;
1008
1009         ret = navi10_get_metrics_table(smu, &metrics);
1010         if (ret)
1011                 return ret;
1012
1013         *speed = metrics.CurrFanSpeed;
1014
1015         return ret;
1016 }
1017
1018 static int navi10_get_fan_speed_percent(struct smu_context *smu,
1019                                         uint32_t *speed)
1020 {
1021         int ret = 0;
1022         uint32_t percent = 0;
1023         uint32_t current_rpm;
1024         PPTable_t *pptable = smu->smu_table.driver_pptable;
1025
1026         ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
1027         if (ret)
1028                 return ret;
1029
1030         percent = current_rpm * 100 / pptable->FanMaximumRpm;
1031         *speed = percent > 100 ? 100 : percent;
1032
1033         return ret;
1034 }
1035
1036 static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1037 {
1038         DpmActivityMonitorCoeffInt_t activity_monitor;
1039         uint32_t i, size = 0;
1040         int16_t workload_type = 0;
1041         static const char *profile_name[] = {
1042                                         "BOOTUP_DEFAULT",
1043                                         "3D_FULL_SCREEN",
1044                                         "POWER_SAVING",
1045                                         "VIDEO",
1046                                         "VR",
1047                                         "COMPUTE",
1048                                         "CUSTOM"};
1049         static const char *title[] = {
1050                         "PROFILE_INDEX(NAME)",
1051                         "CLOCK_TYPE(NAME)",
1052                         "FPS",
1053                         "MinFreqType",
1054                         "MinActiveFreqType",
1055                         "MinActiveFreq",
1056                         "BoosterFreqType",
1057                         "BoosterFreq",
1058                         "PD_Data_limit_c",
1059                         "PD_Data_error_coeff",
1060                         "PD_Data_error_rate_coeff"};
1061         int result = 0;
1062
1063         if (!buf)
1064                 return -EINVAL;
1065
1066         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1067                         title[0], title[1], title[2], title[3], title[4], title[5],
1068                         title[6], title[7], title[8], title[9], title[10]);
1069
1070         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1071                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1072                 workload_type = smu_workload_get_type(smu, i);
1073                 if (workload_type < 0)
1074                         return -EINVAL;
1075
1076                 result = smu_update_table(smu,
1077                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1078                                           (void *)(&activity_monitor), false);
1079                 if (result) {
1080                         pr_err("[%s] Failed to get activity monitor!", __func__);
1081                         return result;
1082                 }
1083
1084                 size += sprintf(buf + size, "%2d %14s%s:\n",
1085                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1086
1087                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1088                         " ",
1089                         0,
1090                         "GFXCLK",
1091                         activity_monitor.Gfx_FPS,
1092                         activity_monitor.Gfx_MinFreqStep,
1093                         activity_monitor.Gfx_MinActiveFreqType,
1094                         activity_monitor.Gfx_MinActiveFreq,
1095                         activity_monitor.Gfx_BoosterFreqType,
1096                         activity_monitor.Gfx_BoosterFreq,
1097                         activity_monitor.Gfx_PD_Data_limit_c,
1098                         activity_monitor.Gfx_PD_Data_error_coeff,
1099                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
1100
1101                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1102                         " ",
1103                         1,
1104                         "SOCCLK",
1105                         activity_monitor.Soc_FPS,
1106                         activity_monitor.Soc_MinFreqStep,
1107                         activity_monitor.Soc_MinActiveFreqType,
1108                         activity_monitor.Soc_MinActiveFreq,
1109                         activity_monitor.Soc_BoosterFreqType,
1110                         activity_monitor.Soc_BoosterFreq,
1111                         activity_monitor.Soc_PD_Data_limit_c,
1112                         activity_monitor.Soc_PD_Data_error_coeff,
1113                         activity_monitor.Soc_PD_Data_error_rate_coeff);
1114
1115                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1116                         " ",
1117                         2,
1118                         "MEMLK",
1119                         activity_monitor.Mem_FPS,
1120                         activity_monitor.Mem_MinFreqStep,
1121                         activity_monitor.Mem_MinActiveFreqType,
1122                         activity_monitor.Mem_MinActiveFreq,
1123                         activity_monitor.Mem_BoosterFreqType,
1124                         activity_monitor.Mem_BoosterFreq,
1125                         activity_monitor.Mem_PD_Data_limit_c,
1126                         activity_monitor.Mem_PD_Data_error_coeff,
1127                         activity_monitor.Mem_PD_Data_error_rate_coeff);
1128         }
1129
1130         return size;
1131 }
1132
1133 static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1134 {
1135         DpmActivityMonitorCoeffInt_t activity_monitor;
1136         int workload_type, ret = 0;
1137
1138         smu->power_profile_mode = input[size];
1139
1140         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1141                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1142                 return -EINVAL;
1143         }
1144
1145         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1146                 if (size < 0)
1147                         return -EINVAL;
1148
1149                 ret = smu_update_table(smu,
1150                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1151                                        (void *)(&activity_monitor), false);
1152                 if (ret) {
1153                         pr_err("[%s] Failed to get activity monitor!", __func__);
1154                         return ret;
1155                 }
1156
1157                 switch (input[0]) {
1158                 case 0: /* Gfxclk */
1159                         activity_monitor.Gfx_FPS = input[1];
1160                         activity_monitor.Gfx_MinFreqStep = input[2];
1161                         activity_monitor.Gfx_MinActiveFreqType = input[3];
1162                         activity_monitor.Gfx_MinActiveFreq = input[4];
1163                         activity_monitor.Gfx_BoosterFreqType = input[5];
1164                         activity_monitor.Gfx_BoosterFreq = input[6];
1165                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
1166                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1167                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1168                         break;
1169                 case 1: /* Socclk */
1170                         activity_monitor.Soc_FPS = input[1];
1171                         activity_monitor.Soc_MinFreqStep = input[2];
1172                         activity_monitor.Soc_MinActiveFreqType = input[3];
1173                         activity_monitor.Soc_MinActiveFreq = input[4];
1174                         activity_monitor.Soc_BoosterFreqType = input[5];
1175                         activity_monitor.Soc_BoosterFreq = input[6];
1176                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1177                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1178                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1179                         break;
1180                 case 2: /* Memlk */
1181                         activity_monitor.Mem_FPS = input[1];
1182                         activity_monitor.Mem_MinFreqStep = input[2];
1183                         activity_monitor.Mem_MinActiveFreqType = input[3];
1184                         activity_monitor.Mem_MinActiveFreq = input[4];
1185                         activity_monitor.Mem_BoosterFreqType = input[5];
1186                         activity_monitor.Mem_BoosterFreq = input[6];
1187                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1188                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1189                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1190                         break;
1191                 }
1192
1193                 ret = smu_update_table(smu,
1194                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1195                                        (void *)(&activity_monitor), true);
1196                 if (ret) {
1197                         pr_err("[%s] Failed to set activity monitor!", __func__);
1198                         return ret;
1199                 }
1200         }
1201
1202         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1203         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1204         if (workload_type < 0)
1205                 return -EINVAL;
1206         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1207                                     1 << workload_type);
1208
1209         return ret;
1210 }
1211
1212 static int navi10_get_profiling_clk_mask(struct smu_context *smu,
1213                                          enum amd_dpm_forced_level level,
1214                                          uint32_t *sclk_mask,
1215                                          uint32_t *mclk_mask,
1216                                          uint32_t *soc_mask)
1217 {
1218         int ret = 0;
1219         uint32_t level_count = 0;
1220
1221         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1222                 if (sclk_mask)
1223                         *sclk_mask = 0;
1224         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1225                 if (mclk_mask)
1226                         *mclk_mask = 0;
1227         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1228                 if(sclk_mask) {
1229                         ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count);
1230                         if (ret)
1231                                 return ret;
1232                         *sclk_mask = level_count - 1;
1233                 }
1234
1235                 if(mclk_mask) {
1236                         ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count);
1237                         if (ret)
1238                                 return ret;
1239                         *mclk_mask = level_count - 1;
1240                 }
1241
1242                 if(soc_mask) {
1243                         ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count);
1244                         if (ret)
1245                                 return ret;
1246                         *soc_mask = level_count - 1;
1247                 }
1248         }
1249
1250         return ret;
1251 }
1252
1253 static int navi10_notify_smc_dispaly_config(struct smu_context *smu)
1254 {
1255         struct smu_clocks min_clocks = {0};
1256         struct pp_display_clock_request clock_req;
1257         int ret = 0;
1258
1259         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1260         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1261         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1262
1263         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1264                 clock_req.clock_type = amd_pp_dcef_clock;
1265                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1266                 if (!smu_display_clock_voltage_request(smu, &clock_req)) {
1267                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1268                                 ret = smu_send_smc_msg_with_param(smu,
1269                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
1270                                                                   min_clocks.dcef_clock_in_sr/100);
1271                                 if (ret) {
1272                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
1273                                         return ret;
1274                                 }
1275                         }
1276                 } else {
1277                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1278                 }
1279         }
1280
1281         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1282                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
1283                 if (ret) {
1284                         pr_err("[%s] Set hard min uclk failed!", __func__);
1285                         return ret;
1286                 }
1287         }
1288
1289         return 0;
1290 }
1291
1292 static int navi10_set_watermarks_table(struct smu_context *smu,
1293                                        void *watermarks, struct
1294                                        dm_pp_wm_sets_with_clock_ranges_soc15
1295                                        *clock_ranges)
1296 {
1297         int i;
1298         Watermarks_t *table = watermarks;
1299
1300         if (!table || !clock_ranges)
1301                 return -EINVAL;
1302
1303         if (clock_ranges->num_wm_dmif_sets > 4 ||
1304             clock_ranges->num_wm_mcif_sets > 4)
1305                 return -EINVAL;
1306
1307         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
1308                 table->WatermarkRow[1][i].MinClock =
1309                         cpu_to_le16((uint16_t)
1310                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1311                         1000));
1312                 table->WatermarkRow[1][i].MaxClock =
1313                         cpu_to_le16((uint16_t)
1314                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1315                         1000));
1316                 table->WatermarkRow[1][i].MinUclk =
1317                         cpu_to_le16((uint16_t)
1318                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1319                         1000));
1320                 table->WatermarkRow[1][i].MaxUclk =
1321                         cpu_to_le16((uint16_t)
1322                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1323                         1000));
1324                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
1325                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
1326         }
1327
1328         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
1329                 table->WatermarkRow[0][i].MinClock =
1330                         cpu_to_le16((uint16_t)
1331                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1332                         1000));
1333                 table->WatermarkRow[0][i].MaxClock =
1334                         cpu_to_le16((uint16_t)
1335                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1336                         1000));
1337                 table->WatermarkRow[0][i].MinUclk =
1338                         cpu_to_le16((uint16_t)
1339                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1340                         1000));
1341                 table->WatermarkRow[0][i].MaxUclk =
1342                         cpu_to_le16((uint16_t)
1343                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1344                         1000));
1345                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
1346                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
1347         }
1348
1349         return 0;
1350 }
1351
1352 static int navi10_thermal_get_temperature(struct smu_context *smu,
1353                                              enum amd_pp_sensors sensor,
1354                                              uint32_t *value)
1355 {
1356         SmuMetrics_t metrics;
1357         int ret = 0;
1358
1359         if (!value)
1360                 return -EINVAL;
1361
1362         ret = navi10_get_metrics_table(smu, &metrics);
1363         if (ret)
1364                 return ret;
1365
1366         switch (sensor) {
1367         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1368                 *value = metrics.TemperatureHotspot *
1369                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1370                 break;
1371         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1372                 *value = metrics.TemperatureEdge *
1373                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1374                 break;
1375         case AMDGPU_PP_SENSOR_MEM_TEMP:
1376                 *value = metrics.TemperatureMem *
1377                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1378                 break;
1379         default:
1380                 pr_err("Invalid sensor for retrieving temp\n");
1381                 return -EINVAL;
1382         }
1383
1384         return 0;
1385 }
1386
1387 static int navi10_read_sensor(struct smu_context *smu,
1388                                  enum amd_pp_sensors sensor,
1389                                  void *data, uint32_t *size)
1390 {
1391         int ret = 0;
1392         struct smu_table_context *table_context = &smu->smu_table;
1393         PPTable_t *pptable = table_context->driver_pptable;
1394
1395         if(!data || !size)
1396                 return -EINVAL;
1397
1398         mutex_lock(&smu->sensor_lock);
1399         switch (sensor) {
1400         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1401                 *(uint32_t *)data = pptable->FanMaximumRpm;
1402                 *size = 4;
1403                 break;
1404         case AMDGPU_PP_SENSOR_MEM_LOAD:
1405         case AMDGPU_PP_SENSOR_GPU_LOAD:
1406                 ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
1407                 *size = 4;
1408                 break;
1409         case AMDGPU_PP_SENSOR_GPU_POWER:
1410                 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1411                 *size = 4;
1412                 break;
1413         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1414         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1415         case AMDGPU_PP_SENSOR_MEM_TEMP:
1416                 ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
1417                 *size = 4;
1418                 break;
1419         default:
1420                 ret = smu_smc_read_sensor(smu, sensor, data, size);
1421         }
1422         mutex_unlock(&smu->sensor_lock);
1423
1424         return ret;
1425 }
1426
1427 static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
1428 {
1429         uint32_t num_discrete_levels = 0;
1430         uint16_t *dpm_levels = NULL;
1431         uint16_t i = 0;
1432         struct smu_table_context *table_context = &smu->smu_table;
1433         PPTable_t *driver_ppt = NULL;
1434
1435         if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
1436                 return -EINVAL;
1437
1438         driver_ppt = table_context->driver_pptable;
1439         num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
1440         dpm_levels = driver_ppt->FreqTableUclk;
1441
1442         if (num_discrete_levels == 0 || dpm_levels == NULL)
1443                 return -EINVAL;
1444
1445         *num_states = num_discrete_levels;
1446         for (i = 0; i < num_discrete_levels; i++) {
1447                 /* convert to khz */
1448                 *clocks_in_khz = (*dpm_levels) * 1000;
1449                 clocks_in_khz++;
1450                 dpm_levels++;
1451         }
1452
1453         return 0;
1454 }
1455
1456 static int navi10_set_peak_clock_by_device(struct smu_context *smu)
1457 {
1458         struct amdgpu_device *adev = smu->adev;
1459         int ret = 0;
1460         uint32_t sclk_freq = 0, uclk_freq = 0;
1461         uint32_t uclk_level = 0;
1462
1463         switch (adev->pdev->revision) {
1464         case 0xf0: /* XTX */
1465         case 0xc0:
1466                 sclk_freq = NAVI10_PEAK_SCLK_XTX;
1467                 break;
1468         case 0xf1: /* XT */
1469         case 0xc1:
1470                 sclk_freq = NAVI10_PEAK_SCLK_XT;
1471                 break;
1472         default: /* XL */
1473                 sclk_freq = NAVI10_PEAK_SCLK_XL;
1474                 break;
1475         }
1476
1477         ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
1478         if (ret)
1479                 return ret;
1480         ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
1481         if (ret)
1482                 return ret;
1483
1484         ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
1485         if (ret)
1486                 return ret;
1487         ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
1488         if (ret)
1489                 return ret;
1490
1491         return ret;
1492 }
1493
1494 static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1495 {
1496         int ret = 0;
1497         struct amdgpu_device *adev = smu->adev;
1498
1499         if (adev->asic_type != CHIP_NAVI10)
1500                 return -EINVAL;
1501
1502         switch (level) {
1503         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1504                 ret = navi10_set_peak_clock_by_device(smu);
1505                 break;
1506         default:
1507                 ret = -EINVAL;
1508                 break;
1509         }
1510
1511         return ret;
1512 }
1513
1514 static int navi10_get_thermal_temperature_range(struct smu_context *smu,
1515                                                 struct smu_temperature_range *range)
1516 {
1517         struct smu_table_context *table_context = &smu->smu_table;
1518         struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
1519
1520         if (!range || !powerplay_table)
1521                 return -EINVAL;
1522
1523         range->max = powerplay_table->software_shutdown_temp *
1524                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1525
1526         return 0;
1527 }
1528
1529 static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
1530                                                 bool disable_memory_clock_switch)
1531 {
1532         int ret = 0;
1533         struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
1534                 (struct smu_11_0_max_sustainable_clocks *)
1535                         smu->smu_table.max_sustainable_clocks;
1536         uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
1537         uint32_t max_memory_clock = max_sustainable_clocks->uclock;
1538
1539         if(smu->disable_uclk_switch == disable_memory_clock_switch)
1540                 return 0;
1541
1542         if(disable_memory_clock_switch)
1543                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0);
1544         else
1545                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0);
1546
1547         if(!ret)
1548                 smu->disable_uclk_switch = disable_memory_clock_switch;
1549
1550         return ret;
1551 }
1552
1553 static int navi10_get_power_limit(struct smu_context *smu,
1554                                      uint32_t *limit,
1555                                      bool asic_default)
1556 {
1557         PPTable_t *pptable = smu->smu_table.driver_pptable;
1558         uint32_t asic_default_power_limit = 0;
1559         int ret = 0;
1560         int power_src;
1561
1562         if (!smu->default_power_limit ||
1563             !smu->power_limit) {
1564                 if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
1565                         power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
1566                         if (power_src < 0)
1567                                 return -EINVAL;
1568
1569                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
1570                                 power_src << 16);
1571                         if (ret) {
1572                                 pr_err("[%s] get PPT limit failed!", __func__);
1573                                 return ret;
1574                         }
1575                         smu_read_smc_arg(smu, &asic_default_power_limit);
1576                 } else {
1577                         /* the last hope to figure out the ppt limit */
1578                         if (!pptable) {
1579                                 pr_err("Cannot get PPT limit due to pptable missing!");
1580                                 return -EINVAL;
1581                         }
1582                         asic_default_power_limit =
1583                                 pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1584                 }
1585
1586                 if (smu->od_enabled) {
1587                         asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
1588                         asic_default_power_limit /= 100;
1589                 }
1590
1591                 smu->default_power_limit = asic_default_power_limit;
1592                 smu->power_limit = asic_default_power_limit;
1593         }
1594
1595         if (asic_default)
1596                 *limit = smu->default_power_limit;
1597         else
1598                 *limit = smu->power_limit;
1599
1600         return 0;
1601 }
1602
1603 static const struct pptable_funcs navi10_ppt_funcs = {
1604         .tables_init = navi10_tables_init,
1605         .alloc_dpm_context = navi10_allocate_dpm_context,
1606         .store_powerplay_table = navi10_store_powerplay_table,
1607         .check_powerplay_table = navi10_check_powerplay_table,
1608         .append_powerplay_table = navi10_append_powerplay_table,
1609         .get_smu_msg_index = navi10_get_smu_msg_index,
1610         .get_smu_clk_index = navi10_get_smu_clk_index,
1611         .get_smu_feature_index = navi10_get_smu_feature_index,
1612         .get_smu_table_index = navi10_get_smu_table_index,
1613         .get_smu_power_index = navi10_get_pwr_src_index,
1614         .get_workload_type = navi10_get_workload_type,
1615         .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
1616         .set_default_dpm_table = navi10_set_default_dpm_table,
1617         .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable,
1618         .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table,
1619         .print_clk_levels = navi10_print_clk_levels,
1620         .force_clk_levels = navi10_force_clk_levels,
1621         .populate_umd_state_clk = navi10_populate_umd_state_clk,
1622         .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
1623         .pre_display_config_changed = navi10_pre_display_config_changed,
1624         .display_config_changed = navi10_display_config_changed,
1625         .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config,
1626         .force_dpm_limit_value = navi10_force_dpm_limit_value,
1627         .unforce_dpm_levels = navi10_unforce_dpm_levels,
1628         .is_dpm_running = navi10_is_dpm_running,
1629         .get_fan_speed_percent = navi10_get_fan_speed_percent,
1630         .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
1631         .get_power_profile_mode = navi10_get_power_profile_mode,
1632         .set_power_profile_mode = navi10_set_power_profile_mode,
1633         .get_profiling_clk_mask = navi10_get_profiling_clk_mask,
1634         .set_watermarks_table = navi10_set_watermarks_table,
1635         .read_sensor = navi10_read_sensor,
1636         .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
1637         .set_performance_level = navi10_set_performance_level,
1638         .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
1639         .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
1640         .get_power_limit = navi10_get_power_limit,
1641 };
1642
1643 void navi10_set_ppt_funcs(struct smu_context *smu)
1644 {
1645         struct smu_table_context *smu_table = &smu->smu_table;
1646
1647         smu->ppt_funcs = &navi10_ppt_funcs;
1648         smu_table->table_count = TABLE_COUNT;
1649 }