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