Merge tag 'for-5.4/io_uring-2019-09-27' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.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_CUSTOM_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         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
551                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
552                                 (void *)smu_table->metrics_table, false);
553                 if (ret) {
554                         pr_info("Failed to export SMU metrics table!\n");
555                         return ret;
556                 }
557                 smu_table->metrics_time = jiffies;
558         }
559
560         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
561
562         return ret;
563 }
564
565 static int navi10_allocate_dpm_context(struct smu_context *smu)
566 {
567         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
568
569         if (smu_dpm->dpm_context)
570                 return -EINVAL;
571
572         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
573                                        GFP_KERNEL);
574         if (!smu_dpm->dpm_context)
575                 return -ENOMEM;
576
577         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
578
579         return 0;
580 }
581
582 static int navi10_set_default_dpm_table(struct smu_context *smu)
583 {
584         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
585         struct smu_table_context *table_context = &smu->smu_table;
586         struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
587         PPTable_t *driver_ppt = NULL;
588
589         driver_ppt = table_context->driver_pptable;
590
591         dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0];
592         dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1];
593
594         dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0];
595         dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1];
596
597         dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0];
598         dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1];
599
600         dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0];
601         dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1];
602
603         dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0];
604         dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1];
605
606         dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0];
607         dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1];
608
609         dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0];
610         dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1];
611
612         dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0];
613         dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1];
614
615         dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0];
616         dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1];
617
618         return 0;
619 }
620
621 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
622 {
623         struct smu_power_context *smu_power = &smu->smu_power;
624         struct smu_power_gate *power_gate = &smu_power->power_gate;
625         int ret = 0;
626
627         if (enable) {
628                 /* vcn dpm on is a prerequisite for vcn power gate messages */
629                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
630                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
631                         if (ret)
632                                 return ret;
633                 }
634                 power_gate->vcn_gated = false;
635         } else {
636                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
637                         ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
638                         if (ret)
639                                 return ret;
640                 }
641                 power_gate->vcn_gated = true;
642         }
643
644         return ret;
645 }
646
647 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
648                                        enum smu_clk_type clk_type,
649                                        uint32_t *value)
650 {
651         int ret = 0, clk_id = 0;
652         SmuMetrics_t metrics;
653
654         ret = navi10_get_metrics_table(smu, &metrics);
655         if (ret)
656                 return ret;
657
658         clk_id = smu_clk_get_index(smu, clk_type);
659         if (clk_id < 0)
660                 return clk_id;
661
662         *value = metrics.CurrClock[clk_id];
663
664         return ret;
665 }
666
667 static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
668 {
669         PPTable_t *pptable = smu->smu_table.driver_pptable;
670         DpmDescriptor_t *dpm_desc = NULL;
671         uint32_t clk_index = 0;
672
673         clk_index = smu_clk_get_index(smu, clk_type);
674         dpm_desc = &pptable->DpmDescriptor[clk_index];
675
676         /* 0 - Fine grained DPM, 1 - Discrete DPM */
677         return dpm_desc->SnapToDiscrete == 0 ? true : false;
678 }
679
680 static int navi10_print_clk_levels(struct smu_context *smu,
681                         enum smu_clk_type clk_type, char *buf)
682 {
683         int i, size = 0, ret = 0;
684         uint32_t cur_value = 0, value = 0, count = 0;
685         uint32_t freq_values[3] = {0};
686         uint32_t mark_index = 0;
687
688         switch (clk_type) {
689         case SMU_GFXCLK:
690         case SMU_SCLK:
691         case SMU_SOCCLK:
692         case SMU_MCLK:
693         case SMU_UCLK:
694         case SMU_FCLK:
695         case SMU_DCEFCLK:
696                 ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
697                 if (ret)
698                         return size;
699
700                 /* 10KHz -> MHz */
701                 cur_value = cur_value / 100;
702
703                 ret = smu_get_dpm_level_count(smu, clk_type, &count);
704                 if (ret)
705                         return size;
706
707                 if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
708                         for (i = 0; i < count; i++) {
709                                 ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
710                                 if (ret)
711                                         return size;
712
713                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
714                                                 cur_value == value ? "*" : "");
715                         }
716                 } else {
717                         ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
718                         if (ret)
719                                 return size;
720                         ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
721                         if (ret)
722                                 return size;
723
724                         freq_values[1] = cur_value;
725                         mark_index = cur_value == freq_values[0] ? 0 :
726                                      cur_value == freq_values[2] ? 2 : 1;
727                         if (mark_index != 1)
728                                 freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
729
730                         for (i = 0; i < 3; i++) {
731                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
732                                                 i == mark_index ? "*" : "");
733                         }
734
735                 }
736                 break;
737         default:
738                 break;
739         }
740
741         return size;
742 }
743
744 static int navi10_force_clk_levels(struct smu_context *smu,
745                                    enum smu_clk_type clk_type, uint32_t mask)
746 {
747
748         int ret = 0, size = 0;
749         uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
750
751         soft_min_level = mask ? (ffs(mask) - 1) : 0;
752         soft_max_level = mask ? (fls(mask) - 1) : 0;
753
754         switch (clk_type) {
755         case SMU_GFXCLK:
756         case SMU_SCLK:
757         case SMU_SOCCLK:
758         case SMU_MCLK:
759         case SMU_UCLK:
760         case SMU_DCEFCLK:
761         case SMU_FCLK:
762                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
763                 if (ret)
764                         return size;
765
766                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
767                 if (ret)
768                         return size;
769
770                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
771                 if (ret)
772                         return size;
773                 break;
774         default:
775                 break;
776         }
777
778         return size;
779 }
780
781 static int navi10_populate_umd_state_clk(struct smu_context *smu)
782 {
783         int ret = 0;
784         uint32_t min_sclk_freq = 0, min_mclk_freq = 0;
785
786         ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL);
787         if (ret)
788                 return ret;
789
790         smu->pstate_sclk = min_sclk_freq * 100;
791
792         ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL);
793         if (ret)
794                 return ret;
795
796         smu->pstate_mclk = min_mclk_freq * 100;
797
798         return ret;
799 }
800
801 static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
802                                                  enum smu_clk_type clk_type,
803                                                  struct pp_clock_levels_with_latency *clocks)
804 {
805         int ret = 0, i = 0;
806         uint32_t level_count = 0, freq = 0;
807
808         switch (clk_type) {
809         case SMU_GFXCLK:
810         case SMU_DCEFCLK:
811         case SMU_SOCCLK:
812                 ret = smu_get_dpm_level_count(smu, clk_type, &level_count);
813                 if (ret)
814                         return ret;
815
816                 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
817                 clocks->num_levels = level_count;
818
819                 for (i = 0; i < level_count; i++) {
820                         ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq);
821                         if (ret)
822                                 return ret;
823
824                         clocks->data[i].clocks_in_khz = freq * 1000;
825                         clocks->data[i].latency_in_us = 0;
826                 }
827                 break;
828         default:
829                 break;
830         }
831
832         return ret;
833 }
834
835 static int navi10_pre_display_config_changed(struct smu_context *smu)
836 {
837         int ret = 0;
838         uint32_t max_freq = 0;
839
840         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
841         if (ret)
842                 return ret;
843
844         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
845                 ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq);
846                 if (ret)
847                         return ret;
848                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq);
849                 if (ret)
850                         return ret;
851         }
852
853         return ret;
854 }
855
856 static int navi10_display_config_changed(struct smu_context *smu)
857 {
858         int ret = 0;
859
860         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
861             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
862                 ret = smu_write_watermarks_table(smu);
863                 if (ret)
864                         return ret;
865
866                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
867         }
868
869         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
870             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
871             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
872                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
873                                                   smu->display_config->num_display);
874                 if (ret)
875                         return ret;
876         }
877
878         return ret;
879 }
880
881 static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest)
882 {
883         int ret = 0, i = 0;
884         uint32_t min_freq, max_freq, force_freq;
885         enum smu_clk_type clk_type;
886
887         enum smu_clk_type clks[] = {
888                 SMU_GFXCLK,
889                 SMU_MCLK,
890                 SMU_SOCCLK,
891         };
892
893         for (i = 0; i < ARRAY_SIZE(clks); i++) {
894                 clk_type = clks[i];
895                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
896                 if (ret)
897                         return ret;
898
899                 force_freq = highest ? max_freq : min_freq;
900                 ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
901                 if (ret)
902                         return ret;
903         }
904
905         return ret;
906 }
907
908 static int navi10_unforce_dpm_levels(struct smu_context *smu)
909 {
910         int ret = 0, i = 0;
911         uint32_t min_freq, max_freq;
912         enum smu_clk_type clk_type;
913
914         enum smu_clk_type clks[] = {
915                 SMU_GFXCLK,
916                 SMU_MCLK,
917                 SMU_SOCCLK,
918         };
919
920         for (i = 0; i < ARRAY_SIZE(clks); i++) {
921                 clk_type = clks[i];
922                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
923                 if (ret)
924                         return ret;
925
926                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
927                 if (ret)
928                         return ret;
929         }
930
931         return ret;
932 }
933
934 static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
935 {
936         int ret = 0;
937         SmuMetrics_t metrics;
938
939         if (!value)
940                 return -EINVAL;
941
942         ret = navi10_get_metrics_table(smu, &metrics);
943         if (ret)
944                 return ret;
945
946         *value = metrics.AverageSocketPower << 8;
947
948         return 0;
949 }
950
951 static int navi10_get_current_activity_percent(struct smu_context *smu,
952                                                enum amd_pp_sensors sensor,
953                                                uint32_t *value)
954 {
955         int ret = 0;
956         SmuMetrics_t metrics;
957
958         if (!value)
959                 return -EINVAL;
960
961         ret = navi10_get_metrics_table(smu, &metrics);
962         if (ret)
963                 return ret;
964
965         switch (sensor) {
966         case AMDGPU_PP_SENSOR_GPU_LOAD:
967                 *value = metrics.AverageGfxActivity;
968                 break;
969         case AMDGPU_PP_SENSOR_MEM_LOAD:
970                 *value = metrics.AverageUclkActivity;
971                 break;
972         default:
973                 pr_err("Invalid sensor for retrieving clock activity\n");
974                 return -EINVAL;
975         }
976
977         return 0;
978 }
979
980 static bool navi10_is_dpm_running(struct smu_context *smu)
981 {
982         int ret = 0;
983         uint32_t feature_mask[2];
984         unsigned long feature_enabled;
985         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
986         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
987                            ((uint64_t)feature_mask[1] << 32));
988         return !!(feature_enabled & SMC_DPM_FEATURE);
989 }
990
991 static int navi10_get_fan_speed_rpm(struct smu_context *smu,
992                                     uint32_t *speed)
993 {
994         SmuMetrics_t metrics;
995         int ret = 0;
996
997         if (!speed)
998                 return -EINVAL;
999
1000         ret = navi10_get_metrics_table(smu, &metrics);
1001         if (ret)
1002                 return ret;
1003
1004         *speed = metrics.CurrFanSpeed;
1005
1006         return ret;
1007 }
1008
1009 static int navi10_get_fan_speed_percent(struct smu_context *smu,
1010                                         uint32_t *speed)
1011 {
1012         int ret = 0;
1013         uint32_t percent = 0;
1014         uint32_t current_rpm;
1015         PPTable_t *pptable = smu->smu_table.driver_pptable;
1016
1017         ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
1018         if (ret)
1019                 return ret;
1020
1021         percent = current_rpm * 100 / pptable->FanMaximumRpm;
1022         *speed = percent > 100 ? 100 : percent;
1023
1024         return ret;
1025 }
1026
1027 static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1028 {
1029         DpmActivityMonitorCoeffInt_t activity_monitor;
1030         uint32_t i, size = 0;
1031         int16_t workload_type = 0;
1032         static const char *profile_name[] = {
1033                                         "BOOTUP_DEFAULT",
1034                                         "3D_FULL_SCREEN",
1035                                         "POWER_SAVING",
1036                                         "VIDEO",
1037                                         "VR",
1038                                         "COMPUTE",
1039                                         "CUSTOM"};
1040         static const char *title[] = {
1041                         "PROFILE_INDEX(NAME)",
1042                         "CLOCK_TYPE(NAME)",
1043                         "FPS",
1044                         "MinFreqType",
1045                         "MinActiveFreqType",
1046                         "MinActiveFreq",
1047                         "BoosterFreqType",
1048                         "BoosterFreq",
1049                         "PD_Data_limit_c",
1050                         "PD_Data_error_coeff",
1051                         "PD_Data_error_rate_coeff"};
1052         int result = 0;
1053
1054         if (!buf)
1055                 return -EINVAL;
1056
1057         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1058                         title[0], title[1], title[2], title[3], title[4], title[5],
1059                         title[6], title[7], title[8], title[9], title[10]);
1060
1061         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1062                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1063                 workload_type = smu_workload_get_type(smu, i);
1064                 if (workload_type < 0)
1065                         return -EINVAL;
1066
1067                 result = smu_update_table(smu,
1068                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1069                                           (void *)(&activity_monitor), false);
1070                 if (result) {
1071                         pr_err("[%s] Failed to get activity monitor!", __func__);
1072                         return result;
1073                 }
1074
1075                 size += sprintf(buf + size, "%2d %14s%s:\n",
1076                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1077
1078                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1079                         " ",
1080                         0,
1081                         "GFXCLK",
1082                         activity_monitor.Gfx_FPS,
1083                         activity_monitor.Gfx_MinFreqStep,
1084                         activity_monitor.Gfx_MinActiveFreqType,
1085                         activity_monitor.Gfx_MinActiveFreq,
1086                         activity_monitor.Gfx_BoosterFreqType,
1087                         activity_monitor.Gfx_BoosterFreq,
1088                         activity_monitor.Gfx_PD_Data_limit_c,
1089                         activity_monitor.Gfx_PD_Data_error_coeff,
1090                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
1091
1092                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1093                         " ",
1094                         1,
1095                         "SOCCLK",
1096                         activity_monitor.Soc_FPS,
1097                         activity_monitor.Soc_MinFreqStep,
1098                         activity_monitor.Soc_MinActiveFreqType,
1099                         activity_monitor.Soc_MinActiveFreq,
1100                         activity_monitor.Soc_BoosterFreqType,
1101                         activity_monitor.Soc_BoosterFreq,
1102                         activity_monitor.Soc_PD_Data_limit_c,
1103                         activity_monitor.Soc_PD_Data_error_coeff,
1104                         activity_monitor.Soc_PD_Data_error_rate_coeff);
1105
1106                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1107                         " ",
1108                         2,
1109                         "MEMLK",
1110                         activity_monitor.Mem_FPS,
1111                         activity_monitor.Mem_MinFreqStep,
1112                         activity_monitor.Mem_MinActiveFreqType,
1113                         activity_monitor.Mem_MinActiveFreq,
1114                         activity_monitor.Mem_BoosterFreqType,
1115                         activity_monitor.Mem_BoosterFreq,
1116                         activity_monitor.Mem_PD_Data_limit_c,
1117                         activity_monitor.Mem_PD_Data_error_coeff,
1118                         activity_monitor.Mem_PD_Data_error_rate_coeff);
1119         }
1120
1121         return size;
1122 }
1123
1124 static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1125 {
1126         DpmActivityMonitorCoeffInt_t activity_monitor;
1127         int workload_type, ret = 0;
1128
1129         smu->power_profile_mode = input[size];
1130
1131         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1132                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1133                 return -EINVAL;
1134         }
1135
1136         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1137                 if (size < 0)
1138                         return -EINVAL;
1139
1140                 ret = smu_update_table(smu,
1141                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1142                                        (void *)(&activity_monitor), false);
1143                 if (ret) {
1144                         pr_err("[%s] Failed to get activity monitor!", __func__);
1145                         return ret;
1146                 }
1147
1148                 switch (input[0]) {
1149                 case 0: /* Gfxclk */
1150                         activity_monitor.Gfx_FPS = input[1];
1151                         activity_monitor.Gfx_MinFreqStep = input[2];
1152                         activity_monitor.Gfx_MinActiveFreqType = input[3];
1153                         activity_monitor.Gfx_MinActiveFreq = input[4];
1154                         activity_monitor.Gfx_BoosterFreqType = input[5];
1155                         activity_monitor.Gfx_BoosterFreq = input[6];
1156                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
1157                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1158                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1159                         break;
1160                 case 1: /* Socclk */
1161                         activity_monitor.Soc_FPS = input[1];
1162                         activity_monitor.Soc_MinFreqStep = input[2];
1163                         activity_monitor.Soc_MinActiveFreqType = input[3];
1164                         activity_monitor.Soc_MinActiveFreq = input[4];
1165                         activity_monitor.Soc_BoosterFreqType = input[5];
1166                         activity_monitor.Soc_BoosterFreq = input[6];
1167                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1168                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1169                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1170                         break;
1171                 case 2: /* Memlk */
1172                         activity_monitor.Mem_FPS = input[1];
1173                         activity_monitor.Mem_MinFreqStep = input[2];
1174                         activity_monitor.Mem_MinActiveFreqType = input[3];
1175                         activity_monitor.Mem_MinActiveFreq = input[4];
1176                         activity_monitor.Mem_BoosterFreqType = input[5];
1177                         activity_monitor.Mem_BoosterFreq = input[6];
1178                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1179                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1180                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1181                         break;
1182                 }
1183
1184                 ret = smu_update_table(smu,
1185                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1186                                        (void *)(&activity_monitor), true);
1187                 if (ret) {
1188                         pr_err("[%s] Failed to set activity monitor!", __func__);
1189                         return ret;
1190                 }
1191         }
1192
1193         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1194         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1195         if (workload_type < 0)
1196                 return -EINVAL;
1197         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1198                                     1 << workload_type);
1199
1200         return ret;
1201 }
1202
1203 static int navi10_get_profiling_clk_mask(struct smu_context *smu,
1204                                          enum amd_dpm_forced_level level,
1205                                          uint32_t *sclk_mask,
1206                                          uint32_t *mclk_mask,
1207                                          uint32_t *soc_mask)
1208 {
1209         int ret = 0;
1210         uint32_t level_count = 0;
1211
1212         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1213                 if (sclk_mask)
1214                         *sclk_mask = 0;
1215         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1216                 if (mclk_mask)
1217                         *mclk_mask = 0;
1218         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1219                 if(sclk_mask) {
1220                         ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count);
1221                         if (ret)
1222                                 return ret;
1223                         *sclk_mask = level_count - 1;
1224                 }
1225
1226                 if(mclk_mask) {
1227                         ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count);
1228                         if (ret)
1229                                 return ret;
1230                         *mclk_mask = level_count - 1;
1231                 }
1232
1233                 if(soc_mask) {
1234                         ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count);
1235                         if (ret)
1236                                 return ret;
1237                         *soc_mask = level_count - 1;
1238                 }
1239         }
1240
1241         return ret;
1242 }
1243
1244 static int navi10_notify_smc_dispaly_config(struct smu_context *smu)
1245 {
1246         struct smu_clocks min_clocks = {0};
1247         struct pp_display_clock_request clock_req;
1248         int ret = 0;
1249
1250         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1251         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1252         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1253
1254         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1255                 clock_req.clock_type = amd_pp_dcef_clock;
1256                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1257                 if (!smu_display_clock_voltage_request(smu, &clock_req)) {
1258                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1259                                 ret = smu_send_smc_msg_with_param(smu,
1260                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
1261                                                                   min_clocks.dcef_clock_in_sr/100);
1262                                 if (ret) {
1263                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
1264                                         return ret;
1265                                 }
1266                         }
1267                 } else {
1268                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1269                 }
1270         }
1271
1272         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1273                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
1274                 if (ret) {
1275                         pr_err("[%s] Set hard min uclk failed!", __func__);
1276                         return ret;
1277                 }
1278         }
1279
1280         return 0;
1281 }
1282
1283 static int navi10_set_watermarks_table(struct smu_context *smu,
1284                                        void *watermarks, struct
1285                                        dm_pp_wm_sets_with_clock_ranges_soc15
1286                                        *clock_ranges)
1287 {
1288         int i;
1289         Watermarks_t *table = watermarks;
1290
1291         if (!table || !clock_ranges)
1292                 return -EINVAL;
1293
1294         if (clock_ranges->num_wm_dmif_sets > 4 ||
1295             clock_ranges->num_wm_mcif_sets > 4)
1296                 return -EINVAL;
1297
1298         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
1299                 table->WatermarkRow[1][i].MinClock =
1300                         cpu_to_le16((uint16_t)
1301                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1302                         1000));
1303                 table->WatermarkRow[1][i].MaxClock =
1304                         cpu_to_le16((uint16_t)
1305                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1306                         1000));
1307                 table->WatermarkRow[1][i].MinUclk =
1308                         cpu_to_le16((uint16_t)
1309                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1310                         1000));
1311                 table->WatermarkRow[1][i].MaxUclk =
1312                         cpu_to_le16((uint16_t)
1313                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1314                         1000));
1315                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
1316                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
1317         }
1318
1319         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
1320                 table->WatermarkRow[0][i].MinClock =
1321                         cpu_to_le16((uint16_t)
1322                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1323                         1000));
1324                 table->WatermarkRow[0][i].MaxClock =
1325                         cpu_to_le16((uint16_t)
1326                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1327                         1000));
1328                 table->WatermarkRow[0][i].MinUclk =
1329                         cpu_to_le16((uint16_t)
1330                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1331                         1000));
1332                 table->WatermarkRow[0][i].MaxUclk =
1333                         cpu_to_le16((uint16_t)
1334                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1335                         1000));
1336                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
1337                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
1338         }
1339
1340         return 0;
1341 }
1342
1343 static int navi10_thermal_get_temperature(struct smu_context *smu,
1344                                              enum amd_pp_sensors sensor,
1345                                              uint32_t *value)
1346 {
1347         SmuMetrics_t metrics;
1348         int ret = 0;
1349
1350         if (!value)
1351                 return -EINVAL;
1352
1353         ret = navi10_get_metrics_table(smu, &metrics);
1354         if (ret)
1355                 return ret;
1356
1357         switch (sensor) {
1358         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1359                 *value = metrics.TemperatureHotspot *
1360                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1361                 break;
1362         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1363                 *value = metrics.TemperatureEdge *
1364                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1365                 break;
1366         case AMDGPU_PP_SENSOR_MEM_TEMP:
1367                 *value = metrics.TemperatureMem *
1368                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1369                 break;
1370         default:
1371                 pr_err("Invalid sensor for retrieving temp\n");
1372                 return -EINVAL;
1373         }
1374
1375         return 0;
1376 }
1377
1378 static int navi10_read_sensor(struct smu_context *smu,
1379                                  enum amd_pp_sensors sensor,
1380                                  void *data, uint32_t *size)
1381 {
1382         int ret = 0;
1383         struct smu_table_context *table_context = &smu->smu_table;
1384         PPTable_t *pptable = table_context->driver_pptable;
1385
1386         if(!data || !size)
1387                 return -EINVAL;
1388
1389         switch (sensor) {
1390         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1391                 *(uint32_t *)data = pptable->FanMaximumRpm;
1392                 *size = 4;
1393                 break;
1394         case AMDGPU_PP_SENSOR_MEM_LOAD:
1395         case AMDGPU_PP_SENSOR_GPU_LOAD:
1396                 ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
1397                 *size = 4;
1398                 break;
1399         case AMDGPU_PP_SENSOR_GPU_POWER:
1400                 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1401                 *size = 4;
1402                 break;
1403         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1404         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1405         case AMDGPU_PP_SENSOR_MEM_TEMP:
1406                 ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
1407                 *size = 4;
1408                 break;
1409         default:
1410                 ret = smu_smc_read_sensor(smu, sensor, data, size);
1411         }
1412
1413         return ret;
1414 }
1415
1416 static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
1417 {
1418         uint32_t num_discrete_levels = 0;
1419         uint16_t *dpm_levels = NULL;
1420         uint16_t i = 0;
1421         struct smu_table_context *table_context = &smu->smu_table;
1422         PPTable_t *driver_ppt = NULL;
1423
1424         if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
1425                 return -EINVAL;
1426
1427         driver_ppt = table_context->driver_pptable;
1428         num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
1429         dpm_levels = driver_ppt->FreqTableUclk;
1430
1431         if (num_discrete_levels == 0 || dpm_levels == NULL)
1432                 return -EINVAL;
1433
1434         *num_states = num_discrete_levels;
1435         for (i = 0; i < num_discrete_levels; i++) {
1436                 /* convert to khz */
1437                 *clocks_in_khz = (*dpm_levels) * 1000;
1438                 clocks_in_khz++;
1439                 dpm_levels++;
1440         }
1441
1442         return 0;
1443 }
1444
1445 static int navi10_set_peak_clock_by_device(struct smu_context *smu)
1446 {
1447         struct amdgpu_device *adev = smu->adev;
1448         int ret = 0;
1449         uint32_t sclk_freq = 0, uclk_freq = 0;
1450         uint32_t uclk_level = 0;
1451
1452         switch (adev->pdev->revision) {
1453         case 0xf0: /* XTX */
1454         case 0xc0:
1455                 sclk_freq = NAVI10_PEAK_SCLK_XTX;
1456                 break;
1457         case 0xf1: /* XT */
1458         case 0xc1:
1459                 sclk_freq = NAVI10_PEAK_SCLK_XT;
1460                 break;
1461         default: /* XL */
1462                 sclk_freq = NAVI10_PEAK_SCLK_XL;
1463                 break;
1464         }
1465
1466         ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
1467         if (ret)
1468                 return ret;
1469         ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
1470         if (ret)
1471                 return ret;
1472
1473         ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
1474         if (ret)
1475                 return ret;
1476         ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
1477         if (ret)
1478                 return ret;
1479
1480         return ret;
1481 }
1482
1483 static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1484 {
1485         int ret = 0;
1486         struct amdgpu_device *adev = smu->adev;
1487
1488         if (adev->asic_type != CHIP_NAVI10)
1489                 return -EINVAL;
1490
1491         switch (level) {
1492         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1493                 ret = navi10_set_peak_clock_by_device(smu);
1494                 break;
1495         default:
1496                 ret = -EINVAL;
1497                 break;
1498         }
1499
1500         return ret;
1501 }
1502
1503 static int navi10_get_thermal_temperature_range(struct smu_context *smu,
1504                                                 struct smu_temperature_range *range)
1505 {
1506         struct smu_table_context *table_context = &smu->smu_table;
1507         struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
1508
1509         if (!range || !powerplay_table)
1510                 return -EINVAL;
1511
1512         range->max = powerplay_table->software_shutdown_temp *
1513                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1514
1515         return 0;
1516 }
1517
1518 static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
1519                                                 bool disable_memory_clock_switch)
1520 {
1521         int ret = 0;
1522         struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
1523                 (struct smu_11_0_max_sustainable_clocks *)
1524                         smu->smu_table.max_sustainable_clocks;
1525         uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
1526         uint32_t max_memory_clock = max_sustainable_clocks->uclock;
1527
1528         if(smu->disable_uclk_switch == disable_memory_clock_switch)
1529                 return 0;
1530
1531         if(disable_memory_clock_switch)
1532                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0);
1533         else
1534                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0);
1535
1536         if(!ret)
1537                 smu->disable_uclk_switch = disable_memory_clock_switch;
1538
1539         return ret;
1540 }
1541
1542 static int navi10_get_power_limit(struct smu_context *smu,
1543                                      uint32_t *limit,
1544                                      bool asic_default)
1545 {
1546         PPTable_t *pptable = smu->smu_table.driver_pptable;
1547         uint32_t asic_default_power_limit = 0;
1548         int ret = 0;
1549         int power_src;
1550
1551         if (!smu->default_power_limit ||
1552             !smu->power_limit) {
1553                 if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
1554                         power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
1555                         if (power_src < 0)
1556                                 return -EINVAL;
1557
1558                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
1559                                 power_src << 16);
1560                         if (ret) {
1561                                 pr_err("[%s] get PPT limit failed!", __func__);
1562                                 return ret;
1563                         }
1564                         smu_read_smc_arg(smu, &asic_default_power_limit);
1565                 } else {
1566                         /* the last hope to figure out the ppt limit */
1567                         if (!pptable) {
1568                                 pr_err("Cannot get PPT limit due to pptable missing!");
1569                                 return -EINVAL;
1570                         }
1571                         asic_default_power_limit =
1572                                 pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1573                 }
1574
1575                 if (smu->od_enabled) {
1576                         asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
1577                         asic_default_power_limit /= 100;
1578                 }
1579
1580                 smu->default_power_limit = asic_default_power_limit;
1581                 smu->power_limit = asic_default_power_limit;
1582         }
1583
1584         if (asic_default)
1585                 *limit = smu->default_power_limit;
1586         else
1587                 *limit = smu->power_limit;
1588
1589         return 0;
1590 }
1591
1592 static const struct pptable_funcs navi10_ppt_funcs = {
1593         .tables_init = navi10_tables_init,
1594         .alloc_dpm_context = navi10_allocate_dpm_context,
1595         .store_powerplay_table = navi10_store_powerplay_table,
1596         .check_powerplay_table = navi10_check_powerplay_table,
1597         .append_powerplay_table = navi10_append_powerplay_table,
1598         .get_smu_msg_index = navi10_get_smu_msg_index,
1599         .get_smu_clk_index = navi10_get_smu_clk_index,
1600         .get_smu_feature_index = navi10_get_smu_feature_index,
1601         .get_smu_table_index = navi10_get_smu_table_index,
1602         .get_smu_power_index = navi10_get_pwr_src_index,
1603         .get_workload_type = navi10_get_workload_type,
1604         .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
1605         .set_default_dpm_table = navi10_set_default_dpm_table,
1606         .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable,
1607         .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table,
1608         .print_clk_levels = navi10_print_clk_levels,
1609         .force_clk_levels = navi10_force_clk_levels,
1610         .populate_umd_state_clk = navi10_populate_umd_state_clk,
1611         .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
1612         .pre_display_config_changed = navi10_pre_display_config_changed,
1613         .display_config_changed = navi10_display_config_changed,
1614         .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config,
1615         .force_dpm_limit_value = navi10_force_dpm_limit_value,
1616         .unforce_dpm_levels = navi10_unforce_dpm_levels,
1617         .is_dpm_running = navi10_is_dpm_running,
1618         .get_fan_speed_percent = navi10_get_fan_speed_percent,
1619         .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
1620         .get_power_profile_mode = navi10_get_power_profile_mode,
1621         .set_power_profile_mode = navi10_set_power_profile_mode,
1622         .get_profiling_clk_mask = navi10_get_profiling_clk_mask,
1623         .set_watermarks_table = navi10_set_watermarks_table,
1624         .read_sensor = navi10_read_sensor,
1625         .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
1626         .set_performance_level = navi10_set_performance_level,
1627         .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
1628         .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
1629         .get_power_limit = navi10_get_power_limit,
1630 };
1631
1632 void navi10_set_ppt_funcs(struct smu_context *smu)
1633 {
1634         struct smu_table_context *smu_table = &smu->smu_table;
1635
1636         smu->ppt_funcs = &navi10_ppt_funcs;
1637         smu_table->table_count = TABLE_COUNT;
1638 }