2 * Copyright 2018 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <linux/delay.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
30 #include "amd_powerplay.h"
31 #include "vega20_smumgr.h"
32 #include "hardwaremanager.h"
33 #include "ppatomfwctrl.h"
34 #include "atomfirmware.h"
35 #include "cgs_common.h"
36 #include "vega20_powertune.h"
37 #include "vega20_inc.h"
38 #include "pppcielanes.h"
39 #include "vega20_hwmgr.h"
40 #include "vega20_processpptables.h"
41 #include "vega20_pptable.h"
42 #include "vega20_thermal.h"
43 #include "vega20_ppsmc.h"
45 #include "amd_pcie_helpers.h"
46 #include "ppinterrupt.h"
47 #include "pp_overdriver.h"
48 #include "pp_thermal.h"
49 #include "soc15_common.h"
50 #include "vega20_baco.h"
51 #include "smuio/smuio_9_0_offset.h"
52 #include "smuio/smuio_9_0_sh_mask.h"
53 #include "nbio/nbio_7_4_sh_mask.h"
55 #define smnPCIE_LC_SPEED_CNTL 0x11140290
56 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
58 #define LINK_WIDTH_MAX 6
59 #define LINK_SPEED_MAX 3
60 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
61 static const int link_speed[] = {25, 50, 80, 160};
63 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
65 struct vega20_hwmgr *data =
66 (struct vega20_hwmgr *)(hwmgr->backend);
68 data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT;
69 data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT;
70 data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT;
71 data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT;
72 data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT;
74 data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT;
75 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
76 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
77 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
78 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
79 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
80 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
81 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
82 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
83 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
84 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
85 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
86 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
89 * Disable the following features for now:
98 data->registry_data.disallowed_features = 0xE0041C00;
99 /* ECC feature should be disabled on old SMUs */
100 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version);
101 if (hwmgr->smu_version < 0x282100)
102 data->registry_data.disallowed_features |= FEATURE_ECC_MASK;
104 if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK))
105 data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK;
107 if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK))
108 data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK;
110 if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK))
111 data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK;
113 if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK))
114 data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK;
116 if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK))
117 data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK;
119 if (!(hwmgr->feature_mask & PP_ULV_MASK))
120 data->registry_data.disallowed_features |= FEATURE_ULV_MASK;
122 if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK))
123 data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK;
125 data->registry_data.od_state_in_dc_support = 0;
126 data->registry_data.thermal_support = 1;
127 data->registry_data.skip_baco_hardware = 0;
129 data->registry_data.log_avfs_param = 0;
130 data->registry_data.sclk_throttle_low_notification = 1;
131 data->registry_data.force_dpm_high = 0;
132 data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
134 data->registry_data.didt_support = 0;
135 if (data->registry_data.didt_support) {
136 data->registry_data.didt_mode = 6;
137 data->registry_data.sq_ramping_support = 1;
138 data->registry_data.db_ramping_support = 0;
139 data->registry_data.td_ramping_support = 0;
140 data->registry_data.tcp_ramping_support = 0;
141 data->registry_data.dbr_ramping_support = 0;
142 data->registry_data.edc_didt_support = 1;
143 data->registry_data.gc_didt_support = 0;
144 data->registry_data.psm_didt_support = 0;
147 data->registry_data.pcie_lane_override = 0xff;
148 data->registry_data.pcie_speed_override = 0xff;
149 data->registry_data.pcie_clock_override = 0xffffffff;
150 data->registry_data.regulator_hot_gpio_support = 1;
151 data->registry_data.ac_dc_switch_gpio_support = 0;
152 data->registry_data.quick_transition_support = 0;
153 data->registry_data.zrpm_start_temp = 0xffff;
154 data->registry_data.zrpm_stop_temp = 0xffff;
155 data->registry_data.od8_feature_enable = 1;
156 data->registry_data.disable_water_mark = 0;
157 data->registry_data.disable_pp_tuning = 0;
158 data->registry_data.disable_xlpp_tuning = 0;
159 data->registry_data.disable_workload_policy = 0;
160 data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
161 data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
162 data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
163 data->registry_data.force_workload_policy_mask = 0;
164 data->registry_data.disable_3d_fs_detection = 0;
165 data->registry_data.fps_support = 1;
166 data->registry_data.disable_auto_wattman = 1;
167 data->registry_data.auto_wattman_debug = 0;
168 data->registry_data.auto_wattman_sample_period = 100;
169 data->registry_data.fclk_gfxclk_ratio = 0;
170 data->registry_data.auto_wattman_threshold = 50;
171 data->registry_data.gfxoff_controlled_by_driver = 1;
172 data->gfxoff_allowed = false;
173 data->counter_gfxoff = 0;
174 data->registry_data.pcie_dpm_key_disabled = !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
177 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
179 struct vega20_hwmgr *data =
180 (struct vega20_hwmgr *)(hwmgr->backend);
181 struct amdgpu_device *adev = hwmgr->adev;
183 if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE)
184 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
185 PHM_PlatformCaps_ControlVDDCI);
187 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
188 PHM_PlatformCaps_TablelessHardwareInterface);
190 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
191 PHM_PlatformCaps_BACO);
193 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
194 PHM_PlatformCaps_EnableSMU7ThermalManagement);
196 if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
197 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
198 PHM_PlatformCaps_UVDPowerGating);
200 if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
201 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
202 PHM_PlatformCaps_VCEPowerGating);
204 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
205 PHM_PlatformCaps_UnTabledHardwareInterface);
207 if (data->registry_data.od8_feature_enable)
208 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
209 PHM_PlatformCaps_OD8inACSupport);
211 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
212 PHM_PlatformCaps_ActivityReporting);
213 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
214 PHM_PlatformCaps_FanSpeedInTableIsRPM);
216 if (data->registry_data.od_state_in_dc_support) {
217 if (data->registry_data.od8_feature_enable)
218 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
219 PHM_PlatformCaps_OD8inDCSupport);
222 if (data->registry_data.thermal_support &&
223 data->registry_data.fuzzy_fan_control_support &&
224 hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
225 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
226 PHM_PlatformCaps_ODFuzzyFanControlSupport);
228 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
229 PHM_PlatformCaps_DynamicPowerManagement);
230 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
231 PHM_PlatformCaps_SMC);
232 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
233 PHM_PlatformCaps_ThermalPolicyDelay);
235 if (data->registry_data.force_dpm_high)
236 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
237 PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
239 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
240 PHM_PlatformCaps_DynamicUVDState);
242 if (data->registry_data.sclk_throttle_low_notification)
243 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
244 PHM_PlatformCaps_SclkThrottleLowNotification);
246 /* power tune caps */
247 /* assume disabled */
248 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
249 PHM_PlatformCaps_PowerContainment);
250 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
251 PHM_PlatformCaps_DiDtSupport);
252 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
253 PHM_PlatformCaps_SQRamping);
254 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
255 PHM_PlatformCaps_DBRamping);
256 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
257 PHM_PlatformCaps_TDRamping);
258 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
259 PHM_PlatformCaps_TCPRamping);
260 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
261 PHM_PlatformCaps_DBRRamping);
262 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
263 PHM_PlatformCaps_DiDtEDCEnable);
264 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
265 PHM_PlatformCaps_GCEDC);
266 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
267 PHM_PlatformCaps_PSM);
269 if (data->registry_data.didt_support) {
270 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
271 PHM_PlatformCaps_DiDtSupport);
272 if (data->registry_data.sq_ramping_support)
273 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
274 PHM_PlatformCaps_SQRamping);
275 if (data->registry_data.db_ramping_support)
276 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
277 PHM_PlatformCaps_DBRamping);
278 if (data->registry_data.td_ramping_support)
279 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
280 PHM_PlatformCaps_TDRamping);
281 if (data->registry_data.tcp_ramping_support)
282 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
283 PHM_PlatformCaps_TCPRamping);
284 if (data->registry_data.dbr_ramping_support)
285 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
286 PHM_PlatformCaps_DBRRamping);
287 if (data->registry_data.edc_didt_support)
288 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
289 PHM_PlatformCaps_DiDtEDCEnable);
290 if (data->registry_data.gc_didt_support)
291 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
292 PHM_PlatformCaps_GCEDC);
293 if (data->registry_data.psm_didt_support)
294 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
295 PHM_PlatformCaps_PSM);
298 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
299 PHM_PlatformCaps_RegulatorHot);
301 if (data->registry_data.ac_dc_switch_gpio_support) {
302 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
303 PHM_PlatformCaps_AutomaticDCTransition);
304 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
305 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
308 if (data->registry_data.quick_transition_support) {
309 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
310 PHM_PlatformCaps_AutomaticDCTransition);
311 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
312 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
313 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
314 PHM_PlatformCaps_Falcon_QuickTransition);
317 if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) {
318 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
319 PHM_PlatformCaps_LowestUclkReservedForUlv);
320 if (data->lowest_uclk_reserved_for_ulv == 1)
321 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
322 PHM_PlatformCaps_LowestUclkReservedForUlv);
325 if (data->registry_data.custom_fan_support)
326 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
327 PHM_PlatformCaps_CustomFanControlSupport);
332 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr)
334 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
335 struct amdgpu_device *adev = hwmgr->adev;
336 uint32_t top32, bottom32;
339 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
340 FEATURE_DPM_PREFETCHER_BIT;
341 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
342 FEATURE_DPM_GFXCLK_BIT;
343 data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
344 FEATURE_DPM_UCLK_BIT;
345 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
346 FEATURE_DPM_SOCCLK_BIT;
347 data->smu_features[GNLD_DPM_UVD].smu_feature_id =
349 data->smu_features[GNLD_DPM_VCE].smu_feature_id =
351 data->smu_features[GNLD_ULV].smu_feature_id =
353 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
354 FEATURE_DPM_MP0CLK_BIT;
355 data->smu_features[GNLD_DPM_LINK].smu_feature_id =
356 FEATURE_DPM_LINK_BIT;
357 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
358 FEATURE_DPM_DCEFCLK_BIT;
359 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
360 FEATURE_DS_GFXCLK_BIT;
361 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
362 FEATURE_DS_SOCCLK_BIT;
363 data->smu_features[GNLD_DS_LCLK].smu_feature_id =
365 data->smu_features[GNLD_PPT].smu_feature_id =
367 data->smu_features[GNLD_TDC].smu_feature_id =
369 data->smu_features[GNLD_THERMAL].smu_feature_id =
371 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
372 FEATURE_GFX_PER_CU_CG_BIT;
373 data->smu_features[GNLD_RM].smu_feature_id =
375 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
376 FEATURE_DS_DCEFCLK_BIT;
377 data->smu_features[GNLD_ACDC].smu_feature_id =
379 data->smu_features[GNLD_VR0HOT].smu_feature_id =
381 data->smu_features[GNLD_VR1HOT].smu_feature_id =
383 data->smu_features[GNLD_FW_CTF].smu_feature_id =
385 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
386 FEATURE_LED_DISPLAY_BIT;
387 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
388 FEATURE_FAN_CONTROL_BIT;
389 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
390 data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
391 data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
392 data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT;
393 data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT;
394 data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
395 data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
396 data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
397 data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT;
399 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
400 data->smu_features[i].smu_feature_bitmap =
401 (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
402 data->smu_features[i].allowed =
403 ((data->registry_data.disallowed_features >> i) & 1) ?
407 /* Get the SN to turn into a Unique ID */
408 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32);
409 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32);
411 adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
414 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
419 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
421 kfree(hwmgr->backend);
422 hwmgr->backend = NULL;
427 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
429 struct vega20_hwmgr *data;
430 struct amdgpu_device *adev = hwmgr->adev;
432 data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL);
436 hwmgr->backend = data;
438 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
439 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
440 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
442 vega20_set_default_registry_data(hwmgr);
444 data->disable_dpm_mask = 0xff;
446 /* need to set voltage control types before EVV patching */
447 data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE;
448 data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE;
449 data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE;
451 data->water_marks_bitmap = 0;
452 data->avfs_exist = false;
454 vega20_set_features_platform_caps(hwmgr);
456 vega20_init_dpm_defaults(hwmgr);
458 /* Parse pptable data read from VBIOS */
459 vega20_set_private_data_based_on_pptable(hwmgr);
461 data->is_tlu_enabled = false;
463 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
464 VEGA20_MAX_HARDWARE_POWERLEVELS;
465 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
466 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
468 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
469 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
470 hwmgr->platform_descriptor.clockStep.engineClock = 500;
471 hwmgr->platform_descriptor.clockStep.memoryClock = 500;
473 data->total_active_cus = adev->gfx.cu_info.number;
474 data->is_custom_profile_set = false;
479 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr)
481 struct vega20_hwmgr *data =
482 (struct vega20_hwmgr *)(hwmgr->backend);
484 data->low_sclk_interrupt_threshold = 0;
489 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
491 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
493 bool use_baco = (amdgpu_in_reset(adev) &&
494 (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
495 (adev->in_runpm && amdgpu_asic_supports_baco(adev));
497 ret = vega20_init_sclk_threshold(hwmgr);
498 PP_ASSERT_WITH_CODE(!ret,
499 "Failed to init sclk threshold!",
503 ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
505 pr_err("Failed to apply vega20 baco workaround!\n");
512 * @fn vega20_init_dpm_state
513 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
515 * @param dpm_state - the address of the DPM Table to initiailize.
518 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state)
520 dpm_state->soft_min_level = 0x0;
521 dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT;
522 dpm_state->hard_min_level = 0x0;
523 dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT;
526 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
527 PPCLK_e clk_id, uint32_t *num_of_levels)
531 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
532 PPSMC_MSG_GetDpmFreqByIndex,
533 (clk_id << 16 | 0xFF),
535 PP_ASSERT_WITH_CODE(!ret,
536 "[GetNumOfDpmLevel] failed to get dpm levels!",
542 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
543 PPCLK_e clk_id, uint32_t index, uint32_t *clk)
547 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
548 PPSMC_MSG_GetDpmFreqByIndex,
549 (clk_id << 16 | index),
551 PP_ASSERT_WITH_CODE(!ret,
552 "[GetDpmFreqByIndex] failed to get dpm freq by index!",
558 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
559 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id)
562 uint32_t i, num_of_levels, clk;
564 ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
565 PP_ASSERT_WITH_CODE(!ret,
566 "[SetupSingleDpmTable] failed to get clk levels!",
569 dpm_table->count = num_of_levels;
571 for (i = 0; i < num_of_levels; i++) {
572 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
573 PP_ASSERT_WITH_CODE(!ret,
574 "[SetupSingleDpmTable] failed to get clk of specific level!",
576 dpm_table->dpm_levels[i].value = clk;
577 dpm_table->dpm_levels[i].enabled = true;
583 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
585 struct vega20_hwmgr *data =
586 (struct vega20_hwmgr *)(hwmgr->backend);
587 struct vega20_single_dpm_table *dpm_table;
590 dpm_table = &(data->dpm_table.gfx_table);
591 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
592 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
593 PP_ASSERT_WITH_CODE(!ret,
594 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
597 dpm_table->count = 1;
598 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
604 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
606 struct vega20_hwmgr *data =
607 (struct vega20_hwmgr *)(hwmgr->backend);
608 struct vega20_single_dpm_table *dpm_table;
611 dpm_table = &(data->dpm_table.mem_table);
612 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
613 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
614 PP_ASSERT_WITH_CODE(!ret,
615 "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
618 dpm_table->count = 1;
619 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
626 * This function is to initialize all DPM state tables
627 * for SMU based on the dependency table.
628 * Dynamic state patching function will then trim these
629 * state tables to the allowed range based
630 * on the power policy or external client requests,
631 * such as UVD request, etc.
633 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
635 struct vega20_hwmgr *data =
636 (struct vega20_hwmgr *)(hwmgr->backend);
637 struct vega20_single_dpm_table *dpm_table;
640 memset(&data->dpm_table, 0, sizeof(data->dpm_table));
643 dpm_table = &(data->dpm_table.soc_table);
644 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
645 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
646 PP_ASSERT_WITH_CODE(!ret,
647 "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
650 dpm_table->count = 1;
651 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
653 vega20_init_dpm_state(&(dpm_table->dpm_state));
656 dpm_table = &(data->dpm_table.gfx_table);
657 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
660 vega20_init_dpm_state(&(dpm_table->dpm_state));
663 dpm_table = &(data->dpm_table.mem_table);
664 ret = vega20_setup_memclk_dpm_table(hwmgr);
667 vega20_init_dpm_state(&(dpm_table->dpm_state));
670 dpm_table = &(data->dpm_table.eclk_table);
671 if (data->smu_features[GNLD_DPM_VCE].enabled) {
672 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
673 PP_ASSERT_WITH_CODE(!ret,
674 "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
677 dpm_table->count = 1;
678 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
680 vega20_init_dpm_state(&(dpm_table->dpm_state));
683 dpm_table = &(data->dpm_table.vclk_table);
684 if (data->smu_features[GNLD_DPM_UVD].enabled) {
685 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
686 PP_ASSERT_WITH_CODE(!ret,
687 "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
690 dpm_table->count = 1;
691 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
693 vega20_init_dpm_state(&(dpm_table->dpm_state));
696 dpm_table = &(data->dpm_table.dclk_table);
697 if (data->smu_features[GNLD_DPM_UVD].enabled) {
698 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
699 PP_ASSERT_WITH_CODE(!ret,
700 "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
703 dpm_table->count = 1;
704 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
706 vega20_init_dpm_state(&(dpm_table->dpm_state));
709 dpm_table = &(data->dpm_table.dcef_table);
710 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
711 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
712 PP_ASSERT_WITH_CODE(!ret,
713 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
716 dpm_table->count = 1;
717 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
719 vega20_init_dpm_state(&(dpm_table->dpm_state));
722 dpm_table = &(data->dpm_table.pixel_table);
723 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
724 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
725 PP_ASSERT_WITH_CODE(!ret,
726 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
729 dpm_table->count = 0;
730 vega20_init_dpm_state(&(dpm_table->dpm_state));
733 dpm_table = &(data->dpm_table.display_table);
734 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
735 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
736 PP_ASSERT_WITH_CODE(!ret,
737 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
740 dpm_table->count = 0;
741 vega20_init_dpm_state(&(dpm_table->dpm_state));
744 dpm_table = &(data->dpm_table.phy_table);
745 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
746 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
747 PP_ASSERT_WITH_CODE(!ret,
748 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
751 dpm_table->count = 0;
752 vega20_init_dpm_state(&(dpm_table->dpm_state));
755 dpm_table = &(data->dpm_table.fclk_table);
756 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
757 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK);
758 PP_ASSERT_WITH_CODE(!ret,
759 "[SetupDefaultDpmTable] failed to get fclk dpm levels!",
762 dpm_table->count = 1;
763 dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100;
765 vega20_init_dpm_state(&(dpm_table->dpm_state));
767 /* save a copy of the default DPM table */
768 memcpy(&(data->golden_dpm_table), &(data->dpm_table),
769 sizeof(struct vega20_dpm_table));
775 * vega20_init_smc_table - Initializes the SMC table and uploads it
777 * @hwmgr: the address of the powerplay hardware manager.
780 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr)
783 struct vega20_hwmgr *data =
784 (struct vega20_hwmgr *)(hwmgr->backend);
785 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
786 struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
787 struct phm_ppt_v3_information *pptable_information =
788 (struct phm_ppt_v3_information *)hwmgr->pptable;
790 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
791 PP_ASSERT_WITH_CODE(!result,
792 "[InitSMCTable] Failed to get vbios bootup values!",
795 data->vbios_boot_state.vddc = boot_up_values.usVddc;
796 data->vbios_boot_state.vddci = boot_up_values.usVddci;
797 data->vbios_boot_state.mvddc = boot_up_values.usMvddc;
798 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
799 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
800 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
801 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
802 data->vbios_boot_state.eclock = boot_up_values.ulEClk;
803 data->vbios_boot_state.vclock = boot_up_values.ulVClk;
804 data->vbios_boot_state.dclock = boot_up_values.ulDClk;
805 data->vbios_boot_state.fclock = boot_up_values.ulFClk;
806 data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
808 smum_send_msg_to_smc_with_parameter(hwmgr,
809 PPSMC_MSG_SetMinDeepSleepDcefclk,
810 (uint32_t)(data->vbios_boot_state.dcef_clock / 100),
813 memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
815 result = smum_smc_table_manager(hwmgr,
816 (uint8_t *)pp_table, TABLE_PPTABLE, false);
817 PP_ASSERT_WITH_CODE(!result,
818 "[InitSMCTable] Failed to upload PPtable!",
825 * Override PCIe link speed and link width for DPM Level 1. PPTable entries
826 * reflect the ASIC capabilities and not the system capabilities. For e.g.
827 * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch
828 * to DPM1, it fails as system doesn't support Gen4.
830 static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
832 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
833 struct vega20_hwmgr *data =
834 (struct vega20_hwmgr *)(hwmgr->backend);
835 uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
836 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
840 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
842 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
844 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
846 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
849 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
851 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
853 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
855 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
857 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
859 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
862 /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
863 * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
864 * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
866 for (i = 0; i < NUM_LINK_LEVELS; i++) {
867 pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
868 pp_table->PcieGenSpeed[i];
869 pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
870 pp_table->PcieLaneCount[i];
872 if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
873 pp_table->PcieLaneCount[i]) {
874 smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
875 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
876 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
878 PP_ASSERT_WITH_CODE(!ret,
879 "[OverridePcieParameters] Attempt to override pcie params failed!",
883 /* update the pptable */
884 pp_table->PcieGenSpeed[i] = pcie_gen_arg;
885 pp_table->PcieLaneCount[i] = pcie_width_arg;
888 /* override to the highest if it's disabled from ppfeaturmask */
889 if (data->registry_data.pcie_dpm_key_disabled) {
890 for (i = 0; i < NUM_LINK_LEVELS; i++) {
891 smu_pcie_arg = (i << 16) | (pcie_gen << 8) | pcie_width;
892 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
893 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
895 PP_ASSERT_WITH_CODE(!ret,
896 "[OverridePcieParameters] Attempt to override pcie params failed!",
899 pp_table->PcieGenSpeed[i] = pcie_gen;
900 pp_table->PcieLaneCount[i] = pcie_width;
902 ret = vega20_enable_smc_features(hwmgr,
904 data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap);
905 PP_ASSERT_WITH_CODE(!ret,
906 "Attempt to Disable DPM LINK Failed!",
908 data->smu_features[GNLD_DPM_LINK].enabled = false;
909 data->smu_features[GNLD_DPM_LINK].supported = false;
915 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
917 struct vega20_hwmgr *data =
918 (struct vega20_hwmgr *)(hwmgr->backend);
919 uint32_t allowed_features_low = 0, allowed_features_high = 0;
923 for (i = 0; i < GNLD_FEATURES_MAX; i++)
924 if (data->smu_features[i].allowed)
925 data->smu_features[i].smu_feature_id > 31 ?
926 (allowed_features_high |=
927 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT)
929 (allowed_features_low |=
930 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT)
933 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
934 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, NULL);
935 PP_ASSERT_WITH_CODE(!ret,
936 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!",
939 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
940 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, NULL);
941 PP_ASSERT_WITH_CODE(!ret,
942 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
948 static int vega20_run_btc(struct pp_hwmgr *hwmgr)
950 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc, NULL);
953 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
955 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc, NULL);
958 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)
960 struct vega20_hwmgr *data =
961 (struct vega20_hwmgr *)(hwmgr->backend);
962 uint64_t features_enabled;
967 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
968 PPSMC_MSG_EnableAllSmuFeatures,
970 "[EnableAllSMUFeatures] Failed to enable all smu features!",
973 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
974 PP_ASSERT_WITH_CODE(!ret,
975 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
978 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
979 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
981 data->smu_features[i].enabled = enabled;
982 data->smu_features[i].supported = enabled;
985 if (data->smu_features[i].allowed && !enabled)
986 pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i);
987 else if (!data->smu_features[i].allowed && enabled)
988 pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i);
995 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr)
997 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
999 if (data->smu_features[GNLD_DPM_UCLK].enabled)
1000 return smum_send_msg_to_smc_with_parameter(hwmgr,
1001 PPSMC_MSG_SetUclkFastSwitch,
1008 static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr)
1010 struct vega20_hwmgr *data =
1011 (struct vega20_hwmgr *)(hwmgr->backend);
1013 return smum_send_msg_to_smc_with_parameter(hwmgr,
1014 PPSMC_MSG_SetFclkGfxClkRatio,
1015 data->registry_data.fclk_gfxclk_ratio,
1019 static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr)
1021 struct vega20_hwmgr *data =
1022 (struct vega20_hwmgr *)(hwmgr->backend);
1025 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
1026 PPSMC_MSG_DisableAllSmuFeatures,
1028 "[DisableAllSMUFeatures] Failed to disable all smu features!",
1031 for (i = 0; i < GNLD_FEATURES_MAX; i++)
1032 data->smu_features[i].enabled = 0;
1037 static int vega20_od8_set_feature_capabilities(
1038 struct pp_hwmgr *hwmgr)
1040 struct phm_ppt_v3_information *pptable_information =
1041 (struct phm_ppt_v3_information *)hwmgr->pptable;
1042 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1043 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1044 struct vega20_od8_settings *od_settings = &(data->od8_settings);
1046 od_settings->overdrive8_capabilities = 0;
1048 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1049 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1050 pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1051 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1052 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1053 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN]))
1054 od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS;
1056 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1057 (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1058 pp_table->MinVoltageGfx / VOLTAGE_SCALE) &&
1059 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1060 pp_table->MaxVoltageGfx / VOLTAGE_SCALE) &&
1061 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >=
1062 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1]))
1063 od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE;
1066 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1067 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] =
1068 data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value;
1069 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1070 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1071 pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1072 (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1073 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX]))
1074 od_settings->overdrive8_capabilities |= OD8_UCLK_MAX;
1077 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1078 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1079 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1080 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1081 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100)
1082 od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT;
1084 if (data->smu_features[GNLD_FAN_CONTROL].enabled) {
1085 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1086 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1087 pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1088 (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1089 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT]))
1090 od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK;
1092 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1093 (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >=
1094 (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) &&
1095 pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1096 (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1097 pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED]))
1098 od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN;
1101 if (data->smu_features[GNLD_THERMAL].enabled) {
1102 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1103 pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1104 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1105 (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1106 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP]))
1107 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN;
1109 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1110 pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1111 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1112 (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1113 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX]))
1114 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM;
1117 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE])
1118 od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE;
1120 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] &&
1121 pp_table->FanZeroRpmEnable)
1122 od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
1124 if (!od_settings->overdrive8_capabilities)
1125 hwmgr->od_enabled = false;
1130 static int vega20_od8_set_feature_id(
1131 struct pp_hwmgr *hwmgr)
1133 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1134 struct vega20_od8_settings *od_settings = &(data->od8_settings);
1136 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1137 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1139 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1142 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1144 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1148 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1149 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1151 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1153 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1155 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1157 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1159 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1162 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1164 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1166 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1168 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1170 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1172 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1176 if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1177 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX;
1179 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0;
1181 if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1182 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT;
1184 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0;
1186 if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1187 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1188 OD8_ACOUSTIC_LIMIT_SCLK;
1190 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1193 if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1194 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1197 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1200 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1201 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1202 OD8_TEMPERATURE_FAN;
1204 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1207 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1208 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1209 OD8_TEMPERATURE_SYSTEM;
1211 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1217 static int vega20_od8_get_gfx_clock_base_voltage(
1218 struct pp_hwmgr *hwmgr,
1224 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1225 PPSMC_MSG_GetAVFSVoltageByDpm,
1226 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq),
1228 PP_ASSERT_WITH_CODE(!ret,
1229 "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!",
1232 *voltage = *voltage / VOLTAGE_SCALE;
1237 static int vega20_od8_initialize_default_settings(
1238 struct pp_hwmgr *hwmgr)
1240 struct phm_ppt_v3_information *pptable_information =
1241 (struct phm_ppt_v3_information *)hwmgr->pptable;
1242 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1243 struct vega20_od8_settings *od8_settings = &(data->od8_settings);
1244 OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table);
1247 /* Set Feature Capabilities */
1248 vega20_od8_set_feature_capabilities(hwmgr);
1250 /* Map FeatureID to individual settings */
1251 vega20_od8_set_feature_id(hwmgr);
1253 /* Set default values */
1254 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true);
1255 PP_ASSERT_WITH_CODE(!ret,
1256 "Failed to export over drive table!",
1259 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1260 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1261 od_table->GfxclkFmin;
1262 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1263 od_table->GfxclkFmax;
1265 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1267 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1271 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1272 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1273 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1274 od_table->GfxclkFreq1;
1276 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1277 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1278 od_table->GfxclkFreq3;
1280 od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2;
1281 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1282 od_table->GfxclkFreq2;
1284 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1285 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value),
1286 od_table->GfxclkFreq1),
1287 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1288 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0);
1289 od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1292 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1293 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value),
1294 od_table->GfxclkFreq2),
1295 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1296 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0);
1297 od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1300 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1301 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value),
1302 od_table->GfxclkFreq3),
1303 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1304 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0);
1305 od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1308 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1310 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value =
1312 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1314 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value =
1316 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1318 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value =
1322 if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1323 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1326 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1329 if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1330 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1331 od_table->OverDrivePct;
1333 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1336 if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1337 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1338 od_table->FanMaximumRpm;
1340 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1343 if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1344 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1345 od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100;
1347 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1350 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1351 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1352 od_table->FanTargetTemperature;
1354 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1357 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1358 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1359 od_table->MaxOpTemp;
1361 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1364 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1365 if (od8_settings->od8_settings_array[i].feature_id) {
1366 od8_settings->od8_settings_array[i].min_value =
1367 pptable_information->od_settings_min[i];
1368 od8_settings->od8_settings_array[i].max_value =
1369 pptable_information->od_settings_max[i];
1370 od8_settings->od8_settings_array[i].current_value =
1371 od8_settings->od8_settings_array[i].default_value;
1373 od8_settings->od8_settings_array[i].min_value =
1375 od8_settings->od8_settings_array[i].max_value =
1377 od8_settings->od8_settings_array[i].current_value =
1382 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false);
1383 PP_ASSERT_WITH_CODE(!ret,
1384 "Failed to import over drive table!",
1390 static int vega20_od8_set_settings(
1391 struct pp_hwmgr *hwmgr,
1395 OverDriveTable_t od_table;
1397 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1398 struct vega20_od8_single_setting *od8_settings =
1399 data->od8_settings.od8_settings_array;
1401 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true);
1402 PP_ASSERT_WITH_CODE(!ret,
1403 "Failed to export over drive table!",
1407 case OD8_SETTING_GFXCLK_FMIN:
1408 od_table.GfxclkFmin = (uint16_t)value;
1410 case OD8_SETTING_GFXCLK_FMAX:
1411 if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value ||
1412 value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value)
1415 od_table.GfxclkFmax = (uint16_t)value;
1417 case OD8_SETTING_GFXCLK_FREQ1:
1418 od_table.GfxclkFreq1 = (uint16_t)value;
1420 case OD8_SETTING_GFXCLK_VOLTAGE1:
1421 od_table.GfxclkVolt1 = (uint16_t)value;
1423 case OD8_SETTING_GFXCLK_FREQ2:
1424 od_table.GfxclkFreq2 = (uint16_t)value;
1426 case OD8_SETTING_GFXCLK_VOLTAGE2:
1427 od_table.GfxclkVolt2 = (uint16_t)value;
1429 case OD8_SETTING_GFXCLK_FREQ3:
1430 od_table.GfxclkFreq3 = (uint16_t)value;
1432 case OD8_SETTING_GFXCLK_VOLTAGE3:
1433 od_table.GfxclkVolt3 = (uint16_t)value;
1435 case OD8_SETTING_UCLK_FMAX:
1436 if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
1437 value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value)
1439 od_table.UclkFmax = (uint16_t)value;
1441 case OD8_SETTING_POWER_PERCENTAGE:
1442 od_table.OverDrivePct = (int16_t)value;
1444 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
1445 od_table.FanMaximumRpm = (uint16_t)value;
1447 case OD8_SETTING_FAN_MIN_SPEED:
1448 od_table.FanMinimumPwm = (uint16_t)value;
1450 case OD8_SETTING_FAN_TARGET_TEMP:
1451 od_table.FanTargetTemperature = (uint16_t)value;
1453 case OD8_SETTING_OPERATING_TEMP_MAX:
1454 od_table.MaxOpTemp = (uint16_t)value;
1458 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false);
1459 PP_ASSERT_WITH_CODE(!ret,
1460 "Failed to import over drive table!",
1466 static int vega20_get_sclk_od(
1467 struct pp_hwmgr *hwmgr)
1469 struct vega20_hwmgr *data = hwmgr->backend;
1470 struct vega20_single_dpm_table *sclk_table =
1471 &(data->dpm_table.gfx_table);
1472 struct vega20_single_dpm_table *golden_sclk_table =
1473 &(data->golden_dpm_table.gfx_table);
1474 int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
1475 int golden_value = golden_sclk_table->dpm_levels
1476 [golden_sclk_table->count - 1].value;
1479 value -= golden_value;
1480 value = DIV_ROUND_UP(value * 100, golden_value);
1485 static int vega20_set_sclk_od(
1486 struct pp_hwmgr *hwmgr, uint32_t value)
1488 struct vega20_hwmgr *data = hwmgr->backend;
1489 struct vega20_single_dpm_table *golden_sclk_table =
1490 &(data->golden_dpm_table.gfx_table);
1494 od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value;
1496 od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
1498 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk);
1499 PP_ASSERT_WITH_CODE(!ret,
1500 "[SetSclkOD] failed to set od gfxclk!",
1503 /* retrieve updated gfxclk table */
1504 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
1505 PP_ASSERT_WITH_CODE(!ret,
1506 "[SetSclkOD] failed to refresh gfxclk table!",
1512 static int vega20_get_mclk_od(
1513 struct pp_hwmgr *hwmgr)
1515 struct vega20_hwmgr *data = hwmgr->backend;
1516 struct vega20_single_dpm_table *mclk_table =
1517 &(data->dpm_table.mem_table);
1518 struct vega20_single_dpm_table *golden_mclk_table =
1519 &(data->golden_dpm_table.mem_table);
1520 int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
1521 int golden_value = golden_mclk_table->dpm_levels
1522 [golden_mclk_table->count - 1].value;
1525 value -= golden_value;
1526 value = DIV_ROUND_UP(value * 100, golden_value);
1531 static int vega20_set_mclk_od(
1532 struct pp_hwmgr *hwmgr, uint32_t value)
1534 struct vega20_hwmgr *data = hwmgr->backend;
1535 struct vega20_single_dpm_table *golden_mclk_table =
1536 &(data->golden_dpm_table.mem_table);
1540 od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value;
1542 od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
1544 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk);
1545 PP_ASSERT_WITH_CODE(!ret,
1546 "[SetMclkOD] failed to set od memclk!",
1549 /* retrieve updated memclk table */
1550 ret = vega20_setup_memclk_dpm_table(hwmgr);
1551 PP_ASSERT_WITH_CODE(!ret,
1552 "[SetMclkOD] failed to refresh memclk table!",
1558 static int vega20_populate_umdpstate_clocks(
1559 struct pp_hwmgr *hwmgr)
1561 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1562 struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table);
1563 struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table);
1565 hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value;
1566 hwmgr->pstate_mclk = mem_table->dpm_levels[0].value;
1568 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1569 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
1570 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1571 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1574 hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100;
1575 hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100;
1580 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr,
1581 PP_Clock *clock, PPCLK_e clock_select)
1585 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1586 PPSMC_MSG_GetDcModeMaxDpmFreq,
1587 (clock_select << 16),
1589 "[GetMaxSustainableClock] Failed to get max DC clock from SMC!",
1592 /* if DC limit is zero, return AC limit */
1594 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1595 PPSMC_MSG_GetMaxDpmFreq,
1596 (clock_select << 16),
1598 "[GetMaxSustainableClock] failed to get max AC clock from SMC!",
1605 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr)
1607 struct vega20_hwmgr *data =
1608 (struct vega20_hwmgr *)(hwmgr->backend);
1609 struct vega20_max_sustainable_clocks *max_sustainable_clocks =
1610 &(data->max_sustainable_clocks);
1613 max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100;
1614 max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100;
1615 max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100;
1616 max_sustainable_clocks->display_clock = 0xFFFFFFFF;
1617 max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
1618 max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
1620 if (data->smu_features[GNLD_DPM_UCLK].enabled)
1621 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1622 &(max_sustainable_clocks->uclock),
1624 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!",
1627 if (data->smu_features[GNLD_DPM_SOCCLK].enabled)
1628 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1629 &(max_sustainable_clocks->soc_clock),
1630 PPCLK_SOCCLK)) == 0,
1631 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!",
1634 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1635 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1636 &(max_sustainable_clocks->dcef_clock),
1637 PPCLK_DCEFCLK)) == 0,
1638 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!",
1640 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1641 &(max_sustainable_clocks->display_clock),
1642 PPCLK_DISPCLK)) == 0,
1643 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!",
1645 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1646 &(max_sustainable_clocks->phy_clock),
1647 PPCLK_PHYCLK)) == 0,
1648 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!",
1650 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1651 &(max_sustainable_clocks->pixel_clock),
1652 PPCLK_PIXCLK)) == 0,
1653 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!",
1657 if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
1658 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;
1663 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
1667 result = smum_send_msg_to_smc(hwmgr,
1668 PPSMC_MSG_SetMGpuFanBoostLimitRpm,
1670 PP_ASSERT_WITH_CODE(!result,
1671 "[EnableMgpuFan] Failed to enable mgpu fan boost!",
1677 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr)
1679 struct vega20_hwmgr *data =
1680 (struct vega20_hwmgr *)(hwmgr->backend);
1682 data->uvd_power_gated = true;
1683 data->vce_power_gated = true;
1686 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1690 smum_send_msg_to_smc_with_parameter(hwmgr,
1691 PPSMC_MSG_NumOfDisplays, 0, NULL);
1693 result = vega20_set_allowed_featuresmask(hwmgr);
1694 PP_ASSERT_WITH_CODE(!result,
1695 "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
1698 result = vega20_init_smc_table(hwmgr);
1699 PP_ASSERT_WITH_CODE(!result,
1700 "[EnableDPMTasks] Failed to initialize SMC table!",
1703 result = vega20_run_btc(hwmgr);
1704 PP_ASSERT_WITH_CODE(!result,
1705 "[EnableDPMTasks] Failed to run btc!",
1708 result = vega20_run_btc_afll(hwmgr);
1709 PP_ASSERT_WITH_CODE(!result,
1710 "[EnableDPMTasks] Failed to run btc afll!",
1713 result = vega20_enable_all_smu_features(hwmgr);
1714 PP_ASSERT_WITH_CODE(!result,
1715 "[EnableDPMTasks] Failed to enable all smu features!",
1718 result = vega20_override_pcie_parameters(hwmgr);
1719 PP_ASSERT_WITH_CODE(!result,
1720 "[EnableDPMTasks] Failed to override pcie parameters!",
1723 result = vega20_notify_smc_display_change(hwmgr);
1724 PP_ASSERT_WITH_CODE(!result,
1725 "[EnableDPMTasks] Failed to notify smc display change!",
1728 result = vega20_send_clock_ratio(hwmgr);
1729 PP_ASSERT_WITH_CODE(!result,
1730 "[EnableDPMTasks] Failed to send clock ratio!",
1733 /* Initialize UVD/VCE powergating state */
1734 vega20_init_powergate_state(hwmgr);
1736 result = vega20_setup_default_dpm_tables(hwmgr);
1737 PP_ASSERT_WITH_CODE(!result,
1738 "[EnableDPMTasks] Failed to setup default DPM tables!",
1741 result = vega20_init_max_sustainable_clocks(hwmgr);
1742 PP_ASSERT_WITH_CODE(!result,
1743 "[EnableDPMTasks] Failed to get maximum sustainable clocks!",
1746 result = vega20_power_control_set_level(hwmgr);
1747 PP_ASSERT_WITH_CODE(!result,
1748 "[EnableDPMTasks] Failed to power control set level!",
1751 result = vega20_od8_initialize_default_settings(hwmgr);
1752 PP_ASSERT_WITH_CODE(!result,
1753 "[EnableDPMTasks] Failed to initialize odn settings!",
1756 result = vega20_populate_umdpstate_clocks(hwmgr);
1757 PP_ASSERT_WITH_CODE(!result,
1758 "[EnableDPMTasks] Failed to populate umdpstate clocks!",
1761 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit,
1762 POWER_SOURCE_AC << 16, &hwmgr->default_power_limit);
1763 PP_ASSERT_WITH_CODE(!result,
1764 "[GetPptLimit] get default PPT limit failed!",
1766 hwmgr->power_limit =
1767 hwmgr->default_power_limit;
1772 static uint32_t vega20_find_lowest_dpm_level(
1773 struct vega20_single_dpm_table *table)
1777 for (i = 0; i < table->count; i++) {
1778 if (table->dpm_levels[i].enabled)
1781 if (i >= table->count) {
1783 table->dpm_levels[i].enabled = true;
1789 static uint32_t vega20_find_highest_dpm_level(
1790 struct vega20_single_dpm_table *table)
1794 PP_ASSERT_WITH_CODE(table != NULL,
1795 "[FindHighestDPMLevel] DPM Table does not exist!",
1797 PP_ASSERT_WITH_CODE(table->count > 0,
1798 "[FindHighestDPMLevel] DPM Table has no entry!",
1800 PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER,
1801 "[FindHighestDPMLevel] DPM Table has too many entries!",
1802 return MAX_REGULAR_DPM_NUMBER - 1);
1804 for (i = table->count - 1; i >= 0; i--) {
1805 if (table->dpm_levels[i].enabled)
1810 table->dpm_levels[i].enabled = true;
1816 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1818 struct vega20_hwmgr *data =
1819 (struct vega20_hwmgr *)(hwmgr->backend);
1823 if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1824 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1825 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
1826 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1827 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1828 (PPCLK_GFXCLK << 16) | (min_freq & 0xffff),
1830 "Failed to set soft min gfxclk !",
1834 if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1835 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1836 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
1837 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1838 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1839 (PPCLK_UCLK << 16) | (min_freq & 0xffff),
1841 "Failed to set soft min memclk !",
1845 if (data->smu_features[GNLD_DPM_UVD].enabled &&
1846 (feature_mask & FEATURE_DPM_UVD_MASK)) {
1847 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
1849 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1850 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1851 (PPCLK_VCLK << 16) | (min_freq & 0xffff),
1853 "Failed to set soft min vclk!",
1856 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level;
1858 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1859 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1860 (PPCLK_DCLK << 16) | (min_freq & 0xffff),
1862 "Failed to set soft min dclk!",
1866 if (data->smu_features[GNLD_DPM_VCE].enabled &&
1867 (feature_mask & FEATURE_DPM_VCE_MASK)) {
1868 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
1870 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1871 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1872 (PPCLK_ECLK << 16) | (min_freq & 0xffff),
1874 "Failed to set soft min eclk!",
1878 if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1879 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1880 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
1882 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1883 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1884 (PPCLK_SOCCLK << 16) | (min_freq & 0xffff),
1886 "Failed to set soft min socclk!",
1890 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1891 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1892 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
1894 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1895 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1896 (PPCLK_FCLK << 16) | (min_freq & 0xffff),
1898 "Failed to set soft min fclk!",
1902 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
1903 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1904 min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
1906 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1907 hwmgr, PPSMC_MSG_SetHardMinByFreq,
1908 (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff),
1910 "Failed to set hard min dcefclk!",
1917 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1919 struct vega20_hwmgr *data =
1920 (struct vega20_hwmgr *)(hwmgr->backend);
1924 if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1925 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1926 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
1928 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1929 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1930 (PPCLK_GFXCLK << 16) | (max_freq & 0xffff),
1932 "Failed to set soft max gfxclk!",
1936 if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1937 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1938 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
1940 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1941 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1942 (PPCLK_UCLK << 16) | (max_freq & 0xffff),
1944 "Failed to set soft max memclk!",
1948 if (data->smu_features[GNLD_DPM_UVD].enabled &&
1949 (feature_mask & FEATURE_DPM_UVD_MASK)) {
1950 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
1952 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1953 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1954 (PPCLK_VCLK << 16) | (max_freq & 0xffff),
1956 "Failed to set soft max vclk!",
1959 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level;
1960 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1961 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1962 (PPCLK_DCLK << 16) | (max_freq & 0xffff),
1964 "Failed to set soft max dclk!",
1968 if (data->smu_features[GNLD_DPM_VCE].enabled &&
1969 (feature_mask & FEATURE_DPM_VCE_MASK)) {
1970 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
1972 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1973 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1974 (PPCLK_ECLK << 16) | (max_freq & 0xffff),
1976 "Failed to set soft max eclk!",
1980 if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1981 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1982 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
1984 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1985 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1986 (PPCLK_SOCCLK << 16) | (max_freq & 0xffff),
1988 "Failed to set soft max socclk!",
1992 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1993 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1994 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
1996 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1997 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1998 (PPCLK_FCLK << 16) | (max_freq & 0xffff),
2000 "Failed to set soft max fclk!",
2007 static int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
2009 struct vega20_hwmgr *data =
2010 (struct vega20_hwmgr *)(hwmgr->backend);
2013 if (data->smu_features[GNLD_DPM_VCE].supported) {
2014 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) {
2016 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n");
2018 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n");
2021 ret = vega20_enable_smc_features(hwmgr,
2023 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap);
2024 PP_ASSERT_WITH_CODE(!ret,
2025 "Attempt to Enable/Disable DPM VCE Failed!",
2027 data->smu_features[GNLD_DPM_VCE].enabled = enable;
2033 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr,
2035 PPCLK_e clock_select,
2042 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2043 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16),
2045 "[GetClockRanges] Failed to get max clock from SMC!",
2048 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2049 PPSMC_MSG_GetMinDpmFreq,
2050 (clock_select << 16),
2052 "[GetClockRanges] Failed to get min clock from SMC!",
2059 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
2061 struct vega20_hwmgr *data =
2062 (struct vega20_hwmgr *)(hwmgr->backend);
2066 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled,
2067 "[GetSclks]: gfxclk dpm not enabled!\n",
2071 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false);
2072 PP_ASSERT_WITH_CODE(!ret,
2073 "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
2076 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true);
2077 PP_ASSERT_WITH_CODE(!ret,
2078 "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
2082 return (gfx_clk * 100);
2085 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
2087 struct vega20_hwmgr *data =
2088 (struct vega20_hwmgr *)(hwmgr->backend);
2092 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled,
2093 "[MemMclks]: memclk dpm not enabled!\n",
2097 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false);
2098 PP_ASSERT_WITH_CODE(!ret,
2099 "[GetMclks]: fail to get min PPCLK_UCLK\n",
2102 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true);
2103 PP_ASSERT_WITH_CODE(!ret,
2104 "[GetMclks]: fail to get max PPCLK_UCLK\n",
2108 return (mem_clk * 100);
2111 static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr,
2112 SmuMetrics_t *metrics_table,
2115 struct vega20_hwmgr *data =
2116 (struct vega20_hwmgr *)(hwmgr->backend);
2120 !data->metrics_time ||
2121 time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) {
2122 ret = smum_smc_table_manager(hwmgr,
2123 (uint8_t *)(&data->metrics_table),
2127 pr_info("Failed to export SMU metrics table!\n");
2130 data->metrics_time = jiffies;
2134 memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t));
2139 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
2143 SmuMetrics_t metrics_table;
2145 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false);
2149 /* For the 40.46 release, they changed the value name */
2150 if (hwmgr->smu_version == 0x282e00)
2151 *query = metrics_table.AverageSocketPower << 8;
2153 *query = metrics_table.CurrSocketPower << 8;
2158 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr,
2159 PPCLK_e clk_id, uint32_t *clk_freq)
2165 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2166 PPSMC_MSG_GetDpmClockFreq, (clk_id << 16),
2168 "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!",
2171 *clk_freq = *clk_freq * 100;
2176 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr,
2178 uint32_t *activity_percent)
2181 SmuMetrics_t metrics_table;
2183 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false);
2188 case AMDGPU_PP_SENSOR_GPU_LOAD:
2189 *activity_percent = metrics_table.AverageGfxActivity;
2191 case AMDGPU_PP_SENSOR_MEM_LOAD:
2192 *activity_percent = metrics_table.AverageUclkActivity;
2195 pr_err("Invalid index for retrieving clock activity\n");
2202 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
2203 void *value, int *size)
2205 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2206 struct amdgpu_device *adev = hwmgr->adev;
2207 SmuMetrics_t metrics_table;
2212 case AMDGPU_PP_SENSOR_GFX_SCLK:
2213 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false);
2217 *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100;
2220 case AMDGPU_PP_SENSOR_GFX_MCLK:
2221 ret = vega20_get_current_clk_freq(hwmgr,
2227 case AMDGPU_PP_SENSOR_GPU_LOAD:
2228 case AMDGPU_PP_SENSOR_MEM_LOAD:
2229 ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value);
2233 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2234 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr);
2237 case AMDGPU_PP_SENSOR_EDGE_TEMP:
2238 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false);
2242 *((uint32_t *)value) = metrics_table.TemperatureEdge *
2243 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2246 case AMDGPU_PP_SENSOR_MEM_TEMP:
2247 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false);
2251 *((uint32_t *)value) = metrics_table.TemperatureHBM *
2252 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2255 case AMDGPU_PP_SENSOR_UVD_POWER:
2256 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
2259 case AMDGPU_PP_SENSOR_VCE_POWER:
2260 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
2263 case AMDGPU_PP_SENSOR_GPU_POWER:
2265 ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value);
2267 case AMDGPU_PP_SENSOR_VDDGFX:
2268 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
2269 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
2270 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
2271 *((uint32_t *)value) =
2272 (uint32_t)convert_to_vddc((uint8_t)val_vid);
2274 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
2275 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value);
2286 static int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
2287 struct pp_display_clock_request *clock_req)
2290 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2291 enum amd_pp_clock_type clk_type = clock_req->clock_type;
2292 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
2293 PPCLK_e clk_select = 0;
2294 uint32_t clk_request = 0;
2296 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
2298 case amd_pp_dcef_clock:
2299 clk_select = PPCLK_DCEFCLK;
2301 case amd_pp_disp_clock:
2302 clk_select = PPCLK_DISPCLK;
2304 case amd_pp_pixel_clock:
2305 clk_select = PPCLK_PIXCLK;
2307 case amd_pp_phy_clock:
2308 clk_select = PPCLK_PHYCLK;
2311 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
2317 clk_request = (clk_select << 16) | clk_freq;
2318 result = smum_send_msg_to_smc_with_parameter(hwmgr,
2319 PPSMC_MSG_SetHardMinByFreq,
2328 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
2329 PHM_PerformanceLevelDesignation designation, uint32_t index,
2330 PHM_PerformanceLevel *level)
2335 static int vega20_notify_smc_display_config_after_ps_adjustment(
2336 struct pp_hwmgr *hwmgr)
2338 struct vega20_hwmgr *data =
2339 (struct vega20_hwmgr *)(hwmgr->backend);
2340 struct vega20_single_dpm_table *dpm_table =
2341 &data->dpm_table.mem_table;
2342 struct PP_Clocks min_clocks = {0};
2343 struct pp_display_clock_request clock_req;
2346 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
2347 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
2348 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
2350 if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
2351 clock_req.clock_type = amd_pp_dcef_clock;
2352 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
2353 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) {
2354 if (data->smu_features[GNLD_DS_DCEFCLK].supported)
2355 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(
2356 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
2357 min_clocks.dcefClockInSR / 100,
2359 "Attempt to set divider for DCEFCLK Failed!",
2362 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2366 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2367 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100;
2368 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2369 PPSMC_MSG_SetHardMinByFreq,
2370 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level,
2372 "[SetHardMinFreq] Set hard min uclk failed!",
2379 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
2381 struct vega20_hwmgr *data =
2382 (struct vega20_hwmgr *)(hwmgr->backend);
2383 uint32_t soft_level;
2386 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2388 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2389 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2390 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2392 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2394 data->dpm_table.mem_table.dpm_state.soft_min_level =
2395 data->dpm_table.mem_table.dpm_state.soft_max_level =
2396 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2398 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
2400 data->dpm_table.soc_table.dpm_state.soft_min_level =
2401 data->dpm_table.soc_table.dpm_state.soft_max_level =
2402 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2404 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2405 FEATURE_DPM_UCLK_MASK |
2406 FEATURE_DPM_SOCCLK_MASK);
2407 PP_ASSERT_WITH_CODE(!ret,
2408 "Failed to upload boot level to highest!",
2411 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2412 FEATURE_DPM_UCLK_MASK |
2413 FEATURE_DPM_SOCCLK_MASK);
2414 PP_ASSERT_WITH_CODE(!ret,
2415 "Failed to upload dpm max level to highest!",
2421 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
2423 struct vega20_hwmgr *data =
2424 (struct vega20_hwmgr *)(hwmgr->backend);
2425 uint32_t soft_level;
2428 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2430 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2431 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2432 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2434 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2436 data->dpm_table.mem_table.dpm_state.soft_min_level =
2437 data->dpm_table.mem_table.dpm_state.soft_max_level =
2438 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2440 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
2442 data->dpm_table.soc_table.dpm_state.soft_min_level =
2443 data->dpm_table.soc_table.dpm_state.soft_max_level =
2444 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2446 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2447 FEATURE_DPM_UCLK_MASK |
2448 FEATURE_DPM_SOCCLK_MASK);
2449 PP_ASSERT_WITH_CODE(!ret,
2450 "Failed to upload boot level to highest!",
2453 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2454 FEATURE_DPM_UCLK_MASK |
2455 FEATURE_DPM_SOCCLK_MASK);
2456 PP_ASSERT_WITH_CODE(!ret,
2457 "Failed to upload dpm max level to highest!",
2464 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
2466 struct vega20_hwmgr *data =
2467 (struct vega20_hwmgr *)(hwmgr->backend);
2468 uint32_t soft_min_level, soft_max_level;
2471 /* gfxclk soft min/max settings */
2473 vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2475 vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2477 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2478 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2479 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2480 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2482 /* uclk soft min/max settings */
2484 vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2486 vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2488 data->dpm_table.mem_table.dpm_state.soft_min_level =
2489 data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2490 data->dpm_table.mem_table.dpm_state.soft_max_level =
2491 data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2493 /* socclk soft min/max settings */
2495 vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
2497 vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
2499 data->dpm_table.soc_table.dpm_state.soft_min_level =
2500 data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
2501 data->dpm_table.soc_table.dpm_state.soft_max_level =
2502 data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
2504 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2505 FEATURE_DPM_UCLK_MASK |
2506 FEATURE_DPM_SOCCLK_MASK);
2507 PP_ASSERT_WITH_CODE(!ret,
2508 "Failed to upload DPM Bootup Levels!",
2511 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2512 FEATURE_DPM_UCLK_MASK |
2513 FEATURE_DPM_SOCCLK_MASK);
2514 PP_ASSERT_WITH_CODE(!ret,
2515 "Failed to upload DPM Max Levels!",
2521 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
2522 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
2524 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2525 struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table);
2526 struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table);
2527 struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table);
2533 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
2534 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
2535 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
2536 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
2537 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2538 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2541 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2543 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2545 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2546 *sclk_mask = gfx_dpm_table->count - 1;
2547 *mclk_mask = mem_dpm_table->count - 1;
2548 *soc_mask = soc_dpm_table->count - 1;
2554 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
2555 enum pp_clock_type type, uint32_t mask)
2557 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2558 uint32_t soft_min_level, soft_max_level, hard_min_level;
2563 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2564 soft_max_level = mask ? (fls(mask) - 1) : 0;
2566 if (soft_max_level >= data->dpm_table.gfx_table.count) {
2567 pr_err("Clock level specified %d is over max allowed %d\n",
2569 data->dpm_table.gfx_table.count - 1);
2573 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2574 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2575 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2576 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2578 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2579 PP_ASSERT_WITH_CODE(!ret,
2580 "Failed to upload boot level to lowest!",
2583 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2584 PP_ASSERT_WITH_CODE(!ret,
2585 "Failed to upload dpm max level to highest!",
2590 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2591 soft_max_level = mask ? (fls(mask) - 1) : 0;
2593 if (soft_max_level >= data->dpm_table.mem_table.count) {
2594 pr_err("Clock level specified %d is over max allowed %d\n",
2596 data->dpm_table.mem_table.count - 1);
2600 data->dpm_table.mem_table.dpm_state.soft_min_level =
2601 data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2602 data->dpm_table.mem_table.dpm_state.soft_max_level =
2603 data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2605 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2606 PP_ASSERT_WITH_CODE(!ret,
2607 "Failed to upload boot level to lowest!",
2610 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2611 PP_ASSERT_WITH_CODE(!ret,
2612 "Failed to upload dpm max level to highest!",
2618 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2619 soft_max_level = mask ? (fls(mask) - 1) : 0;
2621 if (soft_max_level >= data->dpm_table.soc_table.count) {
2622 pr_err("Clock level specified %d is over max allowed %d\n",
2624 data->dpm_table.soc_table.count - 1);
2628 data->dpm_table.soc_table.dpm_state.soft_min_level =
2629 data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
2630 data->dpm_table.soc_table.dpm_state.soft_max_level =
2631 data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
2633 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2634 PP_ASSERT_WITH_CODE(!ret,
2635 "Failed to upload boot level to lowest!",
2638 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2639 PP_ASSERT_WITH_CODE(!ret,
2640 "Failed to upload dpm max level to highest!",
2646 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2647 soft_max_level = mask ? (fls(mask) - 1) : 0;
2649 if (soft_max_level >= data->dpm_table.fclk_table.count) {
2650 pr_err("Clock level specified %d is over max allowed %d\n",
2652 data->dpm_table.fclk_table.count - 1);
2656 data->dpm_table.fclk_table.dpm_state.soft_min_level =
2657 data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
2658 data->dpm_table.fclk_table.dpm_state.soft_max_level =
2659 data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
2661 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2662 PP_ASSERT_WITH_CODE(!ret,
2663 "Failed to upload boot level to lowest!",
2666 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2667 PP_ASSERT_WITH_CODE(!ret,
2668 "Failed to upload dpm max level to highest!",
2674 hard_min_level = mask ? (ffs(mask) - 1) : 0;
2676 if (hard_min_level >= data->dpm_table.dcef_table.count) {
2677 pr_err("Clock level specified %d is over max allowed %d\n",
2679 data->dpm_table.dcef_table.count - 1);
2683 data->dpm_table.dcef_table.dpm_state.hard_min_level =
2684 data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
2686 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
2687 PP_ASSERT_WITH_CODE(!ret,
2688 "Failed to upload boot level to lowest!",
2691 //TODO: Setting DCEFCLK max dpm level is not supported
2696 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2697 soft_max_level = mask ? (fls(mask) - 1) : 0;
2698 if (soft_min_level >= NUM_LINK_LEVELS ||
2699 soft_max_level >= NUM_LINK_LEVELS)
2702 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2703 PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level,
2705 PP_ASSERT_WITH_CODE(!ret,
2706 "Failed to set min link dpm level!",
2718 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
2719 enum amd_dpm_forced_level level)
2722 uint32_t sclk_mask, mclk_mask, soc_mask;
2725 case AMD_DPM_FORCED_LEVEL_HIGH:
2726 ret = vega20_force_dpm_highest(hwmgr);
2729 case AMD_DPM_FORCED_LEVEL_LOW:
2730 ret = vega20_force_dpm_lowest(hwmgr);
2733 case AMD_DPM_FORCED_LEVEL_AUTO:
2734 ret = vega20_unforce_dpm_levels(hwmgr);
2737 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
2738 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
2739 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
2740 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
2741 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
2744 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
2745 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
2746 vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask);
2749 case AMD_DPM_FORCED_LEVEL_MANUAL:
2750 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
2758 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr)
2760 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2762 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
2763 return AMD_FAN_CTRL_MANUAL;
2765 return AMD_FAN_CTRL_AUTO;
2768 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
2771 case AMD_FAN_CTRL_NONE:
2772 vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
2774 case AMD_FAN_CTRL_MANUAL:
2775 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2776 vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
2778 case AMD_FAN_CTRL_AUTO:
2779 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2780 vega20_fan_ctrl_start_smc_fan_control(hwmgr);
2787 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr,
2788 struct amd_pp_simple_clock_info *info)
2791 struct phm_ppt_v2_information *table_info =
2792 (struct phm_ppt_v2_information *)hwmgr->pptable;
2793 struct phm_clock_and_voltage_limits *max_limits =
2794 &table_info->max_clock_voltage_on_ac;
2796 info->engine_max_clock = max_limits->sclk;
2797 info->memory_max_clock = max_limits->mclk;
2803 static int vega20_get_sclks(struct pp_hwmgr *hwmgr,
2804 struct pp_clock_levels_with_latency *clocks)
2806 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2807 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2810 if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
2813 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2814 clocks->num_levels = count;
2816 for (i = 0; i < count; i++) {
2817 clocks->data[i].clocks_in_khz =
2818 dpm_table->dpm_levels[i].value * 1000;
2819 clocks->data[i].latency_in_us = 0;
2825 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr,
2831 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr,
2832 struct pp_clock_levels_with_latency *clocks)
2834 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2835 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table);
2838 if (!data->smu_features[GNLD_DPM_UCLK].enabled)
2841 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2842 clocks->num_levels = data->mclk_latency_table.count = count;
2844 for (i = 0; i < count; i++) {
2845 clocks->data[i].clocks_in_khz =
2846 data->mclk_latency_table.entries[i].frequency =
2847 dpm_table->dpm_levels[i].value * 1000;
2848 clocks->data[i].latency_in_us =
2849 data->mclk_latency_table.entries[i].latency =
2850 vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
2856 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr,
2857 struct pp_clock_levels_with_latency *clocks)
2859 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2860 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table);
2863 if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled)
2866 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2867 clocks->num_levels = count;
2869 for (i = 0; i < count; i++) {
2870 clocks->data[i].clocks_in_khz =
2871 dpm_table->dpm_levels[i].value * 1000;
2872 clocks->data[i].latency_in_us = 0;
2878 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr,
2879 struct pp_clock_levels_with_latency *clocks)
2881 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2882 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table);
2885 if (!data->smu_features[GNLD_DPM_SOCCLK].enabled)
2888 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2889 clocks->num_levels = count;
2891 for (i = 0; i < count; i++) {
2892 clocks->data[i].clocks_in_khz =
2893 dpm_table->dpm_levels[i].value * 1000;
2894 clocks->data[i].latency_in_us = 0;
2901 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
2902 enum amd_pp_clock_type type,
2903 struct pp_clock_levels_with_latency *clocks)
2908 case amd_pp_sys_clock:
2909 ret = vega20_get_sclks(hwmgr, clocks);
2911 case amd_pp_mem_clock:
2912 ret = vega20_get_memclocks(hwmgr, clocks);
2914 case amd_pp_dcef_clock:
2915 ret = vega20_get_dcefclocks(hwmgr, clocks);
2917 case amd_pp_soc_clock:
2918 ret = vega20_get_socclocks(hwmgr, clocks);
2927 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
2928 enum amd_pp_clock_type type,
2929 struct pp_clock_levels_with_voltage *clocks)
2931 clocks->num_levels = 0;
2936 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
2939 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2940 Watermarks_t *table = &(data->smc_state_table.water_marks_table);
2941 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
2943 if (!data->registry_data.disable_water_mark &&
2944 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2945 data->smu_features[GNLD_DPM_SOCCLK].supported) {
2946 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
2947 data->water_marks_bitmap |= WaterMarksExist;
2948 data->water_marks_bitmap &= ~WaterMarksLoaded;
2954 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2955 enum PP_OD_DPM_TABLE_COMMAND type,
2956 long *input, uint32_t size)
2958 struct vega20_hwmgr *data =
2959 (struct vega20_hwmgr *)(hwmgr->backend);
2960 struct vega20_od8_single_setting *od8_settings =
2961 data->od8_settings.od8_settings_array;
2962 OverDriveTable_t *od_table =
2963 &(data->smc_state_table.overdrive_table);
2964 int32_t input_index, input_clk, input_vol, i;
2968 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
2972 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2973 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2974 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2975 pr_info("Sclk min/max frequency overdrive not supported\n");
2979 for (i = 0; i < size; i += 2) {
2981 pr_info("invalid number of input parameters %d\n",
2986 input_index = input[i];
2987 input_clk = input[i + 1];
2989 if (input_index != 0 && input_index != 1) {
2990 pr_info("Invalid index %d\n", input_index);
2991 pr_info("Support min/max sclk frequency setting only which index by 0/1\n");
2995 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2996 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2997 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2999 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
3000 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
3004 if ((input_index == 0 && od_table->GfxclkFmin != input_clk) ||
3005 (input_index == 1 && od_table->GfxclkFmax != input_clk))
3006 data->gfxclk_overdrive = true;
3008 if (input_index == 0)
3009 od_table->GfxclkFmin = input_clk;
3011 od_table->GfxclkFmax = input_clk;
3016 case PP_OD_EDIT_MCLK_VDDC_TABLE:
3017 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3018 pr_info("Mclk max frequency overdrive not supported\n");
3022 for (i = 0; i < size; i += 2) {
3024 pr_info("invalid number of input parameters %d\n",
3029 input_index = input[i];
3030 input_clk = input[i + 1];
3032 if (input_index != 1) {
3033 pr_info("Invalid index %d\n", input_index);
3034 pr_info("Support max Mclk frequency setting only which index by 1\n");
3038 if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
3039 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) {
3040 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
3042 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
3043 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
3047 if (input_index == 1 && od_table->UclkFmax != input_clk)
3048 data->memclk_overdrive = true;
3050 od_table->UclkFmax = input_clk;
3055 case PP_OD_EDIT_VDDC_CURVE:
3056 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3057 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3058 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3059 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3060 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3061 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
3062 pr_info("Voltage curve calibrate not supported\n");
3066 for (i = 0; i < size; i += 3) {
3068 pr_info("invalid number of input parameters %d\n",
3073 input_index = input[i];
3074 input_clk = input[i + 1];
3075 input_vol = input[i + 2];
3077 if (input_index > 2) {
3078 pr_info("Setting for point %d is not supported\n",
3080 pr_info("Three supported points index by 0, 1, 2\n");
3084 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
3085 if (input_clk < od8_settings[od8_id].min_value ||
3086 input_clk > od8_settings[od8_id].max_value) {
3087 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
3089 od8_settings[od8_id].min_value,
3090 od8_settings[od8_id].max_value);
3094 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
3095 if (input_vol < od8_settings[od8_id].min_value ||
3096 input_vol > od8_settings[od8_id].max_value) {
3097 pr_info("clock voltage %d is not within allowed range [%d - %d]\n",
3099 od8_settings[od8_id].min_value,
3100 od8_settings[od8_id].max_value);
3104 switch (input_index) {
3106 od_table->GfxclkFreq1 = input_clk;
3107 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
3110 od_table->GfxclkFreq2 = input_clk;
3111 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
3114 od_table->GfxclkFreq3 = input_clk;
3115 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
3121 case PP_OD_RESTORE_DEFAULT_TABLE:
3122 data->gfxclk_overdrive = false;
3123 data->memclk_overdrive = false;
3125 ret = smum_smc_table_manager(hwmgr,
3126 (uint8_t *)od_table,
3127 TABLE_OVERDRIVE, true);
3128 PP_ASSERT_WITH_CODE(!ret,
3129 "Failed to export overdrive table!",
3133 case PP_OD_COMMIT_DPM_TABLE:
3134 ret = smum_smc_table_manager(hwmgr,
3135 (uint8_t *)od_table,
3136 TABLE_OVERDRIVE, false);
3137 PP_ASSERT_WITH_CODE(!ret,
3138 "Failed to import overdrive table!",
3141 /* retrieve updated gfxclk table */
3142 if (data->gfxclk_overdrive) {
3143 data->gfxclk_overdrive = false;
3145 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
3150 /* retrieve updated memclk table */
3151 if (data->memclk_overdrive) {
3152 data->memclk_overdrive = false;
3154 ret = vega20_setup_memclk_dpm_table(hwmgr);
3167 static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr,
3168 enum pp_mp1_state mp1_state)
3173 switch (mp1_state) {
3174 case PP_MP1_STATE_SHUTDOWN:
3175 msg = PPSMC_MSG_PrepareMp1ForShutdown;
3177 case PP_MP1_STATE_UNLOAD:
3178 msg = PPSMC_MSG_PrepareMp1ForUnload;
3180 case PP_MP1_STATE_RESET:
3181 msg = PPSMC_MSG_PrepareMp1ForReset;
3183 case PP_MP1_STATE_NONE:
3188 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0,
3189 "[PrepareMp1] Failed!",
3195 static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
3197 static const char *ppfeature_name[] = {
3232 static const char *output_title[] = {
3236 uint64_t features_enabled;
3241 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3242 PP_ASSERT_WITH_CODE(!ret,
3243 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
3246 size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
3247 size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
3251 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3252 size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
3255 (features_enabled & (1ULL << i)) ? "Y" : "N");
3261 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
3263 struct vega20_hwmgr *data =
3264 (struct vega20_hwmgr *)(hwmgr->backend);
3265 uint64_t features_enabled, features_to_enable, features_to_disable;
3269 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
3272 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3276 features_to_disable =
3277 features_enabled & ~new_ppfeature_masks;
3278 features_to_enable =
3279 ~features_enabled & new_ppfeature_masks;
3281 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
3282 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
3284 if (features_to_disable) {
3285 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
3290 if (features_to_enable) {
3291 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
3296 /* Update the cached feature enablement state */
3297 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3301 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3302 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
3304 data->smu_features[i].enabled = enabled;
3310 static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr)
3312 struct amdgpu_device *adev = hwmgr->adev;
3314 return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
3315 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
3316 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
3319 static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr)
3321 uint32_t width_level;
3323 width_level = vega20_get_current_pcie_link_width_level(hwmgr);
3324 if (width_level > LINK_WIDTH_MAX)
3327 return link_width[width_level];
3330 static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
3332 struct amdgpu_device *adev = hwmgr->adev;
3334 return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
3335 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
3336 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
3339 static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr)
3341 uint32_t speed_level;
3343 speed_level = vega20_get_current_pcie_link_speed_level(hwmgr);
3344 if (speed_level > LINK_SPEED_MAX)
3347 return link_speed[speed_level];
3350 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
3351 enum pp_clock_type type, char *buf)
3353 struct vega20_hwmgr *data =
3354 (struct vega20_hwmgr *)(hwmgr->backend);
3355 struct vega20_od8_single_setting *od8_settings =
3356 data->od8_settings.od8_settings_array;
3357 OverDriveTable_t *od_table =
3358 &(data->smc_state_table.overdrive_table);
3359 PPTable_t *pptable = &(data->smc_state_table.pp_table);
3360 struct pp_clock_levels_with_latency clocks;
3361 struct vega20_single_dpm_table *fclk_dpm_table =
3362 &(data->dpm_table.fclk_table);
3363 int i, now, size = 0;
3365 uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
3369 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now);
3370 PP_ASSERT_WITH_CODE(!ret,
3371 "Attempt to get current gfx clk Failed!",
3374 if (vega20_get_sclks(hwmgr, &clocks)) {
3375 size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
3380 for (i = 0; i < clocks.num_levels; i++)
3381 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
3382 i, clocks.data[i].clocks_in_khz / 1000,
3383 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3387 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now);
3388 PP_ASSERT_WITH_CODE(!ret,
3389 "Attempt to get current mclk freq Failed!",
3392 if (vega20_get_memclocks(hwmgr, &clocks)) {
3393 size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
3398 for (i = 0; i < clocks.num_levels; i++)
3399 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
3400 i, clocks.data[i].clocks_in_khz / 1000,
3401 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3405 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
3406 PP_ASSERT_WITH_CODE(!ret,
3407 "Attempt to get current socclk freq Failed!",
3410 if (vega20_get_socclocks(hwmgr, &clocks)) {
3411 size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
3416 for (i = 0; i < clocks.num_levels; i++)
3417 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
3418 i, clocks.data[i].clocks_in_khz / 1000,
3419 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3423 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
3424 PP_ASSERT_WITH_CODE(!ret,
3425 "Attempt to get current fclk freq Failed!",
3428 for (i = 0; i < fclk_dpm_table->count; i++)
3429 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
3430 i, fclk_dpm_table->dpm_levels[i].value,
3431 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
3435 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
3436 PP_ASSERT_WITH_CODE(!ret,
3437 "Attempt to get current dcefclk freq Failed!",
3440 if (vega20_get_dcefclocks(hwmgr, &clocks)) {
3441 size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
3446 for (i = 0; i < clocks.num_levels; i++)
3447 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
3448 i, clocks.data[i].clocks_in_khz / 1000,
3449 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3454 vega20_get_current_pcie_link_speed_level(hwmgr);
3455 current_lane_width =
3456 vega20_get_current_pcie_link_width_level(hwmgr);
3457 for (i = 0; i < NUM_LINK_LEVELS; i++) {
3458 gen_speed = pptable->PcieGenSpeed[i];
3459 lane_width = pptable->PcieLaneCount[i];
3461 size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
3462 (gen_speed == 0) ? "2.5GT/s," :
3463 (gen_speed == 1) ? "5.0GT/s," :
3464 (gen_speed == 2) ? "8.0GT/s," :
3465 (gen_speed == 3) ? "16.0GT/s," : "",
3466 (lane_width == 1) ? "x1" :
3467 (lane_width == 2) ? "x2" :
3468 (lane_width == 3) ? "x4" :
3469 (lane_width == 4) ? "x8" :
3470 (lane_width == 5) ? "x12" :
3471 (lane_width == 6) ? "x16" : "",
3472 pptable->LclkFreq[i],
3473 (current_gen_speed == gen_speed) &&
3474 (current_lane_width == lane_width) ?
3480 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3481 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3482 size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
3483 size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
3484 od_table->GfxclkFmin);
3485 size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
3486 od_table->GfxclkFmax);
3491 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3492 size = sysfs_emit(buf, "%s:\n", "OD_MCLK");
3493 size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
3494 od_table->UclkFmax);
3500 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3501 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3502 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3503 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3504 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3505 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3506 size = sysfs_emit(buf, "%s:\n", "OD_VDDC_CURVE");
3507 size += sysfs_emit_at(buf, size, "0: %10uMhz %10dmV\n",
3508 od_table->GfxclkFreq1,
3509 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
3510 size += sysfs_emit_at(buf, size, "1: %10uMhz %10dmV\n",
3511 od_table->GfxclkFreq2,
3512 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
3513 size += sysfs_emit_at(buf, size, "2: %10uMhz %10dmV\n",
3514 od_table->GfxclkFreq3,
3515 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
3521 size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
3523 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3524 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3525 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
3526 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
3527 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
3530 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3531 size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
3532 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
3533 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
3536 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3537 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3538 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3539 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3540 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3541 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3542 size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
3543 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
3544 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
3545 size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
3546 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
3547 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
3548 size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
3549 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
3550 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
3551 size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
3552 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
3553 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
3554 size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
3555 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
3556 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
3557 size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
3558 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
3559 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
3569 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
3570 struct vega20_single_dpm_table *dpm_table)
3572 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3575 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
3576 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3577 "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
3579 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
3580 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
3583 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3584 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3585 PPSMC_MSG_SetHardMinByFreq,
3586 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level,
3588 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
3595 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr)
3597 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3598 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table);
3601 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
3602 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3603 "[SetFclkToHightestDpmLevel] Dpm table has no entry!",
3605 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS,
3606 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!",
3609 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3610 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3611 PPSMC_MSG_SetSoftMinByFreq,
3612 (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level,
3614 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!",
3621 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3623 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3626 smum_send_msg_to_smc_with_parameter(hwmgr,
3627 PPSMC_MSG_NumOfDisplays, 0, NULL);
3629 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr,
3630 &data->dpm_table.mem_table);
3634 return vega20_set_fclk_to_highest_dpm_level(hwmgr);
3637 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3639 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3641 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
3643 if ((data->water_marks_bitmap & WaterMarksExist) &&
3644 !(data->water_marks_bitmap & WaterMarksLoaded)) {
3645 result = smum_smc_table_manager(hwmgr,
3646 (uint8_t *)wm_table, TABLE_WATERMARKS, false);
3647 PP_ASSERT_WITH_CODE(!result,
3648 "Failed to update WMTABLE!",
3650 data->water_marks_bitmap |= WaterMarksLoaded;
3653 if ((data->water_marks_bitmap & WaterMarksExist) &&
3654 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
3655 data->smu_features[GNLD_DPM_SOCCLK].supported) {
3656 result = smum_send_msg_to_smc_with_parameter(hwmgr,
3657 PPSMC_MSG_NumOfDisplays,
3658 hwmgr->display_config->num_display,
3665 static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
3667 struct vega20_hwmgr *data =
3668 (struct vega20_hwmgr *)(hwmgr->backend);
3671 if (data->smu_features[GNLD_DPM_UVD].supported) {
3672 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) {
3674 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n");
3676 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n");
3679 ret = vega20_enable_smc_features(hwmgr,
3681 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap);
3682 PP_ASSERT_WITH_CODE(!ret,
3683 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!",
3685 data->smu_features[GNLD_DPM_UVD].enabled = enable;
3691 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
3693 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3695 if (data->vce_power_gated == bgate)
3698 data->vce_power_gated = bgate;
3700 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3701 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3702 AMD_IP_BLOCK_TYPE_VCE,
3705 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3706 AMD_IP_BLOCK_TYPE_VCE,
3707 AMD_PG_STATE_UNGATE);
3708 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3713 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
3715 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3717 if (data->uvd_power_gated == bgate)
3720 data->uvd_power_gated = bgate;
3721 vega20_enable_disable_uvd_dpm(hwmgr, !bgate);
3724 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
3726 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3727 struct vega20_single_dpm_table *dpm_table;
3728 bool vblank_too_short = false;
3729 bool disable_mclk_switching;
3730 bool disable_fclk_switching;
3731 uint32_t i, latency;
3733 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
3734 !hwmgr->display_config->multi_monitor_in_sync) ||
3736 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3739 dpm_table = &(data->dpm_table.gfx_table);
3740 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3741 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3742 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3743 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3745 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3746 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
3747 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3748 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3751 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3752 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3753 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3756 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3757 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3758 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3763 dpm_table = &(data->dpm_table.mem_table);
3764 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3765 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3766 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3767 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3769 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3770 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
3771 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3772 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3775 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
3776 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3777 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3780 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3781 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3782 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3786 /* honour DAL's UCLK Hardmin */
3787 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
3788 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
3790 /* Hardmin is dependent on displayconfig */
3791 if (disable_mclk_switching) {
3792 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3793 for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
3794 if (data->mclk_latency_table.entries[i].latency <= latency) {
3795 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
3796 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
3803 if (hwmgr->display_config->nb_pstate_switch_disable)
3804 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3806 if ((disable_mclk_switching &&
3807 (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) ||
3808 hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value)
3809 disable_fclk_switching = true;
3811 disable_fclk_switching = false;
3814 dpm_table = &(data->dpm_table.fclk_table);
3815 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3816 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3817 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3818 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3819 if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching)
3820 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3823 dpm_table = &(data->dpm_table.vclk_table);
3824 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3825 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3826 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3827 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3829 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3830 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3831 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3832 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3835 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3836 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3837 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3842 dpm_table = &(data->dpm_table.dclk_table);
3843 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3844 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3845 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3846 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3848 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3849 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3850 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3851 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3854 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3855 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3856 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3861 dpm_table = &(data->dpm_table.soc_table);
3862 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3863 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3864 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3865 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3867 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3868 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
3869 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3870 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3873 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3874 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3875 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3880 dpm_table = &(data->dpm_table.eclk_table);
3881 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3882 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3883 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3884 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3886 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3887 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
3888 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3889 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3892 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3893 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3894 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3902 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
3904 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3905 bool is_update_required = false;
3907 if (data->display_timing.num_existing_displays !=
3908 hwmgr->display_config->num_display)
3909 is_update_required = true;
3911 if (data->registry_data.gfx_clk_deep_sleep_support &&
3912 (data->display_timing.min_clock_in_sr !=
3913 hwmgr->display_config->min_core_set_clock_in_sr))
3914 is_update_required = true;
3916 return is_update_required;
3919 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
3923 ret = vega20_disable_all_smu_features(hwmgr);
3924 PP_ASSERT_WITH_CODE(!ret,
3925 "[DisableDpmTasks] Failed to disable all smu features!",
3931 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr)
3933 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3936 result = vega20_disable_dpm_tasks(hwmgr);
3937 PP_ASSERT_WITH_CODE((0 == result),
3938 "[PowerOffAsic] Failed to disable DPM!",
3940 data->water_marks_bitmap &= ~(WaterMarksLoaded);
3945 static int conv_power_profile_to_pplib_workload(int power_profile)
3947 int pplib_workload = 0;
3949 switch (power_profile) {
3950 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
3951 pplib_workload = WORKLOAD_DEFAULT_BIT;
3953 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
3954 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
3956 case PP_SMC_POWER_PROFILE_POWERSAVING:
3957 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
3959 case PP_SMC_POWER_PROFILE_VIDEO:
3960 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
3962 case PP_SMC_POWER_PROFILE_VR:
3963 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
3965 case PP_SMC_POWER_PROFILE_COMPUTE:
3966 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
3968 case PP_SMC_POWER_PROFILE_CUSTOM:
3969 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
3973 return pplib_workload;
3976 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
3978 DpmActivityMonitorCoeffInt_t activity_monitor;
3979 uint32_t i, size = 0;
3980 uint16_t workload_type = 0;
3981 static const char *profile_name[] = {
3989 static const char *title[] = {
3990 "PROFILE_INDEX(NAME)",
3994 "MinActiveFreqType",
3999 "PD_Data_error_coeff",
4000 "PD_Data_error_rate_coeff"};
4006 size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
4007 title[0], title[1], title[2], title[3], title[4], title[5],
4008 title[6], title[7], title[8], title[9], title[10]);
4010 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
4011 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
4012 workload_type = conv_power_profile_to_pplib_workload(i);
4013 result = vega20_get_activity_monitor_coeff(hwmgr,
4014 (uint8_t *)(&activity_monitor), workload_type);
4015 PP_ASSERT_WITH_CODE(!result,
4016 "[GetPowerProfile] Failed to get activity monitor!",
4019 size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
4020 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
4022 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4026 activity_monitor.Gfx_FPS,
4027 activity_monitor.Gfx_UseRlcBusy,
4028 activity_monitor.Gfx_MinActiveFreqType,
4029 activity_monitor.Gfx_MinActiveFreq,
4030 activity_monitor.Gfx_BoosterFreqType,
4031 activity_monitor.Gfx_BoosterFreq,
4032 activity_monitor.Gfx_PD_Data_limit_c,
4033 activity_monitor.Gfx_PD_Data_error_coeff,
4034 activity_monitor.Gfx_PD_Data_error_rate_coeff);
4036 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4040 activity_monitor.Soc_FPS,
4041 activity_monitor.Soc_UseRlcBusy,
4042 activity_monitor.Soc_MinActiveFreqType,
4043 activity_monitor.Soc_MinActiveFreq,
4044 activity_monitor.Soc_BoosterFreqType,
4045 activity_monitor.Soc_BoosterFreq,
4046 activity_monitor.Soc_PD_Data_limit_c,
4047 activity_monitor.Soc_PD_Data_error_coeff,
4048 activity_monitor.Soc_PD_Data_error_rate_coeff);
4050 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4054 activity_monitor.Mem_FPS,
4055 activity_monitor.Mem_UseRlcBusy,
4056 activity_monitor.Mem_MinActiveFreqType,
4057 activity_monitor.Mem_MinActiveFreq,
4058 activity_monitor.Mem_BoosterFreqType,
4059 activity_monitor.Mem_BoosterFreq,
4060 activity_monitor.Mem_PD_Data_limit_c,
4061 activity_monitor.Mem_PD_Data_error_coeff,
4062 activity_monitor.Mem_PD_Data_error_rate_coeff);
4064 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4068 activity_monitor.Fclk_FPS,
4069 activity_monitor.Fclk_UseRlcBusy,
4070 activity_monitor.Fclk_MinActiveFreqType,
4071 activity_monitor.Fclk_MinActiveFreq,
4072 activity_monitor.Fclk_BoosterFreqType,
4073 activity_monitor.Fclk_BoosterFreq,
4074 activity_monitor.Fclk_PD_Data_limit_c,
4075 activity_monitor.Fclk_PD_Data_error_coeff,
4076 activity_monitor.Fclk_PD_Data_error_rate_coeff);
4082 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
4084 DpmActivityMonitorCoeffInt_t activity_monitor;
4085 int workload_type, result = 0;
4086 uint32_t power_profile_mode = input[size];
4088 if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
4089 pr_err("Invalid power profile mode %d\n", power_profile_mode);
4093 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
4094 struct vega20_hwmgr *data =
4095 (struct vega20_hwmgr *)(hwmgr->backend);
4096 if (size == 0 && !data->is_custom_profile_set)
4098 if (size < 10 && size != 0)
4101 result = vega20_get_activity_monitor_coeff(hwmgr,
4102 (uint8_t *)(&activity_monitor),
4103 WORKLOAD_PPLIB_CUSTOM_BIT);
4104 PP_ASSERT_WITH_CODE(!result,
4105 "[SetPowerProfile] Failed to get activity monitor!",
4108 /* If size==0, then we want to apply the already-configured
4109 * CUSTOM profile again. Just apply it, since we checked its
4116 case 0: /* Gfxclk */
4117 activity_monitor.Gfx_FPS = input[1];
4118 activity_monitor.Gfx_UseRlcBusy = input[2];
4119 activity_monitor.Gfx_MinActiveFreqType = input[3];
4120 activity_monitor.Gfx_MinActiveFreq = input[4];
4121 activity_monitor.Gfx_BoosterFreqType = input[5];
4122 activity_monitor.Gfx_BoosterFreq = input[6];
4123 activity_monitor.Gfx_PD_Data_limit_c = input[7];
4124 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
4125 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
4127 case 1: /* Socclk */
4128 activity_monitor.Soc_FPS = input[1];
4129 activity_monitor.Soc_UseRlcBusy = input[2];
4130 activity_monitor.Soc_MinActiveFreqType = input[3];
4131 activity_monitor.Soc_MinActiveFreq = input[4];
4132 activity_monitor.Soc_BoosterFreqType = input[5];
4133 activity_monitor.Soc_BoosterFreq = input[6];
4134 activity_monitor.Soc_PD_Data_limit_c = input[7];
4135 activity_monitor.Soc_PD_Data_error_coeff = input[8];
4136 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
4139 activity_monitor.Mem_FPS = input[1];
4140 activity_monitor.Mem_UseRlcBusy = input[2];
4141 activity_monitor.Mem_MinActiveFreqType = input[3];
4142 activity_monitor.Mem_MinActiveFreq = input[4];
4143 activity_monitor.Mem_BoosterFreqType = input[5];
4144 activity_monitor.Mem_BoosterFreq = input[6];
4145 activity_monitor.Mem_PD_Data_limit_c = input[7];
4146 activity_monitor.Mem_PD_Data_error_coeff = input[8];
4147 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
4150 activity_monitor.Fclk_FPS = input[1];
4151 activity_monitor.Fclk_UseRlcBusy = input[2];
4152 activity_monitor.Fclk_MinActiveFreqType = input[3];
4153 activity_monitor.Fclk_MinActiveFreq = input[4];
4154 activity_monitor.Fclk_BoosterFreqType = input[5];
4155 activity_monitor.Fclk_BoosterFreq = input[6];
4156 activity_monitor.Fclk_PD_Data_limit_c = input[7];
4157 activity_monitor.Fclk_PD_Data_error_coeff = input[8];
4158 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
4162 result = vega20_set_activity_monitor_coeff(hwmgr,
4163 (uint8_t *)(&activity_monitor),
4164 WORKLOAD_PPLIB_CUSTOM_BIT);
4165 data->is_custom_profile_set = true;
4166 PP_ASSERT_WITH_CODE(!result,
4167 "[SetPowerProfile] Failed to set activity monitor!",
4172 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
4174 conv_power_profile_to_pplib_workload(power_profile_mode);
4175 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
4179 hwmgr->power_profile_mode = power_profile_mode;
4184 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
4185 uint32_t virtual_addr_low,
4186 uint32_t virtual_addr_hi,
4187 uint32_t mc_addr_low,
4188 uint32_t mc_addr_hi,
4191 smum_send_msg_to_smc_with_parameter(hwmgr,
4192 PPSMC_MSG_SetSystemVirtualDramAddrHigh,
4195 smum_send_msg_to_smc_with_parameter(hwmgr,
4196 PPSMC_MSG_SetSystemVirtualDramAddrLow,
4199 smum_send_msg_to_smc_with_parameter(hwmgr,
4200 PPSMC_MSG_DramLogSetDramAddrHigh,
4204 smum_send_msg_to_smc_with_parameter(hwmgr,
4205 PPSMC_MSG_DramLogSetDramAddrLow,
4209 smum_send_msg_to_smc_with_parameter(hwmgr,
4210 PPSMC_MSG_DramLogSetDramSize,
4216 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
4217 struct PP_TemperatureRange *thermal_data)
4219 struct vega20_hwmgr *data =
4220 (struct vega20_hwmgr *)(hwmgr->backend);
4221 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
4223 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
4225 thermal_data->max = pp_table->TedgeLimit *
4226 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4227 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
4228 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4229 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
4230 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4231 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
4232 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4233 thermal_data->mem_crit_max = pp_table->ThbmLimit *
4234 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4235 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
4236 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4241 static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire)
4245 /* I2C bus access can happen very early, when SMU not loaded yet */
4246 if (!vega20_is_smc_ram_running(hwmgr))
4249 res = smum_send_msg_to_smc_with_parameter(hwmgr,
4251 PPSMC_MSG_RequestI2CBus :
4252 PPSMC_MSG_ReleaseI2CBus),
4256 PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res);
4260 static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr,
4261 enum pp_df_cstate state)
4265 /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
4266 if (hwmgr->smu_version < 0x283200) {
4267 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
4271 ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state,
4274 pr_err("SetDfCstate failed!\n");
4279 static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr,
4284 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
4285 PPSMC_MSG_SetXgmiMode,
4286 pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3,
4289 pr_err("SetXgmiPstate failed!\n");
4294 static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
4296 memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0));
4298 gpu_metrics->common_header.structure_size =
4299 sizeof(struct gpu_metrics_v1_0);
4300 gpu_metrics->common_header.format_revision = 1;
4301 gpu_metrics->common_header.content_revision = 0;
4303 gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
4306 static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr,
4309 struct vega20_hwmgr *data =
4310 (struct vega20_hwmgr *)(hwmgr->backend);
4311 struct gpu_metrics_v1_0 *gpu_metrics =
4312 &data->gpu_metrics_table;
4313 SmuMetrics_t metrics;
4314 uint32_t fan_speed_rpm;
4317 ret = vega20_get_metrics_table(hwmgr, &metrics, true);
4321 vega20_init_gpu_metrics_v1_0(gpu_metrics);
4323 gpu_metrics->temperature_edge = metrics.TemperatureEdge;
4324 gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
4325 gpu_metrics->temperature_mem = metrics.TemperatureHBM;
4326 gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
4327 gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
4328 gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
4330 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
4331 gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
4333 gpu_metrics->average_socket_power = metrics.AverageSocketPower;
4335 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
4336 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
4337 gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
4339 gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
4340 gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
4341 gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
4342 gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
4343 gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
4345 gpu_metrics->throttle_status = metrics.ThrottlerStatus;
4347 vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm);
4348 gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm;
4350 gpu_metrics->pcie_link_width =
4351 vega20_get_current_pcie_link_width(hwmgr);
4352 gpu_metrics->pcie_link_speed =
4353 vega20_get_current_pcie_link_speed(hwmgr);
4355 *table = (void *)gpu_metrics;
4357 return sizeof(struct gpu_metrics_v1_0);
4360 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
4361 /* init/fini related */
4362 .backend_init = vega20_hwmgr_backend_init,
4363 .backend_fini = vega20_hwmgr_backend_fini,
4364 .asic_setup = vega20_setup_asic_task,
4365 .power_off_asic = vega20_power_off_asic,
4366 .dynamic_state_management_enable = vega20_enable_dpm_tasks,
4367 .dynamic_state_management_disable = vega20_disable_dpm_tasks,
4368 /* power state related */
4369 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
4370 .pre_display_config_changed = vega20_pre_display_configuration_changed_task,
4371 .display_config_changed = vega20_display_configuration_changed_task,
4372 .check_smc_update_required_for_display_configuration =
4373 vega20_check_smc_update_required_for_display_configuration,
4374 .notify_smc_display_config_after_ps_adjustment =
4375 vega20_notify_smc_display_config_after_ps_adjustment,
4377 .get_sclk = vega20_dpm_get_sclk,
4378 .get_mclk = vega20_dpm_get_mclk,
4379 .get_dal_power_level = vega20_get_dal_power_level,
4380 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
4381 .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage,
4382 .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges,
4383 .display_clock_voltage_request = vega20_display_clock_voltage_request,
4384 .get_performance_level = vega20_get_performance_level,
4385 /* UMD pstate, profile related */
4386 .force_dpm_level = vega20_dpm_force_dpm_level,
4387 .get_power_profile_mode = vega20_get_power_profile_mode,
4388 .set_power_profile_mode = vega20_set_power_profile_mode,
4390 .set_power_limit = vega20_set_power_limit,
4391 .get_sclk_od = vega20_get_sclk_od,
4392 .set_sclk_od = vega20_set_sclk_od,
4393 .get_mclk_od = vega20_get_mclk_od,
4394 .set_mclk_od = vega20_set_mclk_od,
4395 .odn_edit_dpm_table = vega20_odn_edit_dpm_table,
4396 /* for sysfs to retrive/set gfxclk/memclk */
4397 .force_clock_level = vega20_force_clock_level,
4398 .print_clock_levels = vega20_print_clock_levels,
4399 .read_sensor = vega20_read_sensor,
4400 .get_ppfeature_status = vega20_get_ppfeature_status,
4401 .set_ppfeature_status = vega20_set_ppfeature_status,
4402 /* powergate related */
4403 .powergate_uvd = vega20_power_gate_uvd,
4404 .powergate_vce = vega20_power_gate_vce,
4405 /* thermal related */
4406 .start_thermal_controller = vega20_start_thermal_controller,
4407 .stop_thermal_controller = vega20_thermal_stop_thermal_controller,
4408 .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
4409 .register_irq_handlers = smu9_register_irq_handlers,
4410 .disable_smc_firmware_ctf = vega20_thermal_disable_alert,
4411 /* fan control related */
4412 .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent,
4413 .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent,
4414 .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info,
4415 .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm,
4416 .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm,
4417 .get_fan_control_mode = vega20_get_fan_control_mode,
4418 .set_fan_control_mode = vega20_set_fan_control_mode,
4419 /* smu memory related */
4420 .notify_cac_buffer_info = vega20_notify_cac_buffer_info,
4421 .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost,
4423 .get_asic_baco_capability = vega20_baco_get_capability,
4424 .get_asic_baco_state = vega20_baco_get_state,
4425 .set_asic_baco_state = vega20_baco_set_state,
4426 .set_mp1_state = vega20_set_mp1_state,
4427 .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
4428 .set_df_cstate = vega20_set_df_cstate,
4429 .set_xgmi_pstate = vega20_set_xgmi_pstate,
4430 .get_gpu_metrics = vega20_get_gpu_metrics,
4433 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
4435 hwmgr->hwmgr_func = &vega20_hwmgr_funcs;
4436 hwmgr->pptable_func = &vega20_pptable_funcs;