]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drm/amd/powerplay: simplify the interface of get_gpu_power
[linux.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 "amdgpu.h"
27 #include "amdgpu_smu.h"
28 #include "atomfirmware.h"
29 #include "amdgpu_atomfirmware.h"
30 #include "smu_v11_0.h"
31 #include "smu11_driver_if_navi10.h"
32 #include "soc15_common.h"
33 #include "atom.h"
34 #include "navi10_ppt.h"
35 #include "smu_v11_0_pptable.h"
36 #include "smu_v11_0_ppsmc.h"
37
38 #define FEATURE_MASK(feature) (1UL << feature)
39 #define SMC_DPM_FEATURE ( \
40         FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
41         FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
42         FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT)   | \
43         FEATURE_MASK(FEATURE_DPM_UCLK_BIT)       | \
44         FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
45         FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)     | \
46         FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
47         FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
48
49 #define MSG_MAP(msg, index) \
50         [SMU_MSG_##msg] = index
51
52 static int navi10_message_map[SMU_MSG_MAX_COUNT] = {
53         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
54         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
55         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
56         MSG_MAP(SetAllowedFeaturesMaskLow,      PPSMC_MSG_SetAllowedFeaturesMaskLow),
57         MSG_MAP(SetAllowedFeaturesMaskHigh,     PPSMC_MSG_SetAllowedFeaturesMaskHigh),
58         MSG_MAP(EnableAllSmuFeatures,           PPSMC_MSG_EnableAllSmuFeatures),
59         MSG_MAP(DisableAllSmuFeatures,          PPSMC_MSG_DisableAllSmuFeatures),
60         MSG_MAP(EnableSmuFeaturesLow,           PPSMC_MSG_EnableSmuFeaturesLow),
61         MSG_MAP(EnableSmuFeaturesHigh,          PPSMC_MSG_EnableSmuFeaturesHigh),
62         MSG_MAP(DisableSmuFeaturesLow,          PPSMC_MSG_DisableSmuFeaturesLow),
63         MSG_MAP(DisableSmuFeaturesHigh,         PPSMC_MSG_DisableSmuFeaturesHigh),
64         MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetEnabledSmuFeaturesLow),
65         MSG_MAP(GetEnabledSmuFeaturesHigh,      PPSMC_MSG_GetEnabledSmuFeaturesHigh),
66         MSG_MAP(SetWorkloadMask,                PPSMC_MSG_SetWorkloadMask),
67         MSG_MAP(SetPptLimit,                    PPSMC_MSG_SetPptLimit),
68         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
69         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
70         MSG_MAP(SetToolsDramAddrHigh,           PPSMC_MSG_SetToolsDramAddrHigh),
71         MSG_MAP(SetToolsDramAddrLow,            PPSMC_MSG_SetToolsDramAddrLow),
72         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
73         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
74         MSG_MAP(UseDefaultPPTable,              PPSMC_MSG_UseDefaultPPTable),
75         MSG_MAP(UseBackupPPTable,               PPSMC_MSG_UseBackupPPTable),
76         MSG_MAP(RunBtc,                         PPSMC_MSG_RunBtc),
77         MSG_MAP(EnterBaco,                      PPSMC_MSG_EnterBaco),
78         MSG_MAP(SetSoftMinByFreq,               PPSMC_MSG_SetSoftMinByFreq),
79         MSG_MAP(SetSoftMaxByFreq,               PPSMC_MSG_SetSoftMaxByFreq),
80         MSG_MAP(SetHardMinByFreq,               PPSMC_MSG_SetHardMinByFreq),
81         MSG_MAP(SetHardMaxByFreq,               PPSMC_MSG_SetHardMaxByFreq),
82         MSG_MAP(GetMinDpmFreq,                  PPSMC_MSG_GetMinDpmFreq),
83         MSG_MAP(GetMaxDpmFreq,                  PPSMC_MSG_GetMaxDpmFreq),
84         MSG_MAP(GetDpmFreqByIndex,              PPSMC_MSG_GetDpmFreqByIndex),
85         MSG_MAP(SetMemoryChannelConfig,         PPSMC_MSG_SetMemoryChannelConfig),
86         MSG_MAP(SetGeminiMode,                  PPSMC_MSG_SetGeminiMode),
87         MSG_MAP(SetGeminiApertureHigh,          PPSMC_MSG_SetGeminiApertureHigh),
88         MSG_MAP(SetGeminiApertureLow,           PPSMC_MSG_SetGeminiApertureLow),
89         MSG_MAP(OverridePcieParameters,         PPSMC_MSG_OverridePcieParameters),
90         MSG_MAP(SetMinDeepSleepDcefclk,         PPSMC_MSG_SetMinDeepSleepDcefclk),
91         MSG_MAP(ReenableAcDcInterrupt,          PPSMC_MSG_ReenableAcDcInterrupt),
92         MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource),
93         MSG_MAP(SetUclkFastSwitch,              PPSMC_MSG_SetUclkFastSwitch),
94         MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
95         MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload),
96         MSG_MAP(DramLogSetDramAddrHigh,         PPSMC_MSG_DramLogSetDramAddrHigh),
97         MSG_MAP(DramLogSetDramAddrLow,          PPSMC_MSG_DramLogSetDramAddrLow),
98         MSG_MAP(DramLogSetDramSize,             PPSMC_MSG_DramLogSetDramSize),
99         MSG_MAP(ConfigureGfxDidt,               PPSMC_MSG_ConfigureGfxDidt),
100         MSG_MAP(NumOfDisplays,                  PPSMC_MSG_NumOfDisplays),
101         MSG_MAP(SetSystemVirtualDramAddrHigh,   PPSMC_MSG_SetSystemVirtualDramAddrHigh),
102         MSG_MAP(SetSystemVirtualDramAddrLow,    PPSMC_MSG_SetSystemVirtualDramAddrLow),
103         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff),
104         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff),
105         MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit),
106         MSG_MAP(GetDcModeMaxDpmFreq,            PPSMC_MSG_GetDcModeMaxDpmFreq),
107         MSG_MAP(GetDebugData,                   PPSMC_MSG_GetDebugData),
108         MSG_MAP(ExitBaco,                       PPSMC_MSG_ExitBaco),
109         MSG_MAP(PrepareMp1ForReset,             PPSMC_MSG_PrepareMp1ForReset),
110         MSG_MAP(PrepareMp1ForShutdown,          PPSMC_MSG_PrepareMp1ForShutdown),
111         MSG_MAP(PowerUpVcn,             PPSMC_MSG_PowerUpVcn),
112         MSG_MAP(PowerDownVcn,           PPSMC_MSG_PowerDownVcn),
113         MSG_MAP(PowerUpJpeg,            PPSMC_MSG_PowerUpJpeg),
114         MSG_MAP(PowerDownJpeg,          PPSMC_MSG_PowerDownJpeg),
115 };
116
117 static int navi10_clk_map[SMU_CLK_COUNT] = {
118         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
119         CLK_MAP(SCLK,   PPCLK_GFXCLK),
120         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
121         CLK_MAP(FCLK, PPCLK_SOCCLK),
122         CLK_MAP(UCLK, PPCLK_UCLK),
123         CLK_MAP(MCLK, PPCLK_UCLK),
124         CLK_MAP(DCLK, PPCLK_DCLK),
125         CLK_MAP(VCLK, PPCLK_VCLK),
126         CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
127         CLK_MAP(DISPCLK, PPCLK_DISPCLK),
128         CLK_MAP(PIXCLK, PPCLK_PIXCLK),
129         CLK_MAP(PHYCLK, PPCLK_PHYCLK),
130 };
131
132 static int navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
133         FEA_MAP(DPM_PREFETCHER),
134         FEA_MAP(DPM_GFXCLK),
135         FEA_MAP(DPM_GFX_PACE),
136         FEA_MAP(DPM_UCLK),
137         FEA_MAP(DPM_SOCCLK),
138         FEA_MAP(DPM_MP0CLK),
139         FEA_MAP(DPM_LINK),
140         FEA_MAP(DPM_DCEFCLK),
141         FEA_MAP(MEM_VDDCI_SCALING),
142         FEA_MAP(MEM_MVDD_SCALING),
143         FEA_MAP(DS_GFXCLK),
144         FEA_MAP(DS_SOCCLK),
145         FEA_MAP(DS_LCLK),
146         FEA_MAP(DS_DCEFCLK),
147         FEA_MAP(DS_UCLK),
148         FEA_MAP(GFX_ULV),
149         FEA_MAP(FW_DSTATE),
150         FEA_MAP(GFXOFF),
151         FEA_MAP(BACO),
152         FEA_MAP(VCN_PG),
153         FEA_MAP(JPEG_PG),
154         FEA_MAP(USB_PG),
155         FEA_MAP(RSMU_SMN_CG),
156         FEA_MAP(PPT),
157         FEA_MAP(TDC),
158         FEA_MAP(GFX_EDC),
159         FEA_MAP(APCC_PLUS),
160         FEA_MAP(GTHR),
161         FEA_MAP(ACDC),
162         FEA_MAP(VR0HOT),
163         FEA_MAP(VR1HOT),
164         FEA_MAP(FW_CTF),
165         FEA_MAP(FAN_CONTROL),
166         FEA_MAP(THERMAL),
167         FEA_MAP(GFX_DCS),
168         FEA_MAP(RM),
169         FEA_MAP(LED_DISPLAY),
170         FEA_MAP(GFX_SS),
171         FEA_MAP(OUT_OF_BAND_MONITOR),
172         FEA_MAP(TEMP_DEPENDENT_VMIN),
173         FEA_MAP(MMHUB_PG),
174         FEA_MAP(ATHUB_PG),
175 };
176
177 static int navi10_table_map[SMU_TABLE_COUNT] = {
178         TAB_MAP(PPTABLE),
179         TAB_MAP(WATERMARKS),
180         TAB_MAP(AVFS),
181         TAB_MAP(AVFS_PSM_DEBUG),
182         TAB_MAP(AVFS_FUSE_OVERRIDE),
183         TAB_MAP(PMSTATUSLOG),
184         TAB_MAP(SMU_METRICS),
185         TAB_MAP(DRIVER_SMU_CONFIG),
186         TAB_MAP(ACTIVITY_MONITOR_COEFF),
187         TAB_MAP(OVERDRIVE),
188         TAB_MAP(I2C_COMMANDS),
189         TAB_MAP(PACE),
190 };
191
192 static int navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
193         PWR_MAP(AC),
194         PWR_MAP(DC),
195 };
196
197 static int navi10_workload_map[] = {
198         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_PPLIB_DEFAULT_BIT),
199         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
200         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
201         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
202         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
203         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_CUSTOM_BIT),
204         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
205 };
206
207 static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
208 {
209         int val;
210         if (index > SMU_MSG_MAX_COUNT)
211                 return -EINVAL;
212
213         val = navi10_message_map[index];
214         if (val > PPSMC_Message_Count)
215                 return -EINVAL;
216
217         return val;
218 }
219
220 static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
221 {
222         int val;
223         if (index >= SMU_CLK_COUNT)
224                 return -EINVAL;
225
226         val = navi10_clk_map[index];
227         if (val >= PPCLK_COUNT)
228                 return -EINVAL;
229
230         return val;
231 }
232
233 static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
234 {
235         int val;
236         if (index >= SMU_FEATURE_COUNT)
237                 return -EINVAL;
238
239         val = navi10_feature_mask_map[index];
240         if (val > 64)
241                 return -EINVAL;
242
243         return val;
244 }
245
246 static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
247 {
248         int val;
249         if (index >= SMU_TABLE_COUNT)
250                 return -EINVAL;
251
252         val = navi10_table_map[index];
253         if (val >= TABLE_COUNT)
254                 return -EINVAL;
255
256         return val;
257 }
258
259 static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
260 {
261         int val;
262         if (index >= SMU_POWER_SOURCE_COUNT)
263                 return -EINVAL;
264
265         val = navi10_pwr_src_map[index];
266         if (val >= POWER_SOURCE_COUNT)
267                 return -EINVAL;
268
269         return val;
270 }
271
272
273 static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
274 {
275         int val;
276         if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
277                 return -EINVAL;
278
279         val = navi10_workload_map[profile];
280
281         return val;
282 }
283
284 static int
285 navi10_get_allowed_feature_mask(struct smu_context *smu,
286                                   uint32_t *feature_mask, uint32_t num)
287 {
288         struct amdgpu_device *adev = smu->adev;
289
290         if (num > 2)
291                 return -EINVAL;
292
293         memset(feature_mask, 0, sizeof(uint32_t) * num);
294
295         *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
296                                 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
297                                 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
298                                 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
299                                 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
300                                 | FEATURE_MASK(FEATURE_GFX_ULV_BIT)
301                                 | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
302                                 | FEATURE_MASK(FEATURE_PPT_BIT)
303                                 | FEATURE_MASK(FEATURE_TDC_BIT)
304                                 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
305                                 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
306                                 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
307                                 | FEATURE_MASK(FEATURE_THERMAL_BIT)
308                                 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
309                                 | FEATURE_MASK(FEATURE_MMHUB_PG_BIT)
310                                 | FEATURE_MASK(FEATURE_ATHUB_PG_BIT)
311                                 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT);
312
313         if (adev->pm.pp_feature & PP_MCLK_DPM_MASK)
314                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
315                                 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
316                                 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
317
318         if (adev->pm.pp_feature & PP_GFXOFF_MASK)
319                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_SS_BIT)
320                                 | FEATURE_MASK(FEATURE_GFXOFF_BIT);
321
322         if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
323                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT);
324
325         return 0;
326 }
327
328 static int navi10_check_powerplay_table(struct smu_context *smu)
329 {
330         return 0;
331 }
332
333 static int navi10_append_powerplay_table(struct smu_context *smu)
334 {
335         struct amdgpu_device *adev = smu->adev;
336         struct smu_table_context *table_context = &smu->smu_table;
337         PPTable_t *smc_pptable = table_context->driver_pptable;
338         struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
339         int index, ret;
340
341         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
342                                            smc_dpm_info);
343
344         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
345                                       (uint8_t **)&smc_dpm_table);
346         if (ret)
347                 return ret;
348
349         memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers,
350                sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS);
351
352         /* SVI2 Board Parameters */
353         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->MaxVoltageStepGfx;
354         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->MaxVoltageStepSoc;
355         smc_pptable->VddGfxVrMapping = smc_dpm_table->VddGfxVrMapping;
356         smc_pptable->VddSocVrMapping = smc_dpm_table->VddSocVrMapping;
357         smc_pptable->VddMem0VrMapping = smc_dpm_table->VddMem0VrMapping;
358         smc_pptable->VddMem1VrMapping = smc_dpm_table->VddMem1VrMapping;
359         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->GfxUlvPhaseSheddingMask;
360         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->SocUlvPhaseSheddingMask;
361         smc_pptable->ExternalSensorPresent = smc_dpm_table->ExternalSensorPresent;
362         smc_pptable->Padding8_V = smc_dpm_table->Padding8_V;
363
364         /* Telemetry Settings */
365         smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent;
366         smc_pptable->GfxOffset = smc_dpm_table->GfxOffset;
367         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->Padding_TelemetryGfx;
368         smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent;
369         smc_pptable->SocOffset = smc_dpm_table->SocOffset;
370         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->Padding_TelemetrySoc;
371         smc_pptable->Mem0MaxCurrent = smc_dpm_table->Mem0MaxCurrent;
372         smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset;
373         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->Padding_TelemetryMem0;
374         smc_pptable->Mem1MaxCurrent = smc_dpm_table->Mem1MaxCurrent;
375         smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset;
376         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->Padding_TelemetryMem1;
377
378         /* GPIO Settings */
379         smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio;
380         smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity;
381         smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio;
382         smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity;
383         smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio;
384         smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity;
385         smc_pptable->GthrGpio = smc_dpm_table->GthrGpio;
386         smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity;
387
388         /* LED Display Settings */
389         smc_pptable->LedPin0 = smc_dpm_table->LedPin0;
390         smc_pptable->LedPin1 = smc_dpm_table->LedPin1;
391         smc_pptable->LedPin2 = smc_dpm_table->LedPin2;
392         smc_pptable->padding8_4 = smc_dpm_table->padding8_4;
393
394         /* GFXCLK PLL Spread Spectrum */
395         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->PllGfxclkSpreadEnabled;
396         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->PllGfxclkSpreadPercent;
397         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->PllGfxclkSpreadFreq;
398
399         /* GFXCLK DFLL Spread Spectrum */
400         smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table->DfllGfxclkSpreadEnabled;
401         smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table->DfllGfxclkSpreadPercent;
402         smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table->DfllGfxclkSpreadFreq;
403
404         /* UCLK Spread Spectrum */
405         smc_pptable->UclkSpreadEnabled = smc_dpm_table->UclkSpreadEnabled;
406         smc_pptable->UclkSpreadPercent = smc_dpm_table->UclkSpreadPercent;
407         smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq;
408
409         /* SOCCLK Spread Spectrum */
410         smc_pptable->SoclkSpreadEnabled = smc_dpm_table->SoclkSpreadEnabled;
411         smc_pptable->SocclkSpreadPercent = smc_dpm_table->SocclkSpreadPercent;
412         smc_pptable->SocclkSpreadFreq = smc_dpm_table->SocclkSpreadFreq;
413
414         /* Total board power */
415         smc_pptable->TotalBoardPower = smc_dpm_table->TotalBoardPower;
416         smc_pptable->BoardPadding = smc_dpm_table->BoardPadding;
417
418         /* Mvdd Svi2 Div Ratio Setting */
419         smc_pptable->MvddRatio = smc_dpm_table->MvddRatio;
420
421         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
422                 *(uint64_t *)smc_pptable->FeaturesToRun |= FEATURE_MASK(FEATURE_GFX_SS_BIT)
423                                         | FEATURE_MASK(FEATURE_GFXOFF_BIT);
424
425                 /* TODO: remove it once SMU fw fix it */
426                 smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
427         }
428
429         return 0;
430 }
431
432 static int navi10_store_powerplay_table(struct smu_context *smu)
433 {
434         struct smu_11_0_powerplay_table *powerplay_table = NULL;
435         struct smu_table_context *table_context = &smu->smu_table;
436
437         if (!table_context->power_play_table)
438                 return -EINVAL;
439
440         powerplay_table = table_context->power_play_table;
441
442         memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
443                sizeof(PPTable_t));
444
445         return 0;
446 }
447
448 static void navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
449 {
450         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
451                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
452         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
453                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
454         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
455                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
456         SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
457                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
458         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
459                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
460         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
461                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
462                        AMDGPU_GEM_DOMAIN_VRAM);
463 }
464
465 static int navi10_allocate_dpm_context(struct smu_context *smu)
466 {
467         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
468
469         if (smu_dpm->dpm_context)
470                 return -EINVAL;
471
472         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
473                                        GFP_KERNEL);
474         if (!smu_dpm->dpm_context)
475                 return -ENOMEM;
476
477         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
478
479         return 0;
480 }
481
482 static int navi10_set_default_dpm_table(struct smu_context *smu)
483 {
484         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
485         struct smu_table_context *table_context = &smu->smu_table;
486         struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
487         PPTable_t *driver_ppt = NULL;
488
489         driver_ppt = table_context->driver_pptable;
490
491         dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0];
492         dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1];
493
494         dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0];
495         dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1];
496
497         dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0];
498         dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1];
499
500         dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0];
501         dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1];
502
503         dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0];
504         dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1];
505
506         dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0];
507         dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1];
508
509         dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0];
510         dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1];
511
512         dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0];
513         dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1];
514
515         dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0];
516         dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1];
517
518         return 0;
519 }
520
521 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
522 {
523         int ret = 0;
524         struct smu_power_context *smu_power = &smu->smu_power;
525         struct smu_power_gate *power_gate = &smu_power->power_gate;
526
527         if (enable && power_gate->uvd_gated) {
528                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
529                 if (ret)
530                         return ret;
531                 power_gate->uvd_gated = false;
532         } else {
533                 if (!enable && !power_gate->uvd_gated) {
534                         ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
535                         if (ret)
536                                 return ret;
537                         power_gate->uvd_gated = true;
538                 }
539         }
540
541         return 0;
542 }
543
544 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
545                                        enum smu_clk_type clk_type,
546                                        uint32_t *value)
547 {
548         static SmuMetrics_t metrics = {0};
549         int ret = 0, clk_id = 0;
550
551         if (!value)
552                 return -EINVAL;
553
554         ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void *)&metrics, false);
555         if (ret)
556                 return ret;
557
558         clk_id = smu_clk_get_index(smu, clk_type);
559         if (clk_id < 0)
560                 return clk_id;
561
562         *value = metrics.CurrClock[clk_id];
563
564         return ret;
565 }
566
567 static int navi10_print_clk_levels(struct smu_context *smu,
568                         enum smu_clk_type clk_type, char *buf)
569 {
570         int i, size = 0, ret = 0;
571         uint32_t cur_value = 0, value = 0, count = 0;
572
573         switch (clk_type) {
574         case SMU_GFXCLK:
575         case SMU_SCLK:
576         case SMU_SOCCLK:
577         case SMU_MCLK:
578         case SMU_UCLK:
579         case SMU_FCLK:
580         case SMU_DCEFCLK:
581                 ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
582                 if (ret)
583                         return size;
584                 /* 10KHz -> MHz */
585                 cur_value = cur_value / 100;
586
587                 size += sprintf(buf, "current clk: %uMhz\n", cur_value);
588
589                 ret = smu_get_dpm_level_count(smu, clk_type, &count);
590                 if (ret)
591                         return size;
592
593                 for (i = 0; i < count; i++) {
594                         ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
595                         if (ret)
596                                 return size;
597
598                         size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
599                                         cur_value == value ? "*" : "");
600                 }
601                 break;
602         default:
603                 break;
604         }
605
606         return size;
607 }
608
609 static int navi10_force_clk_levels(struct smu_context *smu,
610                                    enum smu_clk_type clk_type, uint32_t mask)
611 {
612
613         int ret = 0, size = 0;
614         uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
615
616         soft_min_level = mask ? (ffs(mask) - 1) : 0;
617         soft_max_level = mask ? (fls(mask) - 1) : 0;
618
619         switch (clk_type) {
620         case SMU_GFXCLK:
621         case SMU_SOCCLK:
622         case SMU_MCLK:
623         case SMU_UCLK:
624         case SMU_DCEFCLK:
625         case SMU_FCLK:
626                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
627                 if (ret)
628                         return size;
629
630                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
631                 if (ret)
632                         return size;
633
634                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
635                 if (ret)
636                         return size;
637                 break;
638         default:
639                 break;
640         }
641
642         return size;
643 }
644
645 static int navi10_populate_umd_state_clk(struct smu_context *smu)
646 {
647         int ret = 0;
648         uint32_t min_sclk_freq = 0;
649
650         ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL);
651         if (ret)
652                 return ret;
653
654         smu->pstate_sclk = min_sclk_freq * 100;
655
656         return ret;
657 }
658
659 static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
660                                                  enum smu_clk_type clk_type,
661                                                  struct pp_clock_levels_with_latency *clocks)
662 {
663         int ret = 0, i = 0;
664         uint32_t level_count = 0, freq = 0;
665
666         switch (clk_type) {
667         case SMU_GFXCLK:
668         case SMU_DCEFCLK:
669         case SMU_SOCCLK:
670                 ret = smu_get_dpm_level_count(smu, clk_type, &level_count);
671                 if (ret)
672                         return ret;
673
674                 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
675                 clocks->num_levels = level_count;
676
677                 for (i = 0; i < level_count; i++) {
678                         ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq);
679                         if (ret)
680                                 return ret;
681
682                         clocks->data[i].clocks_in_khz = freq * 1000;
683                         clocks->data[i].latency_in_us = 0;
684                 }
685                 break;
686         default:
687                 break;
688         }
689
690         return ret;
691 }
692
693 static int navi10_pre_display_config_changed(struct smu_context *smu)
694 {
695         int ret = 0;
696         uint32_t max_freq = 0;
697
698         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
699         if (ret)
700                 return ret;
701
702         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
703                 ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq);
704                 if (ret)
705                         return ret;
706                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq);
707                 if (ret)
708                         return ret;
709         }
710
711         return ret;
712 }
713
714 static int navi10_display_config_changed(struct smu_context *smu)
715 {
716         int ret = 0;
717
718         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
719             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
720                 ret = smu_write_watermarks_table(smu);
721                 if (ret)
722                         return ret;
723
724                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
725         }
726
727         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
728             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
729             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
730                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
731                                                   smu->display_config->num_display);
732                 if (ret)
733                         return ret;
734         }
735
736         return ret;
737 }
738
739 static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest)
740 {
741         int ret = 0, i = 0;
742         uint32_t min_freq, max_freq, force_freq;
743         enum smu_clk_type clk_type;
744
745         enum smu_clk_type clks[] = {
746                 SMU_GFXCLK,
747                 SMU_MCLK,
748                 SMU_SOCCLK,
749         };
750
751         for (i = 0; i < ARRAY_SIZE(clks); i++) {
752                 clk_type = clks[i];
753                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
754                 if (ret)
755                         return ret;
756
757                 force_freq = highest ? max_freq : min_freq;
758                 ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
759                 if (ret)
760                         return ret;
761         }
762
763         return ret;
764 }
765
766 static int navi10_unforce_dpm_levels(struct smu_context *smu) {
767
768         int ret = 0, i = 0;
769         uint32_t min_freq, max_freq;
770         enum smu_clk_type clk_type;
771
772         enum smu_clk_type clks[] = {
773                 SMU_GFXCLK,
774                 SMU_MCLK,
775                 SMU_SOCCLK,
776         };
777
778         for (i = 0; i < ARRAY_SIZE(clks); i++) {
779                 clk_type = clks[i];
780                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
781                 if (ret)
782                         return ret;
783
784                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
785                 if (ret)
786                         return ret;
787         }
788
789         return ret;
790 }
791
792 static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
793 {
794         int ret = 0;
795         SmuMetrics_t metrics;
796
797         if (!value)
798                 return -EINVAL;
799
800         ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void *)&metrics,
801                                false);
802         if (ret)
803                 return ret;
804
805         *value = metrics.CurrSocketPower << 8;
806
807         return 0;
808 }
809
810 static int navi10_get_current_activity_percent(struct smu_context *smu,
811                                                uint32_t *value)
812 {
813         int ret = 0;
814         SmuMetrics_t metrics;
815
816         if (!value)
817                 return -EINVAL;
818
819         ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS,
820                                (void *)&metrics, false);
821         if (ret)
822                 return ret;
823
824         *value = metrics.AverageGfxActivity;
825
826         return 0;
827 }
828
829 static bool navi10_is_dpm_running(struct smu_context *smu)
830 {
831         int ret = 0;
832         uint32_t feature_mask[2];
833         unsigned long feature_enabled;
834         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
835         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
836                            ((uint64_t)feature_mask[1] << 32));
837         return !!(feature_enabled & SMC_DPM_FEATURE);
838 }
839
840 static int navi10_set_thermal_fan_table(struct smu_context *smu)
841 {
842         int ret;
843         struct smu_table_context *table_context = &smu->smu_table;
844         PPTable_t *pptable = table_context->driver_pptable;
845
846         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget,
847                         (uint32_t)pptable->FanTargetTemperature);
848
849         return ret;
850 }
851
852 static int navi10_get_fan_speed_percent(struct smu_context *smu,
853                                         uint32_t *speed)
854 {
855         int ret = 0;
856         uint32_t percent = 0;
857         uint32_t current_rpm;
858         PPTable_t *pptable = smu->smu_table.driver_pptable;
859
860         ret = smu_get_current_rpm(smu, &current_rpm);
861         if (ret)
862                 return ret;
863
864         percent = current_rpm * 100 / pptable->FanMaximumRpm;
865         *speed = percent > 100 ? 100 : percent;
866
867         return ret;
868 }
869
870 static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
871 {
872         DpmActivityMonitorCoeffInt_t activity_monitor;
873         uint32_t i, size = 0;
874         uint16_t workload_type = 0;
875         static const char *profile_name[] = {
876                                         "BOOTUP_DEFAULT",
877                                         "3D_FULL_SCREEN",
878                                         "POWER_SAVING",
879                                         "VIDEO",
880                                         "VR",
881                                         "COMPUTE",
882                                         "CUSTOM"};
883         static const char *title[] = {
884                         "PROFILE_INDEX(NAME)",
885                         "CLOCK_TYPE(NAME)",
886                         "FPS",
887                         "MinFreqType",
888                         "MinActiveFreqType",
889                         "MinActiveFreq",
890                         "BoosterFreqType",
891                         "BoosterFreq",
892                         "PD_Data_limit_c",
893                         "PD_Data_error_coeff",
894                         "PD_Data_error_rate_coeff"};
895         int result = 0;
896
897         if (!buf)
898                 return -EINVAL;
899
900         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
901                         title[0], title[1], title[2], title[3], title[4], title[5],
902                         title[6], title[7], title[8], title[9], title[10]);
903
904         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
905                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
906                 workload_type = smu_workload_get_type(smu, i);
907                 result = smu_update_table(smu,
908                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16,
909                                           (void *)(&activity_monitor), false);
910                 if (result) {
911                         pr_err("[%s] Failed to get activity monitor!", __func__);
912                         return result;
913                 }
914
915                 size += sprintf(buf + size, "%2d %14s%s:\n",
916                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
917
918                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
919                         " ",
920                         0,
921                         "GFXCLK",
922                         activity_monitor.Gfx_FPS,
923                         activity_monitor.Gfx_MinFreqStep,
924                         activity_monitor.Gfx_MinActiveFreqType,
925                         activity_monitor.Gfx_MinActiveFreq,
926                         activity_monitor.Gfx_BoosterFreqType,
927                         activity_monitor.Gfx_BoosterFreq,
928                         activity_monitor.Gfx_PD_Data_limit_c,
929                         activity_monitor.Gfx_PD_Data_error_coeff,
930                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
931
932                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
933                         " ",
934                         1,
935                         "SOCCLK",
936                         activity_monitor.Soc_FPS,
937                         activity_monitor.Soc_MinFreqStep,
938                         activity_monitor.Soc_MinActiveFreqType,
939                         activity_monitor.Soc_MinActiveFreq,
940                         activity_monitor.Soc_BoosterFreqType,
941                         activity_monitor.Soc_BoosterFreq,
942                         activity_monitor.Soc_PD_Data_limit_c,
943                         activity_monitor.Soc_PD_Data_error_coeff,
944                         activity_monitor.Soc_PD_Data_error_rate_coeff);
945
946                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
947                         " ",
948                         2,
949                         "MEMLK",
950                         activity_monitor.Mem_FPS,
951                         activity_monitor.Mem_MinFreqStep,
952                         activity_monitor.Mem_MinActiveFreqType,
953                         activity_monitor.Mem_MinActiveFreq,
954                         activity_monitor.Mem_BoosterFreqType,
955                         activity_monitor.Mem_BoosterFreq,
956                         activity_monitor.Mem_PD_Data_limit_c,
957                         activity_monitor.Mem_PD_Data_error_coeff,
958                         activity_monitor.Mem_PD_Data_error_rate_coeff);
959         }
960
961         return size;
962 }
963
964 static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
965 {
966         DpmActivityMonitorCoeffInt_t activity_monitor;
967         int workload_type, ret = 0;
968
969         smu->power_profile_mode = input[size];
970
971         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
972                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
973                 return -EINVAL;
974         }
975
976         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
977                 if (size < 0)
978                         return -EINVAL;
979
980                 ret = smu_update_table(smu,
981                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
982                                        (void *)(&activity_monitor), false);
983                 if (ret) {
984                         pr_err("[%s] Failed to get activity monitor!", __func__);
985                         return ret;
986                 }
987
988                 switch (input[0]) {
989                 case 0: /* Gfxclk */
990                         activity_monitor.Gfx_FPS = input[1];
991                         activity_monitor.Gfx_MinFreqStep = input[2];
992                         activity_monitor.Gfx_MinActiveFreqType = input[3];
993                         activity_monitor.Gfx_MinActiveFreq = input[4];
994                         activity_monitor.Gfx_BoosterFreqType = input[5];
995                         activity_monitor.Gfx_BoosterFreq = input[6];
996                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
997                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
998                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
999                         break;
1000                 case 1: /* Socclk */
1001                         activity_monitor.Soc_FPS = input[1];
1002                         activity_monitor.Soc_MinFreqStep = input[2];
1003                         activity_monitor.Soc_MinActiveFreqType = input[3];
1004                         activity_monitor.Soc_MinActiveFreq = input[4];
1005                         activity_monitor.Soc_BoosterFreqType = input[5];
1006                         activity_monitor.Soc_BoosterFreq = input[6];
1007                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1008                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1009                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1010                         break;
1011                 case 2: /* Memlk */
1012                         activity_monitor.Mem_FPS = input[1];
1013                         activity_monitor.Mem_MinFreqStep = input[2];
1014                         activity_monitor.Mem_MinActiveFreqType = input[3];
1015                         activity_monitor.Mem_MinActiveFreq = input[4];
1016                         activity_monitor.Mem_BoosterFreqType = input[5];
1017                         activity_monitor.Mem_BoosterFreq = input[6];
1018                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1019                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1020                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1021                         break;
1022                 }
1023
1024                 ret = smu_update_table(smu,
1025                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF | WORKLOAD_PPLIB_CUSTOM_BIT << 16,
1026                                        (void *)(&activity_monitor), true);
1027                 if (ret) {
1028                         pr_err("[%s] Failed to set activity monitor!", __func__);
1029                         return ret;
1030                 }
1031         }
1032
1033         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1034         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1035         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1036                                     1 << workload_type);
1037
1038         return ret;
1039 }
1040
1041 static int navi10_get_profiling_clk_mask(struct smu_context *smu,
1042                                          enum amd_dpm_forced_level level,
1043                                          uint32_t *sclk_mask,
1044                                          uint32_t *mclk_mask,
1045                                          uint32_t *soc_mask)
1046 {
1047         int ret = 0;
1048         uint32_t level_count = 0;
1049
1050         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1051                 if (sclk_mask)
1052                         *sclk_mask = 0;
1053         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1054                 if (mclk_mask)
1055                         *mclk_mask = 0;
1056         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1057                 if(sclk_mask) {
1058                         ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count);
1059                         if (ret)
1060                                 return ret;
1061                         *sclk_mask = level_count - 1;
1062                 }
1063
1064                 if(mclk_mask) {
1065                         ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count);
1066                         if (ret)
1067                                 return ret;
1068                         *sclk_mask = level_count - 1;
1069                 }
1070
1071                 if(soc_mask) {
1072                         ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count);
1073                         if (ret)
1074                                 return ret;
1075                         *sclk_mask = level_count - 1;
1076                 }
1077         }
1078
1079         return ret;
1080 }
1081
1082 static int navi10_notify_smc_dispaly_config(struct smu_context *smu)
1083 {
1084         struct smu_clocks min_clocks = {0};
1085         struct pp_display_clock_request clock_req;
1086         int ret = 0;
1087
1088         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1089         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1090         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1091
1092         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1093                 clock_req.clock_type = amd_pp_dcef_clock;
1094                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1095                 if (!smu_display_clock_voltage_request(smu, &clock_req)) {
1096                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1097                                 ret = smu_send_smc_msg_with_param(smu,
1098                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
1099                                                                   min_clocks.dcef_clock_in_sr/100);
1100                                 if (ret) {
1101                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
1102                                         return ret;
1103                                 }
1104                         }
1105                 } else {
1106                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1107                 }
1108         }
1109
1110         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1111                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
1112                 if (ret) {
1113                         pr_err("[%s] Set hard min uclk failed!", __func__);
1114                         return ret;
1115                 }
1116         }
1117
1118         return 0;
1119 }
1120
1121 static int navi10_set_watermarks_table(struct smu_context *smu,
1122                                        void *watermarks, struct
1123                                        dm_pp_wm_sets_with_clock_ranges_soc15
1124                                        *clock_ranges)
1125 {
1126         int i;
1127         Watermarks_t *table = watermarks;
1128
1129         if (!table || !clock_ranges)
1130                 return -EINVAL;
1131
1132         if (clock_ranges->num_wm_dmif_sets > 4 ||
1133             clock_ranges->num_wm_mcif_sets > 4)
1134                 return -EINVAL;
1135
1136         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
1137                 table->WatermarkRow[1][i].MinClock =
1138                         cpu_to_le16((uint16_t)
1139                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1140                         1000));
1141                 table->WatermarkRow[1][i].MaxClock =
1142                         cpu_to_le16((uint16_t)
1143                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1144                         1000));
1145                 table->WatermarkRow[1][i].MinUclk =
1146                         cpu_to_le16((uint16_t)
1147                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1148                         1000));
1149                 table->WatermarkRow[1][i].MaxUclk =
1150                         cpu_to_le16((uint16_t)
1151                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1152                         1000));
1153                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
1154                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
1155         }
1156
1157         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
1158                 table->WatermarkRow[0][i].MinClock =
1159                         cpu_to_le16((uint16_t)
1160                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1161                         1000));
1162                 table->WatermarkRow[0][i].MaxClock =
1163                         cpu_to_le16((uint16_t)
1164                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1165                         1000));
1166                 table->WatermarkRow[0][i].MinUclk =
1167                         cpu_to_le16((uint16_t)
1168                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1169                         1000));
1170                 table->WatermarkRow[0][i].MaxUclk =
1171                         cpu_to_le16((uint16_t)
1172                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1173                         1000));
1174                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
1175                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
1176         }
1177
1178         return 0;
1179 }
1180
1181 static int navi10_read_sensor(struct smu_context *smu,
1182                                  enum amd_pp_sensors sensor,
1183                                  void *data, uint32_t *size)
1184 {
1185         int ret = 0;
1186         struct smu_table_context *table_context = &smu->smu_table;
1187         PPTable_t *pptable = table_context->driver_pptable;
1188
1189         switch (sensor) {
1190         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1191                 *(uint32_t *)data = pptable->FanMaximumRpm;
1192                 *size = 4;
1193                 break;
1194         case AMDGPU_PP_SENSOR_GPU_LOAD:
1195                 ret = navi10_get_current_activity_percent(smu, (uint32_t *)data);
1196                 *size = 4;
1197                 break;
1198         case AMDGPU_PP_SENSOR_GPU_POWER:
1199                 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1200                 *size = 4;
1201                 break;
1202         default:
1203                 return -EINVAL;
1204         }
1205
1206         return ret;
1207 }
1208
1209 static const struct pptable_funcs navi10_ppt_funcs = {
1210         .tables_init = navi10_tables_init,
1211         .alloc_dpm_context = navi10_allocate_dpm_context,
1212         .store_powerplay_table = navi10_store_powerplay_table,
1213         .check_powerplay_table = navi10_check_powerplay_table,
1214         .append_powerplay_table = navi10_append_powerplay_table,
1215         .get_smu_msg_index = navi10_get_smu_msg_index,
1216         .get_smu_clk_index = navi10_get_smu_clk_index,
1217         .get_smu_feature_index = navi10_get_smu_feature_index,
1218         .get_smu_table_index = navi10_get_smu_table_index,
1219         .get_smu_power_index = navi10_get_pwr_src_index,
1220         .get_workload_type = navi10_get_workload_type,
1221         .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
1222         .set_default_dpm_table = navi10_set_default_dpm_table,
1223         .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable,
1224         .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table,
1225         .print_clk_levels = navi10_print_clk_levels,
1226         .force_clk_levels = navi10_force_clk_levels,
1227         .populate_umd_state_clk = navi10_populate_umd_state_clk,
1228         .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
1229         .pre_display_config_changed = navi10_pre_display_config_changed,
1230         .display_config_changed = navi10_display_config_changed,
1231         .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config,
1232         .force_dpm_limit_value = navi10_force_dpm_limit_value,
1233         .unforce_dpm_levels = navi10_unforce_dpm_levels,
1234         .is_dpm_running = navi10_is_dpm_running,
1235         .set_thermal_fan_table = navi10_set_thermal_fan_table,
1236         .get_fan_speed_percent = navi10_get_fan_speed_percent,
1237         .get_power_profile_mode = navi10_get_power_profile_mode,
1238         .set_power_profile_mode = navi10_set_power_profile_mode,
1239         .get_profiling_clk_mask = navi10_get_profiling_clk_mask,
1240         .set_watermarks_table = navi10_set_watermarks_table,
1241         .read_sensor = navi10_read_sensor,
1242 };
1243
1244 void navi10_set_ppt_funcs(struct smu_context *smu)
1245 {
1246         struct smu_table_context *smu_table = &smu->smu_table;
1247
1248         smu->ppt_funcs = &navi10_ppt_funcs;
1249         smu->smc_if_version = SMU11_DRIVER_IF_VERSION;
1250         smu_table->table_count = TABLE_COUNT;
1251 }