drm/amdgpu: expand to add multiple trap event irq id
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / navi10_ppt.c
CommitLineData
b3490673
HR
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
b3490673 24#include <linux/firmware.h>
354e6e14 25#include <linux/pci.h>
b3490673
HR
26#include "amdgpu.h"
27#include "amdgpu_smu.h"
18c1d3ce 28#include "smu_internal.h"
b3490673
HR
29#include "atomfirmware.h"
30#include "amdgpu_atomfirmware.h"
49e78c82 31#include "soc15_common.h"
b3490673 32#include "smu_v11_0.h"
013fd3a6 33#include "smu11_driver_if_navi10.h"
b3490673
HR
34#include "atom.h"
35#include "navi10_ppt.h"
36#include "smu_v11_0_pptable.h"
37#include "smu_v11_0_ppsmc.h"
49e78c82
EQ
38#include "nbio/nbio_2_3_offset.h"
39#include "nbio/nbio_2_3_sh_mask.h"
947c127b
LG
40#include "thm/thm_11_0_2_offset.h"
41#include "thm/thm_11_0_2_sh_mask.h"
b3490673 42
fc419158
TZ
43#include "asic_reg/mp/mp_11_0_sh_mask.h"
44
55084d7f
EQ
45/*
46 * DO NOT use these for err/warn/info/debug messages.
47 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
48 * They are more MGPU friendly.
49 */
50#undef pr_err
51#undef pr_warn
52#undef pr_info
53#undef pr_debug
54
44ff0ae6 55#define FEATURE_MASK(feature) (1ULL << feature)
4228b601
KW
56#define SMC_DPM_FEATURE ( \
57 FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
58 FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
59 FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \
60 FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
61 FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
62 FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \
63 FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \
64 FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
65
d4f3c0b3
WS
66#define MSG_MAP(msg, index, valid_in_vf) \
67 [SMU_MSG_##msg] = {1, (index), (valid_in_vf)}
b3490673 68
d4f3c0b3
WS
69static struct smu_11_0_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
70 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
71 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
72 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
73 MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0),
74 MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0),
75 MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
76 MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
77 MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1),
78 MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1),
79 MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1),
80 MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1),
81 MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1),
82 MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1),
83 MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1),
84 MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
85 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0),
86 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0),
87 MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
88 MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
89 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0),
90 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
91 MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
92 MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0),
93 MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 0),
94 MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0),
95 MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0),
96 MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0),
97 MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1),
98 MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
99 MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1),
100 MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1),
101 MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
102 MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0),
103 MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 0),
104 MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 0),
105 MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 0),
106 MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0),
107 MSG_MAP(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 0),
108 MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0),
109 MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0),
110 MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 0),
111 MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 0),
112 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1),
113 MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
114 MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
115 MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
116 MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0),
117 MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0),
118 MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0),
119 MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0),
120 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0),
121 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
122 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0),
123 MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1),
124 MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0),
125 MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0),
126 MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0),
127 MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0),
128 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
129 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
130 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
131 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
132 MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0),
133 MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
134 MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange, 0),
135 MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0),
136 MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0),
137 MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0),
b3490673
HR
138};
139
7e01a2ec 140static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
0de94acf 141 CLK_MAP(GFXCLK, PPCLK_GFXCLK),
b1e7e224 142 CLK_MAP(SCLK, PPCLK_GFXCLK),
0de94acf 143 CLK_MAP(SOCCLK, PPCLK_SOCCLK),
b1e7e224 144 CLK_MAP(FCLK, PPCLK_SOCCLK),
0de94acf 145 CLK_MAP(UCLK, PPCLK_UCLK),
b1e7e224 146 CLK_MAP(MCLK, PPCLK_UCLK),
0de94acf
HR
147 CLK_MAP(DCLK, PPCLK_DCLK),
148 CLK_MAP(VCLK, PPCLK_VCLK),
149 CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
150 CLK_MAP(DISPCLK, PPCLK_DISPCLK),
151 CLK_MAP(PIXCLK, PPCLK_PIXCLK),
152 CLK_MAP(PHYCLK, PPCLK_PHYCLK),
153};
154
7e01a2ec 155static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
ffcb08df
HR
156 FEA_MAP(DPM_PREFETCHER),
157 FEA_MAP(DPM_GFXCLK),
158 FEA_MAP(DPM_GFX_PACE),
159 FEA_MAP(DPM_UCLK),
160 FEA_MAP(DPM_SOCCLK),
161 FEA_MAP(DPM_MP0CLK),
162 FEA_MAP(DPM_LINK),
163 FEA_MAP(DPM_DCEFCLK),
164 FEA_MAP(MEM_VDDCI_SCALING),
165 FEA_MAP(MEM_MVDD_SCALING),
166 FEA_MAP(DS_GFXCLK),
167 FEA_MAP(DS_SOCCLK),
168 FEA_MAP(DS_LCLK),
169 FEA_MAP(DS_DCEFCLK),
170 FEA_MAP(DS_UCLK),
171 FEA_MAP(GFX_ULV),
172 FEA_MAP(FW_DSTATE),
173 FEA_MAP(GFXOFF),
174 FEA_MAP(BACO),
175 FEA_MAP(VCN_PG),
176 FEA_MAP(JPEG_PG),
177 FEA_MAP(USB_PG),
178 FEA_MAP(RSMU_SMN_CG),
179 FEA_MAP(PPT),
180 FEA_MAP(TDC),
181 FEA_MAP(GFX_EDC),
182 FEA_MAP(APCC_PLUS),
183 FEA_MAP(GTHR),
184 FEA_MAP(ACDC),
185 FEA_MAP(VR0HOT),
186 FEA_MAP(VR1HOT),
187 FEA_MAP(FW_CTF),
188 FEA_MAP(FAN_CONTROL),
189 FEA_MAP(THERMAL),
190 FEA_MAP(GFX_DCS),
191 FEA_MAP(RM),
192 FEA_MAP(LED_DISPLAY),
193 FEA_MAP(GFX_SS),
194 FEA_MAP(OUT_OF_BAND_MONITOR),
195 FEA_MAP(TEMP_DEPENDENT_VMIN),
196 FEA_MAP(MMHUB_PG),
197 FEA_MAP(ATHUB_PG),
f256ba47 198 FEA_MAP(APCC_DFLL),
ffcb08df
HR
199};
200
7e01a2ec 201static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = {
2436911b
HR
202 TAB_MAP(PPTABLE),
203 TAB_MAP(WATERMARKS),
204 TAB_MAP(AVFS),
205 TAB_MAP(AVFS_PSM_DEBUG),
206 TAB_MAP(AVFS_FUSE_OVERRIDE),
207 TAB_MAP(PMSTATUSLOG),
208 TAB_MAP(SMU_METRICS),
209 TAB_MAP(DRIVER_SMU_CONFIG),
210 TAB_MAP(ACTIVITY_MONITOR_COEFF),
211 TAB_MAP(OVERDRIVE),
212 TAB_MAP(I2C_COMMANDS),
213 TAB_MAP(PACE),
214};
215
7e01a2ec 216static struct smu_11_0_cmn2aisc_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
8890fe5f
HR
217 PWR_MAP(AC),
218 PWR_MAP(DC),
219};
220
7e01a2ec 221static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
6c6187ec
KW
222 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT),
223 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
224 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
225 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
226 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
2c874ad9 227 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
6c6187ec
KW
228 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
229};
230
b3490673
HR
231static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
232{
d4f3c0b3 233 struct smu_11_0_msg_mapping mapping;
7e01a2ec 234
5556b9fe 235 if (index >= SMU_MSG_MAX_COUNT)
b3490673 236 return -EINVAL;
b3490673 237
7e01a2ec 238 mapping = navi10_message_map[index];
c0640304 239 if (!(mapping.valid_mapping)) {
c16d001b 240 return -EINVAL;
c0640304 241 }
c16d001b 242
4ea5081c
WS
243 if (amdgpu_sriov_vf(smc->adev) && !mapping.valid_in_vf)
244 return -EACCES;
245
7e01a2ec 246 return mapping.map_to;
b3490673
HR
247}
248
0de94acf
HR
249static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
250{
7e01a2ec
EQ
251 struct smu_11_0_cmn2aisc_mapping mapping;
252
0de94acf
HR
253 if (index >= SMU_CLK_COUNT)
254 return -EINVAL;
255
7e01a2ec 256 mapping = navi10_clk_map[index];
c0640304 257 if (!(mapping.valid_mapping)) {
0de94acf 258 return -EINVAL;
c0640304 259 }
0de94acf 260
7e01a2ec 261 return mapping.map_to;
0de94acf
HR
262}
263
ffcb08df
HR
264static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
265{
7e01a2ec
EQ
266 struct smu_11_0_cmn2aisc_mapping mapping;
267
ffcb08df
HR
268 if (index >= SMU_FEATURE_COUNT)
269 return -EINVAL;
270
7e01a2ec 271 mapping = navi10_feature_mask_map[index];
c0640304 272 if (!(mapping.valid_mapping)) {
ffcb08df 273 return -EINVAL;
c0640304 274 }
ffcb08df 275
7e01a2ec 276 return mapping.map_to;
ffcb08df
HR
277}
278
2436911b
HR
279static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
280{
7e01a2ec
EQ
281 struct smu_11_0_cmn2aisc_mapping mapping;
282
2436911b
HR
283 if (index >= SMU_TABLE_COUNT)
284 return -EINVAL;
285
7e01a2ec 286 mapping = navi10_table_map[index];
c0640304 287 if (!(mapping.valid_mapping)) {
2436911b 288 return -EINVAL;
c0640304 289 }
2436911b 290
7e01a2ec 291 return mapping.map_to;
2436911b
HR
292}
293
8890fe5f
HR
294static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
295{
7e01a2ec
EQ
296 struct smu_11_0_cmn2aisc_mapping mapping;
297
8890fe5f
HR
298 if (index >= SMU_POWER_SOURCE_COUNT)
299 return -EINVAL;
300
7e01a2ec 301 mapping = navi10_pwr_src_map[index];
c0640304 302 if (!(mapping.valid_mapping)) {
8890fe5f 303 return -EINVAL;
c0640304 304 }
8890fe5f 305
7e01a2ec 306 return mapping.map_to;
8890fe5f
HR
307}
308
6c6187ec
KW
309
310static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
311{
7e01a2ec
EQ
312 struct smu_11_0_cmn2aisc_mapping mapping;
313
6c6187ec
KW
314 if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
315 return -EINVAL;
316
7e01a2ec 317 mapping = navi10_workload_map[profile];
c0640304 318 if (!(mapping.valid_mapping)) {
7e01a2ec 319 return -EINVAL;
c0640304 320 }
6c6187ec 321
7e01a2ec 322 return mapping.map_to;
6c6187ec
KW
323}
324
fc419158
TZ
325static bool is_asic_secure(struct smu_context *smu)
326{
327 struct amdgpu_device *adev = smu->adev;
328 bool is_secure = true;
329 uint32_t mp0_fw_intf;
330
331 mp0_fw_intf = RREG32_PCIE(MP0_Public |
332 (smnMP0_FW_INTF & 0xffffffff));
333
334 if (!(mp0_fw_intf & (1 << 19)))
335 is_secure = false;
336
337 return is_secure;
338}
339
b3490673 340static int
74c958a3 341navi10_get_allowed_feature_mask(struct smu_context *smu,
b3490673
HR
342 uint32_t *feature_mask, uint32_t num)
343{
9e040216
KF
344 struct amdgpu_device *adev = smu->adev;
345
b3490673
HR
346 if (num > 2)
347 return -EINVAL;
348
74c958a3
KW
349 memset(feature_mask, 0, sizeof(uint32_t) * num);
350
77ee9caf 351 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
74c958a3 352 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
74c958a3 353 | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
d7a8efa5 354 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
74c958a3
KW
355 | FEATURE_MASK(FEATURE_PPT_BIT)
356 | FEATURE_MASK(FEATURE_TDC_BIT)
357 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
c1972a56 358 | FEATURE_MASK(FEATURE_APCC_PLUS_BIT)
74c958a3
KW
359 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
360 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
361 | FEATURE_MASK(FEATURE_THERMAL_BIT)
362 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
c1972a56 363 | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
3a3c51dd 364 | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
d8ceb192 365 | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
7c6fe84c 366 | FEATURE_MASK(FEATURE_BACO_BIT)
597292eb
KF
367 | FEATURE_MASK(FEATURE_GFX_SS_BIT)
368 | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
c1972a56
XY
369 | FEATURE_MASK(FEATURE_FW_CTF_BIT)
370 | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT);
8c3b2d1b 371
bc7ef865
AD
372 if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
373 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
374
375 if (adev->pm.pp_feature & PP_SCLK_DPM_MASK)
376 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
377
378 if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
379 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
380
381 if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
382 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT);
383
a39bf398
KW
384 if (adev->pm.pp_feature & PP_MCLK_DPM_MASK)
385 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
386 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
387 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
388
bc7ef865
AD
389 if (adev->pm.pp_feature & PP_ULV_MASK)
390 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
391
392 if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
393 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
394
bb3d7d32 395 if (adev->pm.pp_feature & PP_GFXOFF_MASK)
597292eb 396 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
9e040216 397
c12d410f
HR
398 if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
399 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
400
a201b6ac
HR
401 if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
402 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
403
c4b76d23 404 if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
43717ff6
LL
405 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT);
406
407 if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG)
408 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT);
c4b76d23 409
f5cdd2bd
AD
410 if (smu->dc_controlled_by_gpio)
411 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT);
412
c877dff7
TZ
413 /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */
414 if (is_asic_secure(smu)) {
415 /* only for navi10 A0 */
416 if ((adev->asic_type == CHIP_NAVI10) &&
417 (adev->rev_id == 0)) {
418 *(uint64_t *)feature_mask &=
eefa5e2b
KW
419 ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
420 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
421 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT));
c877dff7
TZ
422 *(uint64_t *)feature_mask &=
423 ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
424 }
425 }
426
b3490673
HR
427 return 0;
428}
429
430static int navi10_check_powerplay_table(struct smu_context *smu)
431{
4a13b4ce
EQ
432 struct smu_table_context *table_context = &smu->smu_table;
433 struct smu_11_0_powerplay_table *powerplay_table =
434 table_context->power_play_table;
435 struct smu_baco_context *smu_baco = &smu->smu_baco;
436
437 if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC)
438 smu->dc_controlled_by_gpio = true;
439
440 mutex_lock(&smu_baco->mutex);
441 if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
442 powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO)
443 smu_baco->platform_support = true;
444 mutex_unlock(&smu_baco->mutex);
445
446 table_context->thermal_controller_type =
447 powerplay_table->thermal_controller_type;
448
449 /*
450 * Instead of having its own buffer space and get overdrive_table copied,
451 * smu->od_settings just points to the actual overdrive_table
452 */
453 smu->od_settings = &powerplay_table->overdrive_table;
454
b3490673
HR
455 return 0;
456}
457
458static int navi10_append_powerplay_table(struct smu_context *smu)
459{
9e040216 460 struct amdgpu_device *adev = smu->adev;
b3490673
HR
461 struct smu_table_context *table_context = &smu->smu_table;
462 PPTable_t *smc_pptable = table_context->driver_pptable;
463 struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
02c0bb4e 464 struct atom_smc_dpm_info_v4_7 *smc_dpm_table_v4_7;
b3490673
HR
465 int index, ret;
466
467 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
468 smc_dpm_info);
469
470 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
471 (uint8_t **)&smc_dpm_table);
472 if (ret)
473 return ret;
474
d9811cfc 475 dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
02c0bb4e
EQ
476 smc_dpm_table->table_header.format_revision,
477 smc_dpm_table->table_header.content_revision);
478
479 if (smc_dpm_table->table_header.format_revision != 4) {
d9811cfc 480 dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n");
02c0bb4e
EQ
481 return -EINVAL;
482 }
483
484 switch (smc_dpm_table->table_header.content_revision) {
485 case 5: /* nv10 and nv14 */
486 memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers,
487 sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header));
488 break;
489 case 7: /* nv12 */
490 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
491 (uint8_t **)&smc_dpm_table_v4_7);
492 if (ret)
493 return ret;
494 memcpy(smc_pptable->I2cControllers, smc_dpm_table_v4_7->I2cControllers,
495 sizeof(*smc_dpm_table_v4_7) - sizeof(smc_dpm_table_v4_7->table_header));
496 break;
497 default:
d9811cfc 498 dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n",
02c0bb4e
EQ
499 smc_dpm_table->table_header.content_revision);
500 return -EINVAL;
501 }
b3490673 502
2a8bfa13 503 if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
2a8bfa13
JX
504 /* TODO: remove it once SMU fw fix it */
505 smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
506 }
507
b3490673
HR
508 return 0;
509}
510
511static int navi10_store_powerplay_table(struct smu_context *smu)
512{
b3490673 513 struct smu_table_context *table_context = &smu->smu_table;
4a13b4ce
EQ
514 struct smu_11_0_powerplay_table *powerplay_table =
515 table_context->power_play_table;
b3490673
HR
516
517 memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
518 sizeof(PPTable_t));
519
4a13b4ce
EQ
520 return 0;
521}
5e6d2665 522
4a13b4ce
EQ
523static int navi10_setup_pptable(struct smu_context *smu)
524{
525 int ret = 0;
f5cdd2bd 526
4a13b4ce
EQ
527 ret = smu_v11_0_setup_pptable(smu);
528 if (ret)
529 return ret;
767acabd 530
4a13b4ce
EQ
531 ret = navi10_store_powerplay_table(smu);
532 if (ret)
533 return ret;
534
535 ret = navi10_append_powerplay_table(smu);
536 if (ret)
537 return ret;
538
539 ret = navi10_check_powerplay_table(smu);
540 if (ret)
541 return ret;
542
543 return ret;
b3490673
HR
544}
545
62b9a88c 546static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
22c9c6ca 547{
b94afb61
KW
548 struct smu_table_context *smu_table = &smu->smu_table;
549
22c9c6ca
HR
550 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
551 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
552 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
553 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
554 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
555 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
556 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
557 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
558 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
559 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
560 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
561 sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
562 AMDGPU_GEM_DOMAIN_VRAM);
9634de27 563
b94afb61
KW
564 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
565 if (!smu_table->metrics_table)
566 return -ENOMEM;
567 smu_table->metrics_time = 0;
568
9fa1ed5b
EQ
569 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
570 if (!smu_table->watermarks_table)
571 return -ENOMEM;
572
9634de27 573 return 0;
22c9c6ca
HR
574}
575
cf24dd27
EQ
576static int navi10_get_smu_metrics_data(struct smu_context *smu,
577 MetricsMember_t member,
578 uint32_t *value)
b94afb61
KW
579{
580 struct smu_table_context *smu_table= &smu->smu_table;
cf24dd27 581 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
b94afb61
KW
582 int ret = 0;
583
885d3865 584 mutex_lock(&smu->metrics_lock);
cf24dd27 585 if (!smu_table->metrics_time ||
df06583d 586 time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) {
cf24dd27
EQ
587 ret = smu_update_table(smu,
588 SMU_TABLE_SMU_METRICS,
589 0,
590 smu_table->metrics_table,
591 false);
b94afb61 592 if (ret) {
d9811cfc 593 dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n");
885d3865 594 mutex_unlock(&smu->metrics_lock);
b94afb61
KW
595 return ret;
596 }
597 smu_table->metrics_time = jiffies;
598 }
599
cf24dd27
EQ
600 switch (member) {
601 case METRICS_CURR_GFXCLK:
602 *value = metrics->CurrClock[PPCLK_GFXCLK];
603 break;
604 case METRICS_CURR_SOCCLK:
605 *value = metrics->CurrClock[PPCLK_SOCCLK];
606 break;
607 case METRICS_CURR_UCLK:
608 *value = metrics->CurrClock[PPCLK_UCLK];
609 break;
610 case METRICS_CURR_VCLK:
611 *value = metrics->CurrClock[PPCLK_VCLK];
612 break;
613 case METRICS_CURR_DCLK:
614 *value = metrics->CurrClock[PPCLK_DCLK];
615 break;
9d09fa6f
ND
616 case METRICS_CURR_DCEFCLK:
617 *value = metrics->CurrClock[PPCLK_DCEFCLK];
618 break;
cf24dd27
EQ
619 case METRICS_AVERAGE_GFXCLK:
620 *value = metrics->AverageGfxclkFrequency;
621 break;
622 case METRICS_AVERAGE_SOCCLK:
623 *value = metrics->AverageSocclkFrequency;
624 break;
625 case METRICS_AVERAGE_UCLK:
626 *value = metrics->AverageUclkFrequency;
627 break;
628 case METRICS_AVERAGE_GFXACTIVITY:
629 *value = metrics->AverageGfxActivity;
630 break;
631 case METRICS_AVERAGE_MEMACTIVITY:
632 *value = metrics->AverageUclkActivity;
633 break;
634 case METRICS_AVERAGE_SOCKETPOWER:
635 *value = metrics->AverageSocketPower << 8;
636 break;
637 case METRICS_TEMPERATURE_EDGE:
638 *value = metrics->TemperatureEdge *
639 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
640 break;
641 case METRICS_TEMPERATURE_HOTSPOT:
642 *value = metrics->TemperatureHotspot *
643 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
644 break;
645 case METRICS_TEMPERATURE_MEM:
646 *value = metrics->TemperatureMem *
647 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
648 break;
649 case METRICS_TEMPERATURE_VRGFX:
650 *value = metrics->TemperatureVrGfx *
651 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
652 break;
653 case METRICS_TEMPERATURE_VRSOC:
654 *value = metrics->TemperatureVrSoc *
655 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
656 break;
657 case METRICS_THROTTLER_STATUS:
658 *value = metrics->ThrottlerStatus;
659 break;
660 case METRICS_CURR_FANSPEED:
661 *value = metrics->CurrFanSpeed;
662 break;
663 default:
664 *value = UINT_MAX;
665 break;
666 }
667
885d3865 668 mutex_unlock(&smu->metrics_lock);
b94afb61
KW
669
670 return ret;
671}
672
b3490673
HR
673static int navi10_allocate_dpm_context(struct smu_context *smu)
674{
675 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
676
677 if (smu_dpm->dpm_context)
678 return -EINVAL;
679
680 smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
681 GFP_KERNEL);
682 if (!smu_dpm->dpm_context)
683 return -ENOMEM;
684
685 smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
686
687 return 0;
688}
689
690static int navi10_set_default_dpm_table(struct smu_context *smu)
691{
3afb244b
EQ
692 struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
693 PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
694 struct smu_11_0_dpm_table *dpm_table;
695 int ret = 0;
b3490673 696
3afb244b
EQ
697 /* socclk dpm table setup */
698 dpm_table = &dpm_context->dpm_tables.soc_table;
699 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
700 ret = smu_v11_0_set_single_dpm_table(smu,
701 SMU_SOCCLK,
702 dpm_table);
703 if (ret)
704 return ret;
705 dpm_table->is_fine_grained =
706 !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete;
707 } else {
708 dpm_table->count = 1;
709 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
710 dpm_table->dpm_levels[0].enabled = true;
711 dpm_table->min = dpm_table->dpm_levels[0].value;
712 dpm_table->max = dpm_table->dpm_levels[0].value;
713 }
b3490673 714
3afb244b
EQ
715 /* gfxclk dpm table setup */
716 dpm_table = &dpm_context->dpm_tables.gfx_table;
717 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
718 ret = smu_v11_0_set_single_dpm_table(smu,
719 SMU_GFXCLK,
720 dpm_table);
721 if (ret)
722 return ret;
723 dpm_table->is_fine_grained =
724 !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete;
725 } else {
726 dpm_table->count = 1;
727 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
728 dpm_table->dpm_levels[0].enabled = true;
729 dpm_table->min = dpm_table->dpm_levels[0].value;
730 dpm_table->max = dpm_table->dpm_levels[0].value;
731 }
b3490673 732
3afb244b
EQ
733 /* uclk dpm table setup */
734 dpm_table = &dpm_context->dpm_tables.uclk_table;
735 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
736 ret = smu_v11_0_set_single_dpm_table(smu,
737 SMU_UCLK,
738 dpm_table);
739 if (ret)
740 return ret;
741 dpm_table->is_fine_grained =
742 !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete;
743 } else {
744 dpm_table->count = 1;
745 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
746 dpm_table->dpm_levels[0].enabled = true;
747 dpm_table->min = dpm_table->dpm_levels[0].value;
748 dpm_table->max = dpm_table->dpm_levels[0].value;
749 }
b3490673 750
3afb244b
EQ
751 /* vclk dpm table setup */
752 dpm_table = &dpm_context->dpm_tables.vclk_table;
753 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
754 ret = smu_v11_0_set_single_dpm_table(smu,
755 SMU_VCLK,
756 dpm_table);
757 if (ret)
758 return ret;
759 dpm_table->is_fine_grained =
760 !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete;
761 } else {
762 dpm_table->count = 1;
763 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
764 dpm_table->dpm_levels[0].enabled = true;
765 dpm_table->min = dpm_table->dpm_levels[0].value;
766 dpm_table->max = dpm_table->dpm_levels[0].value;
767 }
b3490673 768
3afb244b
EQ
769 /* dclk dpm table setup */
770 dpm_table = &dpm_context->dpm_tables.dclk_table;
771 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
772 ret = smu_v11_0_set_single_dpm_table(smu,
773 SMU_DCLK,
774 dpm_table);
775 if (ret)
776 return ret;
777 dpm_table->is_fine_grained =
778 !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete;
779 } else {
780 dpm_table->count = 1;
781 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
782 dpm_table->dpm_levels[0].enabled = true;
783 dpm_table->min = dpm_table->dpm_levels[0].value;
784 dpm_table->max = dpm_table->dpm_levels[0].value;
785 }
b3490673 786
3afb244b
EQ
787 /* dcefclk dpm table setup */
788 dpm_table = &dpm_context->dpm_tables.dcef_table;
789 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
790 ret = smu_v11_0_set_single_dpm_table(smu,
791 SMU_DCEFCLK,
792 dpm_table);
793 if (ret)
794 return ret;
795 dpm_table->is_fine_grained =
796 !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete;
797 } else {
798 dpm_table->count = 1;
799 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
800 dpm_table->dpm_levels[0].enabled = true;
801 dpm_table->min = dpm_table->dpm_levels[0].value;
802 dpm_table->max = dpm_table->dpm_levels[0].value;
803 }
b3490673 804
3afb244b
EQ
805 /* pixelclk dpm table setup */
806 dpm_table = &dpm_context->dpm_tables.pixel_table;
807 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
808 ret = smu_v11_0_set_single_dpm_table(smu,
809 SMU_PIXCLK,
810 dpm_table);
811 if (ret)
812 return ret;
813 dpm_table->is_fine_grained =
814 !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete;
815 } else {
816 dpm_table->count = 1;
817 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
818 dpm_table->dpm_levels[0].enabled = true;
819 dpm_table->min = dpm_table->dpm_levels[0].value;
820 dpm_table->max = dpm_table->dpm_levels[0].value;
821 }
b3490673 822
3afb244b
EQ
823 /* displayclk dpm table setup */
824 dpm_table = &dpm_context->dpm_tables.display_table;
825 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
826 ret = smu_v11_0_set_single_dpm_table(smu,
827 SMU_DISPCLK,
828 dpm_table);
829 if (ret)
830 return ret;
831 dpm_table->is_fine_grained =
832 !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete;
833 } else {
834 dpm_table->count = 1;
835 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
836 dpm_table->dpm_levels[0].enabled = true;
837 dpm_table->min = dpm_table->dpm_levels[0].value;
838 dpm_table->max = dpm_table->dpm_levels[0].value;
839 }
b3490673 840
3afb244b
EQ
841 /* phyclk dpm table setup */
842 dpm_table = &dpm_context->dpm_tables.phy_table;
843 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
844 ret = smu_v11_0_set_single_dpm_table(smu,
845 SMU_PHYCLK,
846 dpm_table);
847 if (ret)
848 return ret;
849 dpm_table->is_fine_grained =
850 !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete;
851 } else {
852 dpm_table->count = 1;
853 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
854 dpm_table->dpm_levels[0].enabled = true;
855 dpm_table->min = dpm_table->dpm_levels[0].value;
856 dpm_table->max = dpm_table->dpm_levels[0].value;
857 }
b3490673
HR
858
859 return 0;
860}
861
f6b4b4a1 862static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
a8179d62 863{
706e5082
EQ
864 struct smu_power_context *smu_power = &smu->smu_power;
865 struct smu_power_gate *power_gate = &smu_power->power_gate;
a8179d62 866 int ret = 0;
5fa790f6
EQ
867
868 if (enable) {
706e5082
EQ
869 /* vcn dpm on is a prerequisite for vcn power gate messages */
870 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
1c58267c 871 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL);
706e5082
EQ
872 if (ret)
873 return ret;
874 }
875 power_gate->vcn_gated = false;
a8179d62 876 } else {
706e5082 877 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
1c58267c 878 ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL);
706e5082
EQ
879 if (ret)
880 return ret;
881 }
882 power_gate->vcn_gated = true;
a8179d62
KF
883 }
884
5fa790f6 885 return ret;
a8179d62
KF
886}
887
43717ff6
LL
888static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
889{
890 struct smu_power_context *smu_power = &smu->smu_power;
891 struct smu_power_gate *power_gate = &smu_power->power_gate;
892 int ret = 0;
893
894 if (enable) {
895 if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
1c58267c 896 ret = smu_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL);
43717ff6
LL
897 if (ret)
898 return ret;
899 }
900 power_gate->jpeg_gated = false;
901 } else {
902 if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
1c58267c 903 ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL);
43717ff6
LL
904 if (ret)
905 return ret;
906 }
907 power_gate->jpeg_gated = true;
908 }
909
910 return ret;
911}
912
98e1a543
KW
913static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
914 enum smu_clk_type clk_type,
915 uint32_t *value)
916{
cf24dd27
EQ
917 MetricsMember_t member_type;
918 int clk_id = 0;
98e1a543
KW
919
920 clk_id = smu_clk_get_index(smu, clk_type);
921 if (clk_id < 0)
922 return clk_id;
923
cf24dd27
EQ
924 switch (clk_id) {
925 case PPCLK_GFXCLK:
926 member_type = METRICS_CURR_GFXCLK;
927 break;
928 case PPCLK_UCLK:
929 member_type = METRICS_CURR_UCLK;
930 break;
931 case PPCLK_SOCCLK:
932 member_type = METRICS_CURR_SOCCLK;
933 break;
934 case PPCLK_VCLK:
935 member_type = METRICS_CURR_VCLK;
936 break;
937 case PPCLK_DCLK:
938 member_type = METRICS_CURR_DCLK;
939 break;
940 case PPCLK_DCEFCLK:
941 member_type = METRICS_CURR_DCEFCLK;
942 break;
943 default:
944 return -EINVAL;
945 }
98e1a543 946
cf24dd27
EQ
947 return navi10_get_smu_metrics_data(smu,
948 member_type,
949 value);
98e1a543
KW
950}
951
c49b1b59
KW
952static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
953{
954 PPTable_t *pptable = smu->smu_table.driver_pptable;
955 DpmDescriptor_t *dpm_desc = NULL;
956 uint32_t clk_index = 0;
957
958 clk_index = smu_clk_get_index(smu, clk_type);
959 dpm_desc = &pptable->DpmDescriptor[clk_index];
960
961 /* 0 - Fine grained DPM, 1 - Discrete DPM */
962 return dpm_desc->SnapToDiscrete == 0 ? true : false;
963}
964
e33a8cfd 965static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_CAP cap)
7f3353f6 966{
e33a8cfd 967 return od_table->cap[cap];
7f3353f6
MC
968}
969
ee23a518
AD
970static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_table,
971 enum SMU_11_0_ODSETTING_ID setting,
972 uint32_t *min, uint32_t *max)
973{
974 if (min)
975 *min = od_table->min[setting];
976 if (max)
977 *max = od_table->max[setting];
978}
7f3353f6 979
b1e7e224
KW
980static int navi10_print_clk_levels(struct smu_context *smu,
981 enum smu_clk_type clk_type, char *buf)
982{
7f3353f6 983 uint16_t *curve_settings;
b1e7e224
KW
984 int i, size = 0, ret = 0;
985 uint32_t cur_value = 0, value = 0, count = 0;
c49b1b59
KW
986 uint32_t freq_values[3] = {0};
987 uint32_t mark_index = 0;
7f3353f6 988 struct smu_table_context *table_context = &smu->smu_table;
fddbfb1c
KF
989 uint32_t gen_speed, lane_width;
990 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
991 struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
992 struct amdgpu_device *adev = smu->adev;
993 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
994 OverDriveTable_t *od_table =
995 (OverDriveTable_t *)table_context->overdrive_table;
996 struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
ee23a518 997 uint32_t min_value, max_value;
b1e7e224
KW
998
999 switch (clk_type) {
1000 case SMU_GFXCLK:
1001 case SMU_SCLK:
1002 case SMU_SOCCLK:
1003 case SMU_MCLK:
1004 case SMU_UCLK:
1005 case SMU_FCLK:
1006 case SMU_DCEFCLK:
5e6dc8fe 1007 ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value);
b1e7e224
KW
1008 if (ret)
1009 return size;
c49b1b59 1010
d8d3493a 1011 ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count);
b1e7e224
KW
1012 if (ret)
1013 return size;
1014
c49b1b59
KW
1015 if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
1016 for (i = 0; i < count; i++) {
d8d3493a 1017 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value);
c49b1b59
KW
1018 if (ret)
1019 return size;
1020
1021 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
1022 cur_value == value ? "*" : "");
1023 }
1024 } else {
d8d3493a 1025 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
c49b1b59
KW
1026 if (ret)
1027 return size;
d8d3493a 1028 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
b1e7e224
KW
1029 if (ret)
1030 return size;
1031
c49b1b59
KW
1032 freq_values[1] = cur_value;
1033 mark_index = cur_value == freq_values[0] ? 0 :
1034 cur_value == freq_values[2] ? 2 : 1;
1035 if (mark_index != 1)
1036 freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
1037
1038 for (i = 0; i < 3; i++) {
1039 size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
1040 i == mark_index ? "*" : "");
1041 }
1042
b1e7e224
KW
1043 }
1044 break;
fddbfb1c
KF
1045 case SMU_PCIE:
1046 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
1047 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
1048 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
1049 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
1050 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
1051 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
1052 for (i = 0; i < NUM_LINK_LEVELS; i++)
1053 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
1054 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
1055 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
1056 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
1057 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "",
1058 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" :
1059 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" :
1060 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" :
1061 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" :
1062 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" :
1063 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "",
1064 pptable->LclkFreq[i],
1065 (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) &&
1066 (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ?
1067 "*" : "");
1068 break;
7f3353f6
MC
1069 case SMU_OD_SCLK:
1070 if (!smu->od_enabled || !od_table || !od_settings)
1071 break;
e33a8cfd 1072 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS))
7f3353f6
MC
1073 break;
1074 size += sprintf(buf + size, "OD_SCLK:\n");
1075 size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
1076 break;
1077 case SMU_OD_MCLK:
1078 if (!smu->od_enabled || !od_table || !od_settings)
1079 break;
e33a8cfd 1080 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX))
7f3353f6
MC
1081 break;
1082 size += sprintf(buf + size, "OD_MCLK:\n");
45826e9c 1083 size += sprintf(buf + size, "1: %uMHz\n", od_table->UclkFmax);
7f3353f6
MC
1084 break;
1085 case SMU_OD_VDDC_CURVE:
1086 if (!smu->od_enabled || !od_table || !od_settings)
1087 break;
e33a8cfd 1088 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE))
7f3353f6
MC
1089 break;
1090 size += sprintf(buf + size, "OD_VDDC_CURVE:\n");
1091 for (i = 0; i < 3; i++) {
1092 switch (i) {
1093 case 0:
1094 curve_settings = &od_table->GfxclkFreq1;
1095 break;
1096 case 1:
1097 curve_settings = &od_table->GfxclkFreq2;
1098 break;
1099 case 2:
1100 curve_settings = &od_table->GfxclkFreq3;
1101 break;
1102 default:
1103 break;
1104 }
d818ed28 1105 size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE);
7f3353f6 1106 }
ee23a518
AD
1107 break;
1108 case SMU_OD_RANGE:
1109 if (!smu->od_enabled || !od_table || !od_settings)
1110 break;
1111 size = sprintf(buf, "%s:\n", "OD_RANGE");
1112
e33a8cfd 1113 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
ee23a518
AD
1114 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN,
1115 &min_value, NULL);
1116 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX,
1117 NULL, &max_value);
1118 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
1119 min_value, max_value);
1120 }
1121
e33a8cfd 1122 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
ee23a518
AD
1123 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX,
1124 &min_value, &max_value);
1125 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
1126 min_value, max_value);
1127 }
1128
e33a8cfd 1129 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
ee23a518
AD
1130 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,
1131 &min_value, &max_value);
1132 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1133 min_value, max_value);
1134 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,
1135 &min_value, &max_value);
1136 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1137 min_value, max_value);
1138 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,
1139 &min_value, &max_value);
1140 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1141 min_value, max_value);
1142 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,
1143 &min_value, &max_value);
1144 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1145 min_value, max_value);
1146 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,
1147 &min_value, &max_value);
1148 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1149 min_value, max_value);
1150 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,
1151 &min_value, &max_value);
1152 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1153 min_value, max_value);
1154 }
1155
7f3353f6 1156 break;
b1e7e224
KW
1157 default:
1158 break;
1159 }
1160
1161 return size;
1162}
1163
db439ca2
KW
1164static int navi10_force_clk_levels(struct smu_context *smu,
1165 enum smu_clk_type clk_type, uint32_t mask)
1166{
1167
1168 int ret = 0, size = 0;
1169 uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
1170
1171 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1172 soft_max_level = mask ? (fls(mask) - 1) : 0;
1173
1174 switch (clk_type) {
1175 case SMU_GFXCLK:
c0b9d6d2 1176 case SMU_SCLK:
db439ca2
KW
1177 case SMU_SOCCLK:
1178 case SMU_MCLK:
1179 case SMU_UCLK:
1180 case SMU_DCEFCLK:
1181 case SMU_FCLK:
09ba2e7d
EQ
1182 /* There is only 2 levels for fine grained DPM */
1183 if (navi10_is_support_fine_grained_dpm(smu, clk_type)) {
1184 soft_max_level = (soft_max_level >= 1 ? 1 : 0);
1185 soft_min_level = (soft_min_level >= 1 ? 1 : 0);
1186 }
1187
d8d3493a 1188 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
db439ca2
KW
1189 if (ret)
1190 return size;
1191
d8d3493a 1192 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
db439ca2
KW
1193 if (ret)
1194 return size;
1195
c98f31d1 1196 ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
db439ca2
KW
1197 if (ret)
1198 return size;
1199 break;
1200 default:
1201 break;
1202 }
1203
1204 return size;
1205}
1206
fa51bfc2
KW
1207static int navi10_populate_umd_state_clk(struct smu_context *smu)
1208{
62cc9dd1
EQ
1209 struct smu_11_0_dpm_context *dpm_context =
1210 smu->smu_dpm.dpm_context;
1211 struct smu_11_0_dpm_table *gfx_table =
1212 &dpm_context->dpm_tables.gfx_table;
1213 struct smu_11_0_dpm_table *mem_table =
1214 &dpm_context->dpm_tables.uclk_table;
1215 struct smu_11_0_dpm_table *soc_table =
1216 &dpm_context->dpm_tables.soc_table;
1217 struct smu_umd_pstate_table *pstate_table =
1218 &smu->pstate_table;
1219 struct amdgpu_device *adev = smu->adev;
1220 uint32_t sclk_freq;
1221
1222 pstate_table->gfxclk_pstate.min = gfx_table->min;
1223 switch (adev->asic_type) {
1224 case CHIP_NAVI10:
1225 switch (adev->pdev->revision) {
1226 case 0xf0: /* XTX */
1227 case 0xc0:
1228 sclk_freq = NAVI10_PEAK_SCLK_XTX;
1229 break;
1230 case 0xf1: /* XT */
1231 case 0xc1:
1232 sclk_freq = NAVI10_PEAK_SCLK_XT;
1233 break;
1234 default: /* XL */
1235 sclk_freq = NAVI10_PEAK_SCLK_XL;
1236 break;
1237 }
1238 break;
1239 case CHIP_NAVI14:
1240 switch (adev->pdev->revision) {
1241 case 0xc7: /* XT */
1242 case 0xf4:
1243 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK;
1244 break;
1245 case 0xc1: /* XTM */
1246 case 0xf2:
1247 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK;
1248 break;
1249 case 0xc3: /* XLM */
1250 case 0xf3:
1251 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
1252 break;
1253 case 0xc5: /* XTX */
1254 case 0xf6:
1255 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
1256 break;
1257 default: /* XL */
1258 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK;
1259 break;
1260 }
1261 break;
1262 case CHIP_NAVI12:
1263 sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK;
1264 break;
1265 default:
1266 sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value;
1267 break;
1268 }
1269 pstate_table->gfxclk_pstate.peak = sclk_freq;
1270
1271 pstate_table->uclk_pstate.min = mem_table->min;
1272 pstate_table->uclk_pstate.peak = mem_table->max;
1273
1274 pstate_table->socclk_pstate.min = soc_table->min;
1275 pstate_table->socclk_pstate.peak = soc_table->max;
1276
1277 if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK &&
1278 mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK &&
1279 soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) {
1280 pstate_table->gfxclk_pstate.standard =
1281 NAVI10_UMD_PSTATE_PROFILING_GFXCLK;
1282 pstate_table->uclk_pstate.standard =
1283 NAVI10_UMD_PSTATE_PROFILING_MEMCLK;
1284 pstate_table->socclk_pstate.standard =
1285 NAVI10_UMD_PSTATE_PROFILING_SOCCLK;
1286 } else {
1287 pstate_table->gfxclk_pstate.standard =
1288 pstate_table->gfxclk_pstate.min;
1289 pstate_table->uclk_pstate.standard =
1290 pstate_table->uclk_pstate.min;
1291 pstate_table->socclk_pstate.standard =
1292 pstate_table->socclk_pstate.min;
1293 }
64974ab2 1294
62cc9dd1 1295 return 0;
fa51bfc2
KW
1296}
1297
a43913ea
KW
1298static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
1299 enum smu_clk_type clk_type,
1300 struct pp_clock_levels_with_latency *clocks)
1301{
1302 int ret = 0, i = 0;
1303 uint32_t level_count = 0, freq = 0;
1304
1305 switch (clk_type) {
1306 case SMU_GFXCLK:
1307 case SMU_DCEFCLK:
1308 case SMU_SOCCLK:
e0d5322c
AD
1309 case SMU_MCLK:
1310 case SMU_UCLK:
d8d3493a 1311 ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count);
a43913ea
KW
1312 if (ret)
1313 return ret;
1314
1315 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
1316 clocks->num_levels = level_count;
1317
1318 for (i = 0; i < level_count; i++) {
d8d3493a 1319 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq);
a43913ea
KW
1320 if (ret)
1321 return ret;
1322
1323 clocks->data[i].clocks_in_khz = freq * 1000;
1324 clocks->data[i].latency_in_us = 0;
1325 }
1326 break;
1327 default:
1328 break;
1329 }
1330
1331 return ret;
1332}
1333
28430544
KW
1334static int navi10_pre_display_config_changed(struct smu_context *smu)
1335{
1336 int ret = 0;
1337 uint32_t max_freq = 0;
1338
1c58267c 1339 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL);
28430544
KW
1340 if (ret)
1341 return ret;
1342
1343 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
e5ef784b 1344 ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq);
28430544
KW
1345 if (ret)
1346 return ret;
661b94f5 1347 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq);
28430544
KW
1348 if (ret)
1349 return ret;
1350 }
1351
1352 return ret;
1353}
1354
0a6430da
KW
1355static int navi10_display_config_changed(struct smu_context *smu)
1356{
1357 int ret = 0;
1358
0a6430da
KW
1359 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1360 smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
1361 smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
1362 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
1c58267c
MC
1363 smu->display_config->num_display,
1364 NULL);
0a6430da
KW
1365 if (ret)
1366 return ret;
1367 }
1368
1369 return ret;
1370}
50add63b 1371
077ca74e
KW
1372static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
1373{
077ca74e
KW
1374 if (!value)
1375 return -EINVAL;
1376
cf24dd27
EQ
1377 return navi10_get_smu_metrics_data(smu,
1378 METRICS_AVERAGE_SOCKETPOWER,
1379 value);
077ca74e
KW
1380}
1381
7447a23b 1382static int navi10_get_current_activity_percent(struct smu_context *smu,
7f963d9f 1383 enum amd_pp_sensors sensor,
7447a23b
KW
1384 uint32_t *value)
1385{
1386 int ret = 0;
7447a23b
KW
1387
1388 if (!value)
1389 return -EINVAL;
1390
7f963d9f
AD
1391 switch (sensor) {
1392 case AMDGPU_PP_SENSOR_GPU_LOAD:
cf24dd27
EQ
1393 ret = navi10_get_smu_metrics_data(smu,
1394 METRICS_AVERAGE_GFXACTIVITY,
1395 value);
7f963d9f
AD
1396 break;
1397 case AMDGPU_PP_SENSOR_MEM_LOAD:
cf24dd27
EQ
1398 ret = navi10_get_smu_metrics_data(smu,
1399 METRICS_AVERAGE_MEMACTIVITY,
1400 value);
7f963d9f
AD
1401 break;
1402 default:
d9811cfc 1403 dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
7f963d9f
AD
1404 return -EINVAL;
1405 }
7447a23b 1406
cf24dd27 1407 return ret;
7447a23b
KW
1408}
1409
4228b601
KW
1410static bool navi10_is_dpm_running(struct smu_context *smu)
1411{
1412 int ret = 0;
1413 uint32_t feature_mask[2];
1414 unsigned long feature_enabled;
1415 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
1416 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
1417 ((uint64_t)feature_mask[1] << 32));
1418 return !!(feature_enabled & SMC_DPM_FEATURE);
1419}
1420
95ccc155
AD
1421static int navi10_get_fan_speed_rpm(struct smu_context *smu,
1422 uint32_t *speed)
ab43c4bf 1423{
95ccc155 1424 if (!speed)
ab43c4bf
KW
1425 return -EINVAL;
1426
cf24dd27
EQ
1427 return navi10_get_smu_metrics_data(smu,
1428 METRICS_CURR_FANSPEED,
1429 speed);
ab43c4bf
KW
1430}
1431
2d589a5b
KW
1432static int navi10_get_fan_speed_percent(struct smu_context *smu,
1433 uint32_t *speed)
1434{
1435 int ret = 0;
1436 uint32_t percent = 0;
95ccc155 1437 uint32_t current_rpm;
2d589a5b
KW
1438 PPTable_t *pptable = smu->smu_table.driver_pptable;
1439
95ccc155 1440 ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
2d589a5b
KW
1441 if (ret)
1442 return ret;
1443
1444 percent = current_rpm * 100 / pptable->FanMaximumRpm;
1445 *speed = percent > 100 ? 100 : percent;
1446
1447 return ret;
1448}
1449
b45dc20b
KW
1450static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1451{
1452 DpmActivityMonitorCoeffInt_t activity_monitor;
1453 uint32_t i, size = 0;
c0640304 1454 int16_t workload_type = 0;
b45dc20b
KW
1455 static const char *profile_name[] = {
1456 "BOOTUP_DEFAULT",
1457 "3D_FULL_SCREEN",
1458 "POWER_SAVING",
1459 "VIDEO",
1460 "VR",
1461 "COMPUTE",
1462 "CUSTOM"};
1463 static const char *title[] = {
1464 "PROFILE_INDEX(NAME)",
1465 "CLOCK_TYPE(NAME)",
1466 "FPS",
1467 "MinFreqType",
1468 "MinActiveFreqType",
1469 "MinActiveFreq",
1470 "BoosterFreqType",
1471 "BoosterFreq",
1472 "PD_Data_limit_c",
1473 "PD_Data_error_coeff",
1474 "PD_Data_error_rate_coeff"};
1475 int result = 0;
1476
1477 if (!buf)
1478 return -EINVAL;
1479
1480 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1481 title[0], title[1], title[2], title[3], title[4], title[5],
1482 title[6], title[7], title[8], title[9], title[10]);
1483
1484 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1485 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1486 workload_type = smu_workload_get_type(smu, i);
c0640304
EQ
1487 if (workload_type < 0)
1488 return -EINVAL;
1489
b45dc20b 1490 result = smu_update_table(smu,
0d9d78b5 1491 SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
b45dc20b
KW
1492 (void *)(&activity_monitor), false);
1493 if (result) {
d9811cfc 1494 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
b45dc20b
KW
1495 return result;
1496 }
1497
1498 size += sprintf(buf + size, "%2d %14s%s:\n",
1499 i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1500
1501 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1502 " ",
1503 0,
1504 "GFXCLK",
1505 activity_monitor.Gfx_FPS,
1506 activity_monitor.Gfx_MinFreqStep,
1507 activity_monitor.Gfx_MinActiveFreqType,
1508 activity_monitor.Gfx_MinActiveFreq,
1509 activity_monitor.Gfx_BoosterFreqType,
1510 activity_monitor.Gfx_BoosterFreq,
1511 activity_monitor.Gfx_PD_Data_limit_c,
1512 activity_monitor.Gfx_PD_Data_error_coeff,
1513 activity_monitor.Gfx_PD_Data_error_rate_coeff);
1514
1515 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1516 " ",
1517 1,
1518 "SOCCLK",
1519 activity_monitor.Soc_FPS,
1520 activity_monitor.Soc_MinFreqStep,
1521 activity_monitor.Soc_MinActiveFreqType,
1522 activity_monitor.Soc_MinActiveFreq,
1523 activity_monitor.Soc_BoosterFreqType,
1524 activity_monitor.Soc_BoosterFreq,
1525 activity_monitor.Soc_PD_Data_limit_c,
1526 activity_monitor.Soc_PD_Data_error_coeff,
1527 activity_monitor.Soc_PD_Data_error_rate_coeff);
1528
1529 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1530 " ",
1531 2,
1532 "MEMLK",
1533 activity_monitor.Mem_FPS,
1534 activity_monitor.Mem_MinFreqStep,
1535 activity_monitor.Mem_MinActiveFreqType,
1536 activity_monitor.Mem_MinActiveFreq,
1537 activity_monitor.Mem_BoosterFreqType,
1538 activity_monitor.Mem_BoosterFreq,
1539 activity_monitor.Mem_PD_Data_limit_c,
1540 activity_monitor.Mem_PD_Data_error_coeff,
1541 activity_monitor.Mem_PD_Data_error_rate_coeff);
1542 }
1543
1544 return size;
1545}
1546
1547static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1548{
1549 DpmActivityMonitorCoeffInt_t activity_monitor;
1550 int workload_type, ret = 0;
1551
1552 smu->power_profile_mode = input[size];
1553
1554 if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
d9811cfc 1555 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
b45dc20b
KW
1556 return -EINVAL;
1557 }
1558
1559 if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
b45dc20b
KW
1560
1561 ret = smu_update_table(smu,
0d9d78b5 1562 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
b45dc20b
KW
1563 (void *)(&activity_monitor), false);
1564 if (ret) {
d9811cfc 1565 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
b45dc20b
KW
1566 return ret;
1567 }
1568
1569 switch (input[0]) {
1570 case 0: /* Gfxclk */
1571 activity_monitor.Gfx_FPS = input[1];
1572 activity_monitor.Gfx_MinFreqStep = input[2];
1573 activity_monitor.Gfx_MinActiveFreqType = input[3];
1574 activity_monitor.Gfx_MinActiveFreq = input[4];
1575 activity_monitor.Gfx_BoosterFreqType = input[5];
1576 activity_monitor.Gfx_BoosterFreq = input[6];
1577 activity_monitor.Gfx_PD_Data_limit_c = input[7];
1578 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1579 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1580 break;
1581 case 1: /* Socclk */
1582 activity_monitor.Soc_FPS = input[1];
1583 activity_monitor.Soc_MinFreqStep = input[2];
1584 activity_monitor.Soc_MinActiveFreqType = input[3];
1585 activity_monitor.Soc_MinActiveFreq = input[4];
1586 activity_monitor.Soc_BoosterFreqType = input[5];
1587 activity_monitor.Soc_BoosterFreq = input[6];
1588 activity_monitor.Soc_PD_Data_limit_c = input[7];
1589 activity_monitor.Soc_PD_Data_error_coeff = input[8];
1590 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1591 break;
1592 case 2: /* Memlk */
1593 activity_monitor.Mem_FPS = input[1];
1594 activity_monitor.Mem_MinFreqStep = input[2];
1595 activity_monitor.Mem_MinActiveFreqType = input[3];
1596 activity_monitor.Mem_MinActiveFreq = input[4];
1597 activity_monitor.Mem_BoosterFreqType = input[5];
1598 activity_monitor.Mem_BoosterFreq = input[6];
1599 activity_monitor.Mem_PD_Data_limit_c = input[7];
1600 activity_monitor.Mem_PD_Data_error_coeff = input[8];
1601 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1602 break;
1603 }
1604
1605 ret = smu_update_table(smu,
0d9d78b5 1606 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
b45dc20b
KW
1607 (void *)(&activity_monitor), true);
1608 if (ret) {
d9811cfc 1609 dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
b45dc20b
KW
1610 return ret;
1611 }
1612 }
1613
1614 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1615 workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
c0640304
EQ
1616 if (workload_type < 0)
1617 return -EINVAL;
b45dc20b 1618 smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1c58267c 1619 1 << workload_type, NULL);
b45dc20b
KW
1620
1621 return ret;
1622}
1623
19796597 1624static int navi10_notify_smc_display_config(struct smu_context *smu)
4f963b01
KW
1625{
1626 struct smu_clocks min_clocks = {0};
1627 struct pp_display_clock_request clock_req;
1628 int ret = 0;
1629
1630 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1631 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1632 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1633
1634 if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1635 clock_req.clock_type = amd_pp_dcef_clock;
1636 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
3697b339 1637
6c45e480 1638 ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req);
3697b339 1639 if (!ret) {
4f963b01
KW
1640 if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1641 ret = smu_send_smc_msg_with_param(smu,
1642 SMU_MSG_SetMinDeepSleepDcefclk,
1c58267c
MC
1643 min_clocks.dcef_clock_in_sr/100,
1644 NULL);
4f963b01 1645 if (ret) {
d9811cfc 1646 dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!");
4f963b01
KW
1647 return ret;
1648 }
1649 }
1650 } else {
d9811cfc 1651 dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!");
4f963b01
KW
1652 }
1653 }
1654
1655 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
661b94f5 1656 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
4f963b01 1657 if (ret) {
d9811cfc 1658 dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__);
4f963b01
KW
1659 return ret;
1660 }
1661 }
1662
1663 return 0;
1664}
1665
5bbb0994
KW
1666static int navi10_set_watermarks_table(struct smu_context *smu,
1667 void *watermarks, struct
1668 dm_pp_wm_sets_with_clock_ranges_soc15
1669 *clock_ranges)
1670{
1671 int i;
2622e2ae 1672 int ret = 0;
5bbb0994
KW
1673 Watermarks_t *table = watermarks;
1674
1675 if (!table || !clock_ranges)
1676 return -EINVAL;
1677
1678 if (clock_ranges->num_wm_dmif_sets > 4 ||
1679 clock_ranges->num_wm_mcif_sets > 4)
1680 return -EINVAL;
1681
1682 for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
1683 table->WatermarkRow[1][i].MinClock =
1684 cpu_to_le16((uint16_t)
1685 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1686 1000));
1687 table->WatermarkRow[1][i].MaxClock =
1688 cpu_to_le16((uint16_t)
1689 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1690 1000));
1691 table->WatermarkRow[1][i].MinUclk =
1692 cpu_to_le16((uint16_t)
1693 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1694 1000));
1695 table->WatermarkRow[1][i].MaxUclk =
1696 cpu_to_le16((uint16_t)
1697 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1698 1000));
1699 table->WatermarkRow[1][i].WmSetting = (uint8_t)
1700 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
1701 }
1702
1703 for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
1704 table->WatermarkRow[0][i].MinClock =
1705 cpu_to_le16((uint16_t)
1706 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1707 1000));
1708 table->WatermarkRow[0][i].MaxClock =
1709 cpu_to_le16((uint16_t)
1710 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1711 1000));
1712 table->WatermarkRow[0][i].MinUclk =
1713 cpu_to_le16((uint16_t)
1714 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1715 1000));
1716 table->WatermarkRow[0][i].MaxUclk =
1717 cpu_to_le16((uint16_t)
1718 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1719 1000));
1720 table->WatermarkRow[0][i].WmSetting = (uint8_t)
1721 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
1722 }
1723
2622e2ae
HW
1724 smu->watermarks_bitmap |= WATERMARKS_EXIST;
1725
1726 /* pass data to smu controller */
1727 if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1728 ret = smu_write_watermarks_table(smu);
1729 if (ret) {
d9811cfc 1730 dev_err(smu->adev->dev, "Failed to update WMTABLE!");
2622e2ae
HW
1731 return ret;
1732 }
1733 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1734 }
1735
5bbb0994
KW
1736 return 0;
1737}
1738
e5aa29ce
KW
1739static int navi10_thermal_get_temperature(struct smu_context *smu,
1740 enum amd_pp_sensors sensor,
1741 uint32_t *value)
1742{
e5aa29ce
KW
1743 int ret = 0;
1744
1745 if (!value)
1746 return -EINVAL;
1747
e5aa29ce
KW
1748 switch (sensor) {
1749 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
cf24dd27
EQ
1750 ret = navi10_get_smu_metrics_data(smu,
1751 METRICS_TEMPERATURE_HOTSPOT,
1752 value);
e5aa29ce
KW
1753 break;
1754 case AMDGPU_PP_SENSOR_EDGE_TEMP:
cf24dd27
EQ
1755 ret = navi10_get_smu_metrics_data(smu,
1756 METRICS_TEMPERATURE_EDGE,
1757 value);
e5aa29ce
KW
1758 break;
1759 case AMDGPU_PP_SENSOR_MEM_TEMP:
cf24dd27
EQ
1760 ret = navi10_get_smu_metrics_data(smu,
1761 METRICS_TEMPERATURE_MEM,
1762 value);
e5aa29ce
KW
1763 break;
1764 default:
d9811cfc 1765 dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
e5aa29ce
KW
1766 return -EINVAL;
1767 }
1768
cf24dd27 1769 return ret;
e5aa29ce
KW
1770}
1771
9c62f993
KW
1772static int navi10_read_sensor(struct smu_context *smu,
1773 enum amd_pp_sensors sensor,
1774 void *data, uint32_t *size)
1775{
1776 int ret = 0;
1777 struct smu_table_context *table_context = &smu->smu_table;
1778 PPTable_t *pptable = table_context->driver_pptable;
1779
9b4e63f4
KF
1780 if(!data || !size)
1781 return -EINVAL;
1782
95f71bfa 1783 mutex_lock(&smu->sensor_lock);
9c62f993
KW
1784 switch (sensor) {
1785 case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1786 *(uint32_t *)data = pptable->FanMaximumRpm;
1787 *size = 4;
1788 break;
7f963d9f 1789 case AMDGPU_PP_SENSOR_MEM_LOAD:
d573bb21 1790 case AMDGPU_PP_SENSOR_GPU_LOAD:
7f963d9f 1791 ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
d573bb21
KW
1792 *size = 4;
1793 break;
564c4c7f
KW
1794 case AMDGPU_PP_SENSOR_GPU_POWER:
1795 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1796 *size = 4;
1797 break;
e5aa29ce
KW
1798 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1799 case AMDGPU_PP_SENSOR_EDGE_TEMP:
1800 case AMDGPU_PP_SENSOR_MEM_TEMP:
1801 ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
1802 *size = 4;
1803 break;
e0f9e936
EQ
1804 case AMDGPU_PP_SENSOR_GFX_MCLK:
1805 ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
1806 *(uint32_t *)data *= 100;
1807 *size = 4;
1808 break;
1809 case AMDGPU_PP_SENSOR_GFX_SCLK:
1810 ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
1811 *(uint32_t *)data *= 100;
1812 *size = 4;
1813 break;
b2febc99
EQ
1814 case AMDGPU_PP_SENSOR_VDDGFX:
1815 ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
1816 *size = 4;
1817 break;
9c62f993 1818 default:
b2febc99
EQ
1819 ret = -EOPNOTSUPP;
1820 break;
9c62f993 1821 }
95f71bfa 1822 mutex_unlock(&smu->sensor_lock);
9c62f993
KW
1823
1824 return ret;
1825}
1826
f4b3295f 1827static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
1828{
1829 uint32_t num_discrete_levels = 0;
1830 uint16_t *dpm_levels = NULL;
1831 uint16_t i = 0;
1832 struct smu_table_context *table_context = &smu->smu_table;
1833 PPTable_t *driver_ppt = NULL;
1834
1835 if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
1836 return -EINVAL;
1837
1838 driver_ppt = table_context->driver_pptable;
1839 num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
1840 dpm_levels = driver_ppt->FreqTableUclk;
1841
1842 if (num_discrete_levels == 0 || dpm_levels == NULL)
1843 return -EINVAL;
1844
1845 *num_states = num_discrete_levels;
1846 for (i = 0; i < num_discrete_levels; i++) {
1847 /* convert to khz */
1848 *clocks_in_khz = (*dpm_levels) * 1000;
1849 clocks_in_khz++;
1850 dpm_levels++;
1851 }
1852
1853 return 0;
1854}
1855
7a816371
KW
1856static int navi10_get_thermal_temperature_range(struct smu_context *smu,
1857 struct smu_temperature_range *range)
1858{
e02e4d51
EQ
1859 struct smu_table_context *table_context = &smu->smu_table;
1860 struct smu_11_0_powerplay_table *powerplay_table =
1861 table_context->power_play_table;
cbf3f132 1862 PPTable_t *pptable = smu->smu_table.driver_pptable;
7a816371 1863
cbf3f132 1864 if (!range)
7a816371
KW
1865 return -EINVAL;
1866
0540eced
EQ
1867 memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range));
1868
cbf3f132
EQ
1869 range->max = pptable->TedgeLimit *
1870 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1871 range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
1872 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1873 range->hotspot_crit_max = pptable->ThotspotLimit *
1874 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1875 range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
1876 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1877 range->mem_crit_max = pptable->TmemLimit *
1878 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1879 range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
a056ddce 1880 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
e02e4d51 1881 range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
7a816371
KW
1882
1883 return 0;
1884}
1885
6e92e156
KF
1886static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
1887 bool disable_memory_clock_switch)
1888{
1889 int ret = 0;
1890 struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
1891 (struct smu_11_0_max_sustainable_clocks *)
1892 smu->smu_table.max_sustainable_clocks;
1893 uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
1894 uint32_t max_memory_clock = max_sustainable_clocks->uclock;
1895
1896 if(smu->disable_uclk_switch == disable_memory_clock_switch)
1897 return 0;
1898
1899 if(disable_memory_clock_switch)
661b94f5 1900 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0);
6e92e156 1901 else
661b94f5 1902 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0);
6e92e156
KF
1903
1904 if(!ret)
1905 smu->disable_uclk_switch = disable_memory_clock_switch;
1906
1907 return ret;
1908}
1909
a141b4e3 1910static int navi10_get_power_limit(struct smu_context *smu)
b4af964e 1911{
1e239fdd
EQ
1912 struct smu_11_0_powerplay_table *powerplay_table =
1913 (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
549db526 1914 struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
b4af964e 1915 PPTable_t *pptable = smu->smu_table.driver_pptable;
1e239fdd
EQ
1916 uint32_t power_limit, od_percent;
1917
1918 if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
1919 /* the last hope to figure out the ppt limit */
1920 if (!pptable) {
1921 dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
1922 return -EINVAL;
b4af964e 1923 }
1e239fdd
EQ
1924 power_limit =
1925 pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1926 }
1927 smu->current_power_limit = power_limit;
b4af964e 1928
549db526
EQ
1929 if (smu->od_enabled &&
1930 navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
1e239fdd
EQ
1931 od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
1932
1933 dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
1934
1935 power_limit *= (100 + od_percent);
1936 power_limit /= 100;
b4af964e 1937 }
1e239fdd 1938 smu->max_power_limit = power_limit;
b4af964e 1939
b4af964e
EQ
1940 return 0;
1941}
1942
372120f0
KF
1943static int navi10_update_pcie_parameters(struct smu_context *smu,
1944 uint32_t pcie_gen_cap,
1945 uint32_t pcie_width_cap)
1946{
0b590970 1947 struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
372120f0 1948 PPTable_t *pptable = smu->smu_table.driver_pptable;
372120f0 1949 uint32_t smu_pcie_arg;
0b590970 1950 int ret, i;
372120f0 1951
0b590970
EQ
1952 /* lclk dpm table setup */
1953 for (i = 0; i < MAX_PCIE_CONF; i++) {
1954 dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i];
1955 dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i];
1956 }
fddbfb1c 1957
372120f0
KF
1958 for (i = 0; i < NUM_LINK_LEVELS; i++) {
1959 smu_pcie_arg = (i << 16) |
1960 ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
1961 (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
1962 pptable->PcieLaneCount[i] : pcie_width_cap);
1963 ret = smu_send_smc_msg_with_param(smu,
1964 SMU_MSG_OverridePcieParameters,
1c58267c
MC
1965 smu_pcie_arg,
1966 NULL);
fddbfb1c
KF
1967
1968 if (ret)
1969 return ret;
1970
1971 if (pptable->PcieGenSpeed[i] > pcie_gen_cap)
1972 dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap;
1973 if (pptable->PcieLaneCount[i] > pcie_width_cap)
1974 dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap;
372120f0 1975 }
fddbfb1c
KF
1976
1977 return 0;
21677d08
MC
1978}
1979
d9811cfc
EQ
1980static inline void navi10_dump_od_table(struct smu_context *smu,
1981 OverDriveTable_t *od_table)
1982{
1983 dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
1984 dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1);
1985 dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2);
1986 dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3);
1987 dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax);
1988 dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct);
21677d08
MC
1989}
1990
d9811cfc
EQ
1991static int navi10_od_setting_check_range(struct smu_context *smu,
1992 struct smu_11_0_overdrive_table *od_table,
1993 enum SMU_11_0_ODSETTING_ID setting,
1994 uint32_t value)
21677d08
MC
1995{
1996 if (value < od_table->min[setting]) {
d9811cfc 1997 dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]);
21677d08
MC
1998 return -EINVAL;
1999 }
2000 if (value > od_table->max[setting]) {
d9811cfc 2001 dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]);
21677d08
MC
2002 return -EINVAL;
2003 }
2004 return 0;
2005}
2006
0531aa6e
AD
2007static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
2008 uint16_t *voltage,
2009 uint32_t freq)
2010{
2011 uint32_t param = (freq & 0xFFFF) | (PPCLK_GFXCLK << 16);
2012 uint32_t value = 0;
2013 int ret;
2014
2015 ret = smu_send_smc_msg_with_param(smu,
2016 SMU_MSG_GetVoltageByDpm,
1c58267c
MC
2017 param,
2018 &value);
0531aa6e 2019 if (ret) {
d9811cfc 2020 dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
0531aa6e
AD
2021 return ret;
2022 }
2023
0531aa6e
AD
2024 *voltage = (uint16_t)value;
2025
2026 return 0;
2027}
2028
49e78c82
EQ
2029static bool navi10_is_baco_supported(struct smu_context *smu)
2030{
2031 struct amdgpu_device *adev = smu->adev;
2032 uint32_t val;
2033
311531f0 2034 if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu)))
49e78c82
EQ
2035 return false;
2036
2037 val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
2038 return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
2039}
2040
792f80d1
EQ
2041static int navi10_set_default_od_settings(struct smu_context *smu)
2042{
2043 OverDriveTable_t *od_table =
2044 (OverDriveTable_t *)smu->smu_table.overdrive_table;
2045 OverDriveTable_t *boot_od_table =
2046 (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
21677d08
MC
2047 int ret = 0;
2048
792f80d1
EQ
2049 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false);
2050 if (ret) {
d9811cfc 2051 dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
21677d08 2052 return ret;
792f80d1 2053 }
21677d08 2054
792f80d1
EQ
2055 if (!od_table->GfxclkVolt1) {
2056 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
2057 &od_table->GfxclkVolt1,
2058 od_table->GfxclkFreq1);
2059 if (ret)
2060 return ret;
2061 }
21677d08 2062
792f80d1
EQ
2063 if (!od_table->GfxclkVolt2) {
2064 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
2065 &od_table->GfxclkVolt2,
2066 od_table->GfxclkFreq2);
2067 if (ret)
2068 return ret;
21677d08
MC
2069 }
2070
792f80d1
EQ
2071 if (!od_table->GfxclkVolt3) {
2072 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
2073 &od_table->GfxclkVolt3,
2074 od_table->GfxclkFreq3);
2075 if (ret)
2076 return ret;
21677d08 2077 }
372120f0 2078
792f80d1
EQ
2079 memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
2080
d9811cfc 2081 navi10_dump_od_table(smu, od_table);
792f80d1
EQ
2082
2083 return 0;
372120f0
KF
2084}
2085
21677d08
MC
2086static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) {
2087 int i;
2088 int ret = 0;
2089 struct smu_table_context *table_context = &smu->smu_table;
2090 OverDriveTable_t *od_table;
2091 struct smu_11_0_overdrive_table *od_settings;
66107132
MC
2092 enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting;
2093 uint16_t *freq_ptr, *voltage_ptr;
21677d08
MC
2094 od_table = (OverDriveTable_t *)table_context->overdrive_table;
2095
2096 if (!smu->od_enabled) {
d9811cfc 2097 dev_warn(smu->adev->dev, "OverDrive is not enabled!\n");
21677d08
MC
2098 return -EINVAL;
2099 }
2100
2101 if (!smu->od_settings) {
d9811cfc 2102 dev_err(smu->adev->dev, "OD board limits are not set!\n");
21677d08
MC
2103 return -ENOENT;
2104 }
2105
2106 od_settings = smu->od_settings;
2107
2108 switch (type) {
2109 case PP_OD_EDIT_SCLK_VDDC_TABLE:
e33a8cfd 2110 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
d9811cfc 2111 dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n");
21677d08
MC
2112 return -ENOTSUPP;
2113 }
2114 if (!table_context->overdrive_table) {
d9811cfc 2115 dev_err(smu->adev->dev, "Overdrive is not initialized\n");
21677d08
MC
2116 return -EINVAL;
2117 }
2118 for (i = 0; i < size; i += 2) {
2119 if (i + 2 > size) {
d9811cfc 2120 dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size);
21677d08
MC
2121 return -EINVAL;
2122 }
2123 switch (input[i]) {
2124 case 0:
2125 freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN;
2126 freq_ptr = &od_table->GfxclkFmin;
2127 if (input[i + 1] > od_table->GfxclkFmax) {
d9811cfc 2128 dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n",
21677d08
MC
2129 input[i + 1],
2130 od_table->GfxclkFmin);
2131 return -EINVAL;
2132 }
2133 break;
2134 case 1:
2135 freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX;
2136 freq_ptr = &od_table->GfxclkFmax;
2137 if (input[i + 1] < od_table->GfxclkFmin) {
d9811cfc 2138 dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n",
21677d08
MC
2139 input[i + 1],
2140 od_table->GfxclkFmax);
2141 return -EINVAL;
2142 }
2143 break;
2144 default:
d9811cfc
EQ
2145 dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
2146 dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n");
21677d08
MC
2147 return -EINVAL;
2148 }
d9811cfc 2149 ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]);
21677d08
MC
2150 if (ret)
2151 return ret;
2152 *freq_ptr = input[i + 1];
2153 }
2154 break;
2155 case PP_OD_EDIT_MCLK_VDDC_TABLE:
e33a8cfd 2156 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
d9811cfc 2157 dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n");
21677d08
MC
2158 return -ENOTSUPP;
2159 }
2160 if (size < 2) {
d9811cfc 2161 dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
21677d08
MC
2162 return -EINVAL;
2163 }
2164 if (input[0] != 1) {
d9811cfc
EQ
2165 dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]);
2166 dev_info(smu->adev->dev, "Supported indices: [1:max]\n");
21677d08
MC
2167 return -EINVAL;
2168 }
d9811cfc 2169 ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]);
21677d08
MC
2170 if (ret)
2171 return ret;
2172 od_table->UclkFmax = input[1];
2173 break;
93c5f1f6
MC
2174 case PP_OD_RESTORE_DEFAULT_TABLE:
2175 if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) {
d9811cfc 2176 dev_err(smu->adev->dev, "Overdrive table was not initialized!\n");
93c5f1f6
MC
2177 return -EINVAL;
2178 }
2179 memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
2180 break;
21677d08 2181 case PP_OD_COMMIT_DPM_TABLE:
d9811cfc 2182 navi10_dump_od_table(smu, od_table);
21677d08
MC
2183 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
2184 if (ret) {
d9811cfc 2185 dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
21677d08
MC
2186 return ret;
2187 }
2188 // no lock needed because smu_od_edit_dpm_table has it
2189 ret = smu_handle_task(smu, smu->smu_dpm.dpm_level,
2190 AMD_PP_TASK_READJUST_POWER_STATE,
2191 false);
2192 if (ret) {
2193 return ret;
2194 }
2195 break;
2196 case PP_OD_EDIT_VDDC_CURVE:
e33a8cfd 2197 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
d9811cfc 2198 dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n");
66107132
MC
2199 return -ENOTSUPP;
2200 }
2201 if (size < 3) {
d9811cfc 2202 dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
66107132
MC
2203 return -EINVAL;
2204 }
2205 if (!od_table) {
d9811cfc 2206 dev_info(smu->adev->dev, "Overdrive is not initialized\n");
66107132
MC
2207 return -EINVAL;
2208 }
2209
2210 switch (input[0]) {
2211 case 0:
2212 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1;
2213 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1;
2214 freq_ptr = &od_table->GfxclkFreq1;
2215 voltage_ptr = &od_table->GfxclkVolt1;
2216 break;
2217 case 1:
2218 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2;
2219 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2;
2220 freq_ptr = &od_table->GfxclkFreq2;
2221 voltage_ptr = &od_table->GfxclkVolt2;
2222 break;
2223 case 2:
2224 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3;
2225 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3;
2226 freq_ptr = &od_table->GfxclkFreq3;
2227 voltage_ptr = &od_table->GfxclkVolt3;
2228 break;
2229 default:
d9811cfc
EQ
2230 dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]);
2231 dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n");
66107132
MC
2232 return -EINVAL;
2233 }
d9811cfc 2234 ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]);
66107132
MC
2235 if (ret)
2236 return ret;
2237 // Allow setting zero to disable the OverDrive VDDC curve
2238 if (input[2] != 0) {
d9811cfc 2239 ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]);
66107132
MC
2240 if (ret)
2241 return ret;
2242 *freq_ptr = input[1];
2243 *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE;
d9811cfc 2244 dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr);
66107132
MC
2245 } else {
2246 // If setting 0, disable all voltage curve settings
2247 od_table->GfxclkVolt1 = 0;
2248 od_table->GfxclkVolt2 = 0;
2249 od_table->GfxclkVolt3 = 0;
2250 }
d9811cfc 2251 navi10_dump_od_table(smu, od_table);
66107132 2252 break;
21677d08
MC
2253 default:
2254 return -ENOSYS;
2255 }
2256 return ret;
2257}
372120f0 2258
0eeaa899
EQ
2259static int navi10_run_btc(struct smu_context *smu)
2260{
2261 int ret = 0;
2262
1c58267c 2263 ret = smu_send_smc_msg(smu, SMU_MSG_RunBtc, NULL);
0eeaa899 2264 if (ret)
d9811cfc 2265 dev_err(smu->adev->dev, "RunBtc failed!\n");
0eeaa899
EQ
2266
2267 return ret;
2268}
2269
1cf8c930
EQ
2270static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable)
2271{
2272 int result = 0;
2273
2274 if (!enable)
1c58267c 2275 result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL);
1cf8c930 2276 else
1c58267c 2277 result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL);
1cf8c930
EQ
2278
2279 return result;
2280}
2281
31157341
EQ
2282static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev)
2283{
2284 if (adev->asic_type != CHIP_NAVI10)
2285 return false;
2286
2287 if (adev->pdev->device == 0x731f &&
2288 (adev->pdev->revision == 0xc2 ||
2289 adev->pdev->revision == 0xc3 ||
2290 adev->pdev->revision == 0xca ||
2291 adev->pdev->revision == 0xcb))
2292 return true;
2293 else
2294 return false;
2295}
2296
1cf8c930
EQ
2297static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu)
2298{
2299 uint32_t uclk_count, uclk_min, uclk_max;
2300 uint32_t smu_version;
2301 int ret = 0;
2302
31157341
EQ
2303 if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev))
2304 return 0;
2305
1cf8c930
EQ
2306 ret = smu_get_smc_version(smu, NULL, &smu_version);
2307 if (ret)
2308 return ret;
2309
2310 /* This workaround is available only for 42.50 or later SMC firmwares */
2311 if (smu_version < 0x2A3200)
2312 return 0;
2313
d8d3493a 2314 ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count);
1cf8c930
EQ
2315 if (ret)
2316 return ret;
2317
d8d3493a 2318 ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min);
1cf8c930
EQ
2319 if (ret)
2320 return ret;
2321
d8d3493a 2322 ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max);
1cf8c930
EQ
2323 if (ret)
2324 return ret;
2325
2326 /* Force UCLK out of the highest DPM */
661b94f5 2327 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min);
1cf8c930
EQ
2328 if (ret)
2329 return ret;
2330
2331 /* Revert the UCLK Hardmax */
661b94f5 2332 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max);
1cf8c930
EQ
2333 if (ret)
2334 return ret;
2335
2336 /*
2337 * In this case, SMU already disabled dummy pstate during enablement
2338 * of UCLK DPM, we have to re-enabled it.
2339 * */
2340 return navi10_dummy_pstate_control(smu, true);
2341}
2342
b3490673 2343static const struct pptable_funcs navi10_ppt_funcs = {
22c9c6ca 2344 .tables_init = navi10_tables_init,
b3490673 2345 .alloc_dpm_context = navi10_allocate_dpm_context,
b3490673 2346 .get_smu_msg_index = navi10_get_smu_msg_index,
0de94acf 2347 .get_smu_clk_index = navi10_get_smu_clk_index,
ffcb08df 2348 .get_smu_feature_index = navi10_get_smu_feature_index,
2436911b 2349 .get_smu_table_index = navi10_get_smu_table_index,
8890fe5f 2350 .get_smu_power_index = navi10_get_pwr_src_index,
6c6187ec 2351 .get_workload_type = navi10_get_workload_type,
74c958a3 2352 .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
b3490673 2353 .set_default_dpm_table = navi10_set_default_dpm_table,
f6b4b4a1 2354 .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
43717ff6 2355 .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
b1e7e224 2356 .print_clk_levels = navi10_print_clk_levels,
db439ca2 2357 .force_clk_levels = navi10_force_clk_levels,
fa51bfc2 2358 .populate_umd_state_clk = navi10_populate_umd_state_clk,
a43913ea 2359 .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
28430544 2360 .pre_display_config_changed = navi10_pre_display_config_changed,
0a6430da 2361 .display_config_changed = navi10_display_config_changed,
19796597 2362 .notify_smc_display_config = navi10_notify_smc_display_config,
4228b601 2363 .is_dpm_running = navi10_is_dpm_running,
2d589a5b 2364 .get_fan_speed_percent = navi10_get_fan_speed_percent,
95ccc155 2365 .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
b45dc20b
KW
2366 .get_power_profile_mode = navi10_get_power_profile_mode,
2367 .set_power_profile_mode = navi10_set_power_profile_mode,
5bbb0994 2368 .set_watermarks_table = navi10_set_watermarks_table,
9c62f993 2369 .read_sensor = navi10_read_sensor,
f4b3295f 2370 .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
46a301e1 2371 .set_performance_level = smu_v11_0_set_performance_level,
7a816371 2372 .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
6e92e156 2373 .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
b4af964e 2374 .get_power_limit = navi10_get_power_limit,
372120f0 2375 .update_pcie_parameters = navi10_update_pcie_parameters,
6c45e480
EQ
2376 .init_microcode = smu_v11_0_init_microcode,
2377 .load_microcode = smu_v11_0_load_microcode,
6f47116e 2378 .fini_microcode = smu_v11_0_fini_microcode,
6c45e480
EQ
2379 .init_smc_tables = smu_v11_0_init_smc_tables,
2380 .fini_smc_tables = smu_v11_0_fini_smc_tables,
2381 .init_power = smu_v11_0_init_power,
2382 .fini_power = smu_v11_0_fini_power,
2383 .check_fw_status = smu_v11_0_check_fw_status,
4a13b4ce 2384 .setup_pptable = navi10_setup_pptable,
6c45e480 2385 .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
6c45e480
EQ
2386 .check_fw_version = smu_v11_0_check_fw_version,
2387 .write_pptable = smu_v11_0_write_pptable,
ce0d0ec3 2388 .set_driver_table_location = smu_v11_0_set_driver_table_location,
6c45e480
EQ
2389 .set_tool_table_location = smu_v11_0_set_tool_table_location,
2390 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
2391 .system_features_control = smu_v11_0_system_features_control,
6c45e480 2392 .send_smc_msg_with_param = smu_v11_0_send_msg_with_param,
6c45e480
EQ
2393 .init_display_count = smu_v11_0_init_display_count,
2394 .set_allowed_mask = smu_v11_0_set_allowed_mask,
2395 .get_enabled_mask = smu_v11_0_get_enabled_mask,
2396 .notify_display_change = smu_v11_0_notify_display_change,
2397 .set_power_limit = smu_v11_0_set_power_limit,
6c45e480 2398 .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
22f1e0e8
EQ
2399 .enable_thermal_alert = smu_v11_0_enable_thermal_alert,
2400 .disable_thermal_alert = smu_v11_0_disable_thermal_alert,
ce63d8f8 2401 .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk,
6c45e480
EQ
2402 .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
2403 .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
2404 .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
2405 .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
2406 .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
2407 .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
2408 .gfx_off_control = smu_v11_0_gfx_off_control,
2409 .register_irq_handler = smu_v11_0_register_irq_handler,
2410 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
2411 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
49e78c82 2412 .baco_is_support= navi10_is_baco_supported,
6c45e480
EQ
2413 .baco_get_state = smu_v11_0_baco_get_state,
2414 .baco_set_state = smu_v11_0_baco_set_state,
11520f27
AD
2415 .baco_enter = smu_v11_0_baco_enter,
2416 .baco_exit = smu_v11_0_baco_exit,
6c45e480
EQ
2417 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
2418 .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
21677d08
MC
2419 .set_default_od_settings = navi10_set_default_od_settings,
2420 .od_edit_dpm_table = navi10_od_edit_dpm_table,
0eeaa899 2421 .run_btc = navi10_run_btc,
1cf8c930 2422 .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround,
fa34520c 2423 .set_power_source = smu_v11_0_set_power_source,
b3490673
HR
2424};
2425
2426void navi10_set_ppt_funcs(struct smu_context *smu)
2427{
2428 smu->ppt_funcs = &navi10_ppt_funcs;
2429}