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 "smuio/smuio_9_0_offset.h"
51 #include "smuio/smuio_9_0_sh_mask.h"
53 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
55 struct vega20_hwmgr *data =
56 (struct vega20_hwmgr *)(hwmgr->backend);
58 data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT;
59 data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT;
60 data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT;
61 data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT;
62 data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT;
64 data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT;
65 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
66 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
67 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
68 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
69 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
70 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
71 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
72 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
73 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
74 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
75 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
76 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
78 data->registry_data.disallowed_features = 0x0;
79 data->registry_data.od_state_in_dc_support = 0;
80 data->registry_data.thermal_support = 1;
81 data->registry_data.skip_baco_hardware = 0;
83 data->registry_data.log_avfs_param = 0;
84 data->registry_data.sclk_throttle_low_notification = 1;
85 data->registry_data.force_dpm_high = 0;
86 data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
88 data->registry_data.didt_support = 0;
89 if (data->registry_data.didt_support) {
90 data->registry_data.didt_mode = 6;
91 data->registry_data.sq_ramping_support = 1;
92 data->registry_data.db_ramping_support = 0;
93 data->registry_data.td_ramping_support = 0;
94 data->registry_data.tcp_ramping_support = 0;
95 data->registry_data.dbr_ramping_support = 0;
96 data->registry_data.edc_didt_support = 1;
97 data->registry_data.gc_didt_support = 0;
98 data->registry_data.psm_didt_support = 0;
101 data->registry_data.pcie_lane_override = 0xff;
102 data->registry_data.pcie_speed_override = 0xff;
103 data->registry_data.pcie_clock_override = 0xffffffff;
104 data->registry_data.regulator_hot_gpio_support = 1;
105 data->registry_data.ac_dc_switch_gpio_support = 0;
106 data->registry_data.quick_transition_support = 0;
107 data->registry_data.zrpm_start_temp = 0xffff;
108 data->registry_data.zrpm_stop_temp = 0xffff;
109 data->registry_data.od8_feature_enable = 1;
110 data->registry_data.disable_water_mark = 0;
111 data->registry_data.disable_pp_tuning = 0;
112 data->registry_data.disable_xlpp_tuning = 0;
113 data->registry_data.disable_workload_policy = 0;
114 data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
115 data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
116 data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
117 data->registry_data.force_workload_policy_mask = 0;
118 data->registry_data.disable_3d_fs_detection = 0;
119 data->registry_data.fps_support = 1;
120 data->registry_data.disable_auto_wattman = 1;
121 data->registry_data.auto_wattman_debug = 0;
122 data->registry_data.auto_wattman_sample_period = 100;
123 data->registry_data.fclk_gfxclk_ratio = 0x3F6CCCCD;
124 data->registry_data.auto_wattman_threshold = 50;
125 data->registry_data.gfxoff_controlled_by_driver = 1;
126 data->gfxoff_allowed = false;
127 data->counter_gfxoff = 0;
130 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
132 struct vega20_hwmgr *data =
133 (struct vega20_hwmgr *)(hwmgr->backend);
134 struct amdgpu_device *adev = hwmgr->adev;
136 if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE)
137 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
138 PHM_PlatformCaps_ControlVDDCI);
140 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
141 PHM_PlatformCaps_TablelessHardwareInterface);
143 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
144 PHM_PlatformCaps_EnableSMU7ThermalManagement);
146 if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
147 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
148 PHM_PlatformCaps_UVDPowerGating);
150 if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
151 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
152 PHM_PlatformCaps_VCEPowerGating);
154 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
155 PHM_PlatformCaps_UnTabledHardwareInterface);
157 if (data->registry_data.od8_feature_enable)
158 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
159 PHM_PlatformCaps_OD8inACSupport);
161 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
162 PHM_PlatformCaps_ActivityReporting);
163 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
164 PHM_PlatformCaps_FanSpeedInTableIsRPM);
166 if (data->registry_data.od_state_in_dc_support) {
167 if (data->registry_data.od8_feature_enable)
168 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
169 PHM_PlatformCaps_OD8inDCSupport);
172 if (data->registry_data.thermal_support &&
173 data->registry_data.fuzzy_fan_control_support &&
174 hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
175 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
176 PHM_PlatformCaps_ODFuzzyFanControlSupport);
178 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
179 PHM_PlatformCaps_DynamicPowerManagement);
180 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
181 PHM_PlatformCaps_SMC);
182 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
183 PHM_PlatformCaps_ThermalPolicyDelay);
185 if (data->registry_data.force_dpm_high)
186 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
187 PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
189 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
190 PHM_PlatformCaps_DynamicUVDState);
192 if (data->registry_data.sclk_throttle_low_notification)
193 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
194 PHM_PlatformCaps_SclkThrottleLowNotification);
196 /* power tune caps */
197 /* assume disabled */
198 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
199 PHM_PlatformCaps_PowerContainment);
200 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
201 PHM_PlatformCaps_DiDtSupport);
202 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
203 PHM_PlatformCaps_SQRamping);
204 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
205 PHM_PlatformCaps_DBRamping);
206 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
207 PHM_PlatformCaps_TDRamping);
208 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
209 PHM_PlatformCaps_TCPRamping);
210 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
211 PHM_PlatformCaps_DBRRamping);
212 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
213 PHM_PlatformCaps_DiDtEDCEnable);
214 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
215 PHM_PlatformCaps_GCEDC);
216 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
217 PHM_PlatformCaps_PSM);
219 if (data->registry_data.didt_support) {
220 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
221 PHM_PlatformCaps_DiDtSupport);
222 if (data->registry_data.sq_ramping_support)
223 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
224 PHM_PlatformCaps_SQRamping);
225 if (data->registry_data.db_ramping_support)
226 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
227 PHM_PlatformCaps_DBRamping);
228 if (data->registry_data.td_ramping_support)
229 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
230 PHM_PlatformCaps_TDRamping);
231 if (data->registry_data.tcp_ramping_support)
232 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
233 PHM_PlatformCaps_TCPRamping);
234 if (data->registry_data.dbr_ramping_support)
235 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
236 PHM_PlatformCaps_DBRRamping);
237 if (data->registry_data.edc_didt_support)
238 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
239 PHM_PlatformCaps_DiDtEDCEnable);
240 if (data->registry_data.gc_didt_support)
241 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
242 PHM_PlatformCaps_GCEDC);
243 if (data->registry_data.psm_didt_support)
244 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
245 PHM_PlatformCaps_PSM);
248 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
249 PHM_PlatformCaps_RegulatorHot);
251 if (data->registry_data.ac_dc_switch_gpio_support) {
252 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
253 PHM_PlatformCaps_AutomaticDCTransition);
254 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
255 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
258 if (data->registry_data.quick_transition_support) {
259 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
260 PHM_PlatformCaps_AutomaticDCTransition);
261 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
262 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
263 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
264 PHM_PlatformCaps_Falcon_QuickTransition);
267 if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) {
268 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
269 PHM_PlatformCaps_LowestUclkReservedForUlv);
270 if (data->lowest_uclk_reserved_for_ulv == 1)
271 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
272 PHM_PlatformCaps_LowestUclkReservedForUlv);
275 if (data->registry_data.custom_fan_support)
276 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
277 PHM_PlatformCaps_CustomFanControlSupport);
282 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr)
284 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
287 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
288 FEATURE_DPM_PREFETCHER_BIT;
289 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
290 FEATURE_DPM_GFXCLK_BIT;
291 data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
292 FEATURE_DPM_UCLK_BIT;
293 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
294 FEATURE_DPM_SOCCLK_BIT;
295 data->smu_features[GNLD_DPM_UVD].smu_feature_id =
297 data->smu_features[GNLD_DPM_VCE].smu_feature_id =
299 data->smu_features[GNLD_ULV].smu_feature_id =
301 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
302 FEATURE_DPM_MP0CLK_BIT;
303 data->smu_features[GNLD_DPM_LINK].smu_feature_id =
304 FEATURE_DPM_LINK_BIT;
305 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
306 FEATURE_DPM_DCEFCLK_BIT;
307 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
308 FEATURE_DS_GFXCLK_BIT;
309 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
310 FEATURE_DS_SOCCLK_BIT;
311 data->smu_features[GNLD_DS_LCLK].smu_feature_id =
313 data->smu_features[GNLD_PPT].smu_feature_id =
315 data->smu_features[GNLD_TDC].smu_feature_id =
317 data->smu_features[GNLD_THERMAL].smu_feature_id =
319 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
320 FEATURE_GFX_PER_CU_CG_BIT;
321 data->smu_features[GNLD_RM].smu_feature_id =
323 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
324 FEATURE_DS_DCEFCLK_BIT;
325 data->smu_features[GNLD_ACDC].smu_feature_id =
327 data->smu_features[GNLD_VR0HOT].smu_feature_id =
329 data->smu_features[GNLD_VR1HOT].smu_feature_id =
331 data->smu_features[GNLD_FW_CTF].smu_feature_id =
333 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
334 FEATURE_LED_DISPLAY_BIT;
335 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
336 FEATURE_FAN_CONTROL_BIT;
337 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
338 data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
339 data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
340 data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT;
341 data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT;
342 data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
343 data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
344 data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
346 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
347 data->smu_features[i].smu_feature_bitmap =
348 (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
349 data->smu_features[i].allowed =
350 ((data->registry_data.disallowed_features >> i) & 1) ?
355 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
360 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
362 kfree(hwmgr->backend);
363 hwmgr->backend = NULL;
368 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
370 struct vega20_hwmgr *data;
371 struct amdgpu_device *adev = hwmgr->adev;
373 data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL);
377 hwmgr->backend = data;
379 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
380 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
381 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
383 vega20_set_default_registry_data(hwmgr);
385 data->disable_dpm_mask = 0xff;
387 /* need to set voltage control types before EVV patching */
388 data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE;
389 data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE;
390 data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE;
392 data->water_marks_bitmap = 0;
393 data->avfs_exist = false;
395 vega20_set_features_platform_caps(hwmgr);
397 vega20_init_dpm_defaults(hwmgr);
399 /* Parse pptable data read from VBIOS */
400 vega20_set_private_data_based_on_pptable(hwmgr);
402 data->is_tlu_enabled = false;
404 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
405 VEGA20_MAX_HARDWARE_POWERLEVELS;
406 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
407 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
409 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
410 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
411 hwmgr->platform_descriptor.clockStep.engineClock = 500;
412 hwmgr->platform_descriptor.clockStep.memoryClock = 500;
414 data->total_active_cus = adev->gfx.cu_info.number;
419 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr)
421 struct vega20_hwmgr *data =
422 (struct vega20_hwmgr *)(hwmgr->backend);
424 data->low_sclk_interrupt_threshold = 0;
429 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
433 ret = vega20_init_sclk_threshold(hwmgr);
434 PP_ASSERT_WITH_CODE(!ret,
435 "Failed to init sclk threshold!",
442 * @fn vega20_init_dpm_state
443 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
445 * @param dpm_state - the address of the DPM Table to initiailize.
448 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state)
450 dpm_state->soft_min_level = 0x0;
451 dpm_state->soft_max_level = 0xffff;
452 dpm_state->hard_min_level = 0x0;
453 dpm_state->hard_max_level = 0xffff;
456 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
457 PPCLK_e clk_id, uint32_t *num_of_levels)
461 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
462 PPSMC_MSG_GetDpmFreqByIndex,
463 (clk_id << 16 | 0xFF));
464 PP_ASSERT_WITH_CODE(!ret,
465 "[GetNumOfDpmLevel] failed to get dpm levels!",
468 *num_of_levels = smum_get_argument(hwmgr);
469 PP_ASSERT_WITH_CODE(*num_of_levels > 0,
470 "[GetNumOfDpmLevel] number of clk levels is invalid!",
476 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
477 PPCLK_e clk_id, uint32_t index, uint32_t *clk)
481 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
482 PPSMC_MSG_GetDpmFreqByIndex,
483 (clk_id << 16 | index));
484 PP_ASSERT_WITH_CODE(!ret,
485 "[GetDpmFreqByIndex] failed to get dpm freq by index!",
488 *clk = smum_get_argument(hwmgr);
489 PP_ASSERT_WITH_CODE(*clk,
490 "[GetDpmFreqByIndex] clk value is invalid!",
496 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
497 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id)
500 uint32_t i, num_of_levels, clk;
502 ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
503 PP_ASSERT_WITH_CODE(!ret,
504 "[SetupSingleDpmTable] failed to get clk levels!",
507 dpm_table->count = num_of_levels;
509 for (i = 0; i < num_of_levels; i++) {
510 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
511 PP_ASSERT_WITH_CODE(!ret,
512 "[SetupSingleDpmTable] failed to get clk of specific level!",
514 dpm_table->dpm_levels[i].value = clk;
515 dpm_table->dpm_levels[i].enabled = true;
521 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
523 struct vega20_hwmgr *data =
524 (struct vega20_hwmgr *)(hwmgr->backend);
525 struct vega20_single_dpm_table *dpm_table;
528 dpm_table = &(data->dpm_table.gfx_table);
529 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
530 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
531 PP_ASSERT_WITH_CODE(!ret,
532 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
535 dpm_table->count = 1;
536 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
542 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
544 struct vega20_hwmgr *data =
545 (struct vega20_hwmgr *)(hwmgr->backend);
546 struct vega20_single_dpm_table *dpm_table;
549 dpm_table = &(data->dpm_table.mem_table);
550 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
551 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
552 PP_ASSERT_WITH_CODE(!ret,
553 "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
556 dpm_table->count = 1;
557 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
564 * This function is to initialize all DPM state tables
565 * for SMU based on the dependency table.
566 * Dynamic state patching function will then trim these
567 * state tables to the allowed range based
568 * on the power policy or external client requests,
569 * such as UVD request, etc.
571 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
573 struct vega20_hwmgr *data =
574 (struct vega20_hwmgr *)(hwmgr->backend);
575 struct vega20_single_dpm_table *dpm_table;
578 memset(&data->dpm_table, 0, sizeof(data->dpm_table));
581 dpm_table = &(data->dpm_table.soc_table);
582 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
583 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
584 PP_ASSERT_WITH_CODE(!ret,
585 "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
588 dpm_table->count = 1;
589 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
591 vega20_init_dpm_state(&(dpm_table->dpm_state));
594 dpm_table = &(data->dpm_table.gfx_table);
595 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
598 vega20_init_dpm_state(&(dpm_table->dpm_state));
601 dpm_table = &(data->dpm_table.mem_table);
602 ret = vega20_setup_memclk_dpm_table(hwmgr);
605 vega20_init_dpm_state(&(dpm_table->dpm_state));
608 dpm_table = &(data->dpm_table.eclk_table);
609 if (data->smu_features[GNLD_DPM_VCE].enabled) {
610 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
611 PP_ASSERT_WITH_CODE(!ret,
612 "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
615 dpm_table->count = 1;
616 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
618 vega20_init_dpm_state(&(dpm_table->dpm_state));
621 dpm_table = &(data->dpm_table.vclk_table);
622 if (data->smu_features[GNLD_DPM_UVD].enabled) {
623 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
624 PP_ASSERT_WITH_CODE(!ret,
625 "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
628 dpm_table->count = 1;
629 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
631 vega20_init_dpm_state(&(dpm_table->dpm_state));
634 dpm_table = &(data->dpm_table.dclk_table);
635 if (data->smu_features[GNLD_DPM_UVD].enabled) {
636 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
637 PP_ASSERT_WITH_CODE(!ret,
638 "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
641 dpm_table->count = 1;
642 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
644 vega20_init_dpm_state(&(dpm_table->dpm_state));
647 dpm_table = &(data->dpm_table.dcef_table);
648 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
649 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
650 PP_ASSERT_WITH_CODE(!ret,
651 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
654 dpm_table->count = 1;
655 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
657 vega20_init_dpm_state(&(dpm_table->dpm_state));
660 dpm_table = &(data->dpm_table.pixel_table);
661 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
662 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
663 PP_ASSERT_WITH_CODE(!ret,
664 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
667 dpm_table->count = 0;
668 vega20_init_dpm_state(&(dpm_table->dpm_state));
671 dpm_table = &(data->dpm_table.display_table);
672 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
673 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
674 PP_ASSERT_WITH_CODE(!ret,
675 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
678 dpm_table->count = 0;
679 vega20_init_dpm_state(&(dpm_table->dpm_state));
682 dpm_table = &(data->dpm_table.phy_table);
683 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
684 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
685 PP_ASSERT_WITH_CODE(!ret,
686 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
689 dpm_table->count = 0;
690 vega20_init_dpm_state(&(dpm_table->dpm_state));
693 dpm_table = &(data->dpm_table.fclk_table);
694 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
695 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK);
696 PP_ASSERT_WITH_CODE(!ret,
697 "[SetupDefaultDpmTable] failed to get fclk dpm levels!",
700 dpm_table->count = 0;
701 vega20_init_dpm_state(&(dpm_table->dpm_state));
703 /* save a copy of the default DPM table */
704 memcpy(&(data->golden_dpm_table), &(data->dpm_table),
705 sizeof(struct vega20_dpm_table));
711 * Initializes the SMC table and uploads it
713 * @param hwmgr the address of the powerplay hardware manager.
714 * @param pInput the pointer to input data (PowerState)
717 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr)
720 struct vega20_hwmgr *data =
721 (struct vega20_hwmgr *)(hwmgr->backend);
722 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
723 struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
724 struct phm_ppt_v3_information *pptable_information =
725 (struct phm_ppt_v3_information *)hwmgr->pptable;
727 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
728 PP_ASSERT_WITH_CODE(!result,
729 "[InitSMCTable] Failed to get vbios bootup values!",
732 data->vbios_boot_state.vddc = boot_up_values.usVddc;
733 data->vbios_boot_state.vddci = boot_up_values.usVddci;
734 data->vbios_boot_state.mvddc = boot_up_values.usMvddc;
735 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
736 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
737 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
738 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
739 data->vbios_boot_state.eclock = boot_up_values.ulEClk;
740 data->vbios_boot_state.vclock = boot_up_values.ulVClk;
741 data->vbios_boot_state.dclock = boot_up_values.ulDClk;
742 data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
744 smum_send_msg_to_smc_with_parameter(hwmgr,
745 PPSMC_MSG_SetMinDeepSleepDcefclk,
746 (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
748 memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
750 result = smum_smc_table_manager(hwmgr,
751 (uint8_t *)pp_table, TABLE_PPTABLE, false);
752 PP_ASSERT_WITH_CODE(!result,
753 "[InitSMCTable] Failed to upload PPtable!",
759 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
761 struct vega20_hwmgr *data =
762 (struct vega20_hwmgr *)(hwmgr->backend);
763 uint32_t allowed_features_low = 0, allowed_features_high = 0;
767 for (i = 0; i < GNLD_FEATURES_MAX; i++)
768 if (data->smu_features[i].allowed)
769 data->smu_features[i].smu_feature_id > 31 ?
770 (allowed_features_high |=
771 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT)
773 (allowed_features_low |=
774 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT)
777 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
778 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high);
779 PP_ASSERT_WITH_CODE(!ret,
780 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!",
783 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
784 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low);
785 PP_ASSERT_WITH_CODE(!ret,
786 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
792 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
794 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc);
797 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)
799 struct vega20_hwmgr *data =
800 (struct vega20_hwmgr *)(hwmgr->backend);
801 uint64_t features_enabled;
806 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
807 PPSMC_MSG_EnableAllSmuFeatures)) == 0,
808 "[EnableAllSMUFeatures] Failed to enable all smu features!",
811 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
812 PP_ASSERT_WITH_CODE(!ret,
813 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
816 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
817 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
819 data->smu_features[i].enabled = enabled;
820 data->smu_features[i].supported = enabled;
823 if (data->smu_features[i].allowed && !enabled)
824 pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i);
825 else if (!data->smu_features[i].allowed && enabled)
826 pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i);
833 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr)
835 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
837 if (data->smu_features[GNLD_DPM_UCLK].enabled)
838 return smum_send_msg_to_smc_with_parameter(hwmgr,
839 PPSMC_MSG_SetUclkFastSwitch,
845 static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr)
847 struct vega20_hwmgr *data =
848 (struct vega20_hwmgr *)(hwmgr->backend);
850 return smum_send_msg_to_smc_with_parameter(hwmgr,
851 PPSMC_MSG_SetFclkGfxClkRatio,
852 data->registry_data.fclk_gfxclk_ratio);
855 static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr)
857 struct vega20_hwmgr *data =
858 (struct vega20_hwmgr *)(hwmgr->backend);
859 uint64_t features_enabled;
864 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
865 PPSMC_MSG_DisableAllSmuFeatures)) == 0,
866 "[DisableAllSMUFeatures] Failed to disable all smu features!",
869 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
870 PP_ASSERT_WITH_CODE(!ret,
871 "[DisableAllSMUFeatures] Failed to get enabled smc features!",
874 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
875 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
877 data->smu_features[i].enabled = enabled;
878 data->smu_features[i].supported = enabled;
884 static int vega20_od8_set_feature_capabilities(
885 struct pp_hwmgr *hwmgr)
887 struct phm_ppt_v3_information *pptable_information =
888 (struct phm_ppt_v3_information *)hwmgr->pptable;
889 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
890 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
891 struct vega20_od8_settings *od_settings = &(data->od8_settings);
893 od_settings->overdrive8_capabilities = 0;
895 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
896 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
897 pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
898 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
899 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
900 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN]))
901 od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS;
903 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
904 (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
905 pp_table->MinVoltageGfx / VOLTAGE_SCALE) &&
906 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
907 pp_table->MaxVoltageGfx / VOLTAGE_SCALE) &&
908 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >=
909 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1]))
910 od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE;
913 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
914 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
915 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
916 pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
917 (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
918 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX]))
919 od_settings->overdrive8_capabilities |= OD8_UCLK_MAX;
922 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
923 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
924 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
925 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
926 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100)
927 od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT;
929 if (data->smu_features[GNLD_FAN_CONTROL].enabled) {
930 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
931 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
932 pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
933 (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
934 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT]))
935 od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK;
937 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
938 (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >=
939 (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) &&
940 pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
941 (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
942 pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED]))
943 od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN;
946 if (data->smu_features[GNLD_THERMAL].enabled) {
947 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
948 pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
949 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
950 (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
951 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP]))
952 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN;
954 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
955 pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
956 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
957 (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
958 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX]))
959 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM;
962 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE])
963 od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE;
965 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] &&
966 pp_table->FanZeroRpmEnable)
967 od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
972 static int vega20_od8_set_feature_id(
973 struct pp_hwmgr *hwmgr)
975 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
976 struct vega20_od8_settings *od_settings = &(data->od8_settings);
978 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
979 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
981 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
984 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
986 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
990 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
991 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
993 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
995 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
997 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
999 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1001 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1004 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1006 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1008 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1010 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1012 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1014 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1018 if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1019 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX;
1021 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0;
1023 if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1024 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT;
1026 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0;
1028 if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1029 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1030 OD8_ACOUSTIC_LIMIT_SCLK;
1032 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1035 if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1036 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1039 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1042 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1043 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1044 OD8_TEMPERATURE_FAN;
1046 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1049 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1050 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1051 OD8_TEMPERATURE_SYSTEM;
1053 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1059 static int vega20_od8_get_gfx_clock_base_voltage(
1060 struct pp_hwmgr *hwmgr,
1066 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1067 PPSMC_MSG_GetAVFSVoltageByDpm,
1068 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1069 PP_ASSERT_WITH_CODE(!ret,
1070 "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!",
1073 *voltage = smum_get_argument(hwmgr);
1074 *voltage = *voltage / VOLTAGE_SCALE;
1079 static int vega20_od8_initialize_default_settings(
1080 struct pp_hwmgr *hwmgr)
1082 struct phm_ppt_v3_information *pptable_information =
1083 (struct phm_ppt_v3_information *)hwmgr->pptable;
1084 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1085 struct vega20_od8_settings *od8_settings = &(data->od8_settings);
1086 OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table);
1089 /* Set Feature Capabilities */
1090 vega20_od8_set_feature_capabilities(hwmgr);
1092 /* Map FeatureID to individual settings */
1093 vega20_od8_set_feature_id(hwmgr);
1095 /* Set default values */
1096 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true);
1097 PP_ASSERT_WITH_CODE(!ret,
1098 "Failed to export over drive table!",
1101 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1102 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1103 od_table->GfxclkFmin;
1104 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1105 od_table->GfxclkFmax;
1107 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1109 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1113 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1114 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1115 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1116 od_table->GfxclkFreq1;
1118 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1119 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1120 od_table->GfxclkFreq3;
1122 od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2;
1123 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1124 od_table->GfxclkFreq2;
1126 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1127 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value),
1128 od_table->GfxclkFreq1),
1129 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1130 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0);
1131 od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1134 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1135 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value),
1136 od_table->GfxclkFreq2),
1137 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1138 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0);
1139 od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1142 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1143 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value),
1144 od_table->GfxclkFreq3),
1145 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1146 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0);
1147 od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1150 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1152 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value =
1154 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1156 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value =
1158 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1160 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value =
1164 if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1165 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1168 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1171 if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1172 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1173 od_table->OverDrivePct;
1175 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1178 if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1179 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1180 od_table->FanMaximumRpm;
1182 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1185 if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1186 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1187 od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100;
1189 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1192 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1193 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1194 od_table->FanTargetTemperature;
1196 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1199 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1200 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1201 od_table->MaxOpTemp;
1203 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1206 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1207 if (od8_settings->od8_settings_array[i].feature_id) {
1208 od8_settings->od8_settings_array[i].min_value =
1209 pptable_information->od_settings_min[i];
1210 od8_settings->od8_settings_array[i].max_value =
1211 pptable_information->od_settings_max[i];
1212 od8_settings->od8_settings_array[i].current_value =
1213 od8_settings->od8_settings_array[i].default_value;
1215 od8_settings->od8_settings_array[i].min_value =
1217 od8_settings->od8_settings_array[i].max_value =
1219 od8_settings->od8_settings_array[i].current_value =
1224 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false);
1225 PP_ASSERT_WITH_CODE(!ret,
1226 "Failed to import over drive table!",
1232 static int vega20_od8_set_settings(
1233 struct pp_hwmgr *hwmgr,
1237 OverDriveTable_t od_table;
1239 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1240 struct vega20_od8_single_setting *od8_settings =
1241 data->od8_settings.od8_settings_array;
1243 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true);
1244 PP_ASSERT_WITH_CODE(!ret,
1245 "Failed to export over drive table!",
1249 case OD8_SETTING_GFXCLK_FMIN:
1250 od_table.GfxclkFmin = (uint16_t)value;
1252 case OD8_SETTING_GFXCLK_FMAX:
1253 if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value ||
1254 value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value)
1257 od_table.GfxclkFmax = (uint16_t)value;
1259 case OD8_SETTING_GFXCLK_FREQ1:
1260 od_table.GfxclkFreq1 = (uint16_t)value;
1262 case OD8_SETTING_GFXCLK_VOLTAGE1:
1263 od_table.GfxclkVolt1 = (uint16_t)value;
1265 case OD8_SETTING_GFXCLK_FREQ2:
1266 od_table.GfxclkFreq2 = (uint16_t)value;
1268 case OD8_SETTING_GFXCLK_VOLTAGE2:
1269 od_table.GfxclkVolt2 = (uint16_t)value;
1271 case OD8_SETTING_GFXCLK_FREQ3:
1272 od_table.GfxclkFreq3 = (uint16_t)value;
1274 case OD8_SETTING_GFXCLK_VOLTAGE3:
1275 od_table.GfxclkVolt3 = (uint16_t)value;
1277 case OD8_SETTING_UCLK_FMAX:
1278 if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
1279 value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value)
1281 od_table.UclkFmax = (uint16_t)value;
1283 case OD8_SETTING_POWER_PERCENTAGE:
1284 od_table.OverDrivePct = (int16_t)value;
1286 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
1287 od_table.FanMaximumRpm = (uint16_t)value;
1289 case OD8_SETTING_FAN_MIN_SPEED:
1290 od_table.FanMinimumPwm = (uint16_t)value;
1292 case OD8_SETTING_FAN_TARGET_TEMP:
1293 od_table.FanTargetTemperature = (uint16_t)value;
1295 case OD8_SETTING_OPERATING_TEMP_MAX:
1296 od_table.MaxOpTemp = (uint16_t)value;
1300 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false);
1301 PP_ASSERT_WITH_CODE(!ret,
1302 "Failed to import over drive table!",
1308 static int vega20_get_sclk_od(
1309 struct pp_hwmgr *hwmgr)
1311 struct vega20_hwmgr *data = hwmgr->backend;
1312 struct vega20_single_dpm_table *sclk_table =
1313 &(data->dpm_table.gfx_table);
1314 struct vega20_single_dpm_table *golden_sclk_table =
1315 &(data->golden_dpm_table.gfx_table);
1319 value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value -
1320 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100,
1321 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value);
1326 static int vega20_set_sclk_od(
1327 struct pp_hwmgr *hwmgr, uint32_t value)
1329 struct vega20_hwmgr *data = hwmgr->backend;
1330 struct vega20_single_dpm_table *golden_sclk_table =
1331 &(data->golden_dpm_table.gfx_table);
1335 od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value;
1337 od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
1339 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk);
1340 PP_ASSERT_WITH_CODE(!ret,
1341 "[SetSclkOD] failed to set od gfxclk!",
1344 /* retrieve updated gfxclk table */
1345 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
1346 PP_ASSERT_WITH_CODE(!ret,
1347 "[SetSclkOD] failed to refresh gfxclk table!",
1353 static int vega20_get_mclk_od(
1354 struct pp_hwmgr *hwmgr)
1356 struct vega20_hwmgr *data = hwmgr->backend;
1357 struct vega20_single_dpm_table *mclk_table =
1358 &(data->dpm_table.mem_table);
1359 struct vega20_single_dpm_table *golden_mclk_table =
1360 &(data->golden_dpm_table.mem_table);
1364 value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value -
1365 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100,
1366 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value);
1371 static int vega20_set_mclk_od(
1372 struct pp_hwmgr *hwmgr, uint32_t value)
1374 struct vega20_hwmgr *data = hwmgr->backend;
1375 struct vega20_single_dpm_table *golden_mclk_table =
1376 &(data->golden_dpm_table.mem_table);
1380 od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value;
1382 od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
1384 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk);
1385 PP_ASSERT_WITH_CODE(!ret,
1386 "[SetMclkOD] failed to set od memclk!",
1389 /* retrieve updated memclk table */
1390 ret = vega20_setup_memclk_dpm_table(hwmgr);
1391 PP_ASSERT_WITH_CODE(!ret,
1392 "[SetMclkOD] failed to refresh memclk table!",
1398 static int vega20_populate_umdpstate_clocks(
1399 struct pp_hwmgr *hwmgr)
1401 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1402 struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table);
1403 struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table);
1405 hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value;
1406 hwmgr->pstate_mclk = mem_table->dpm_levels[0].value;
1408 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1409 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
1410 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1411 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1414 hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100;
1415 hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100;
1420 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr,
1421 PP_Clock *clock, PPCLK_e clock_select)
1425 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1426 PPSMC_MSG_GetDcModeMaxDpmFreq,
1427 (clock_select << 16))) == 0,
1428 "[GetMaxSustainableClock] Failed to get max DC clock from SMC!",
1430 *clock = smum_get_argument(hwmgr);
1432 /* if DC limit is zero, return AC limit */
1434 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1435 PPSMC_MSG_GetMaxDpmFreq,
1436 (clock_select << 16))) == 0,
1437 "[GetMaxSustainableClock] failed to get max AC clock from SMC!",
1439 *clock = smum_get_argument(hwmgr);
1445 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr)
1447 struct vega20_hwmgr *data =
1448 (struct vega20_hwmgr *)(hwmgr->backend);
1449 struct vega20_max_sustainable_clocks *max_sustainable_clocks =
1450 &(data->max_sustainable_clocks);
1453 max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100;
1454 max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100;
1455 max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100;
1456 max_sustainable_clocks->display_clock = 0xFFFFFFFF;
1457 max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
1458 max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
1460 if (data->smu_features[GNLD_DPM_UCLK].enabled)
1461 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1462 &(max_sustainable_clocks->uclock),
1464 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!",
1467 if (data->smu_features[GNLD_DPM_SOCCLK].enabled)
1468 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1469 &(max_sustainable_clocks->soc_clock),
1470 PPCLK_SOCCLK)) == 0,
1471 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!",
1474 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1475 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1476 &(max_sustainable_clocks->dcef_clock),
1477 PPCLK_DCEFCLK)) == 0,
1478 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!",
1480 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1481 &(max_sustainable_clocks->display_clock),
1482 PPCLK_DISPCLK)) == 0,
1483 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!",
1485 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1486 &(max_sustainable_clocks->phy_clock),
1487 PPCLK_PHYCLK)) == 0,
1488 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!",
1490 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1491 &(max_sustainable_clocks->pixel_clock),
1492 PPCLK_PIXCLK)) == 0,
1493 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!",
1497 if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
1498 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;
1503 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
1507 result = smum_send_msg_to_smc(hwmgr,
1508 PPSMC_MSG_SetMGpuFanBoostLimitRpm);
1509 PP_ASSERT_WITH_CODE(!result,
1510 "[EnableMgpuFan] Failed to enable mgpu fan boost!",
1516 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr)
1518 struct vega20_hwmgr *data =
1519 (struct vega20_hwmgr *)(hwmgr->backend);
1521 data->uvd_power_gated = true;
1522 data->vce_power_gated = true;
1524 if (data->smu_features[GNLD_DPM_UVD].enabled)
1525 data->uvd_power_gated = false;
1527 if (data->smu_features[GNLD_DPM_VCE].enabled)
1528 data->vce_power_gated = false;
1531 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1535 smum_send_msg_to_smc_with_parameter(hwmgr,
1536 PPSMC_MSG_NumOfDisplays, 0);
1538 result = vega20_set_allowed_featuresmask(hwmgr);
1539 PP_ASSERT_WITH_CODE(!result,
1540 "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
1543 result = vega20_init_smc_table(hwmgr);
1544 PP_ASSERT_WITH_CODE(!result,
1545 "[EnableDPMTasks] Failed to initialize SMC table!",
1548 result = vega20_run_btc_afll(hwmgr);
1549 PP_ASSERT_WITH_CODE(!result,
1550 "[EnableDPMTasks] Failed to run btc afll!",
1553 result = vega20_enable_all_smu_features(hwmgr);
1554 PP_ASSERT_WITH_CODE(!result,
1555 "[EnableDPMTasks] Failed to enable all smu features!",
1558 result = vega20_notify_smc_display_change(hwmgr);
1559 PP_ASSERT_WITH_CODE(!result,
1560 "[EnableDPMTasks] Failed to notify smc display change!",
1563 result = vega20_send_clock_ratio(hwmgr);
1564 PP_ASSERT_WITH_CODE(!result,
1565 "[EnableDPMTasks] Failed to send clock ratio!",
1568 /* Initialize UVD/VCE powergating state */
1569 vega20_init_powergate_state(hwmgr);
1571 result = vega20_setup_default_dpm_tables(hwmgr);
1572 PP_ASSERT_WITH_CODE(!result,
1573 "[EnableDPMTasks] Failed to setup default DPM tables!",
1576 result = vega20_init_max_sustainable_clocks(hwmgr);
1577 PP_ASSERT_WITH_CODE(!result,
1578 "[EnableDPMTasks] Failed to get maximum sustainable clocks!",
1581 result = vega20_power_control_set_level(hwmgr);
1582 PP_ASSERT_WITH_CODE(!result,
1583 "[EnableDPMTasks] Failed to power control set level!",
1586 result = vega20_od8_initialize_default_settings(hwmgr);
1587 PP_ASSERT_WITH_CODE(!result,
1588 "[EnableDPMTasks] Failed to initialize odn settings!",
1591 result = vega20_populate_umdpstate_clocks(hwmgr);
1592 PP_ASSERT_WITH_CODE(!result,
1593 "[EnableDPMTasks] Failed to populate umdpstate clocks!",
1596 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit,
1597 POWER_SOURCE_AC << 16);
1598 PP_ASSERT_WITH_CODE(!result,
1599 "[GetPptLimit] get default PPT limit failed!",
1601 hwmgr->power_limit =
1602 hwmgr->default_power_limit = smum_get_argument(hwmgr);
1607 static uint32_t vega20_find_lowest_dpm_level(
1608 struct vega20_single_dpm_table *table)
1612 for (i = 0; i < table->count; i++) {
1613 if (table->dpm_levels[i].enabled)
1616 if (i >= table->count) {
1618 table->dpm_levels[i].enabled = true;
1624 static uint32_t vega20_find_highest_dpm_level(
1625 struct vega20_single_dpm_table *table)
1629 PP_ASSERT_WITH_CODE(table != NULL,
1630 "[FindHighestDPMLevel] DPM Table does not exist!",
1632 PP_ASSERT_WITH_CODE(table->count > 0,
1633 "[FindHighestDPMLevel] DPM Table has no entry!",
1635 PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER,
1636 "[FindHighestDPMLevel] DPM Table has too many entries!",
1637 return MAX_REGULAR_DPM_NUMBER - 1);
1639 for (i = table->count - 1; i >= 0; i--) {
1640 if (table->dpm_levels[i].enabled)
1645 table->dpm_levels[i].enabled = true;
1651 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
1653 struct vega20_hwmgr *data =
1654 (struct vega20_hwmgr *)(hwmgr->backend);
1658 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1659 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
1660 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1661 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1662 (PPCLK_GFXCLK << 16) | (min_freq & 0xffff))),
1663 "Failed to set soft min gfxclk !",
1667 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1668 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
1669 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1670 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1671 (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
1672 "Failed to set soft min memclk !",
1675 min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
1676 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1677 hwmgr, PPSMC_MSG_SetHardMinByFreq,
1678 (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
1679 "Failed to set hard min memclk !",
1683 if (data->smu_features[GNLD_DPM_UVD].enabled) {
1684 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
1686 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1687 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1688 (PPCLK_VCLK << 16) | (min_freq & 0xffff))),
1689 "Failed to set soft min vclk!",
1692 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level;
1694 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1695 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1696 (PPCLK_DCLK << 16) | (min_freq & 0xffff))),
1697 "Failed to set soft min dclk!",
1701 if (data->smu_features[GNLD_DPM_VCE].enabled) {
1702 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
1704 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1705 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1706 (PPCLK_ECLK << 16) | (min_freq & 0xffff))),
1707 "Failed to set soft min eclk!",
1711 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
1712 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
1714 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1715 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1716 (PPCLK_SOCCLK << 16) | (min_freq & 0xffff))),
1717 "Failed to set soft min socclk!",
1724 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
1726 struct vega20_hwmgr *data =
1727 (struct vega20_hwmgr *)(hwmgr->backend);
1731 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1732 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
1734 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1735 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1736 (PPCLK_GFXCLK << 16) | (max_freq & 0xffff))),
1737 "Failed to set soft max gfxclk!",
1741 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1742 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
1744 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1745 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1746 (PPCLK_UCLK << 16) | (max_freq & 0xffff))),
1747 "Failed to set soft max memclk!",
1751 if (data->smu_features[GNLD_DPM_UVD].enabled) {
1752 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
1754 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1755 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1756 (PPCLK_VCLK << 16) | (max_freq & 0xffff))),
1757 "Failed to set soft max vclk!",
1760 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level;
1761 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1762 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1763 (PPCLK_DCLK << 16) | (max_freq & 0xffff))),
1764 "Failed to set soft max dclk!",
1768 if (data->smu_features[GNLD_DPM_VCE].enabled) {
1769 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
1771 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1772 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1773 (PPCLK_ECLK << 16) | (max_freq & 0xffff))),
1774 "Failed to set soft max eclk!",
1778 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
1779 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
1781 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1782 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1783 (PPCLK_SOCCLK << 16) | (max_freq & 0xffff))),
1784 "Failed to set soft max socclk!",
1791 int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
1793 struct vega20_hwmgr *data =
1794 (struct vega20_hwmgr *)(hwmgr->backend);
1797 if (data->smu_features[GNLD_DPM_VCE].supported) {
1798 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) {
1800 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n");
1802 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n");
1805 ret = vega20_enable_smc_features(hwmgr,
1807 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap);
1808 PP_ASSERT_WITH_CODE(!ret,
1809 "Attempt to Enable/Disable DPM VCE Failed!",
1811 data->smu_features[GNLD_DPM_VCE].enabled = enable;
1817 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr,
1819 PPCLK_e clock_select,
1826 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1827 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16))) == 0,
1828 "[GetClockRanges] Failed to get max clock from SMC!",
1830 *clock = smum_get_argument(hwmgr);
1832 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1833 PPSMC_MSG_GetMinDpmFreq,
1834 (clock_select << 16))) == 0,
1835 "[GetClockRanges] Failed to get min clock from SMC!",
1837 *clock = smum_get_argument(hwmgr);
1843 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
1845 struct vega20_hwmgr *data =
1846 (struct vega20_hwmgr *)(hwmgr->backend);
1850 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled,
1851 "[GetSclks]: gfxclk dpm not enabled!\n",
1855 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false);
1856 PP_ASSERT_WITH_CODE(!ret,
1857 "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
1860 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true);
1861 PP_ASSERT_WITH_CODE(!ret,
1862 "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
1866 return (gfx_clk * 100);
1869 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
1871 struct vega20_hwmgr *data =
1872 (struct vega20_hwmgr *)(hwmgr->backend);
1876 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled,
1877 "[MemMclks]: memclk dpm not enabled!\n",
1881 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false);
1882 PP_ASSERT_WITH_CODE(!ret,
1883 "[GetMclks]: fail to get min PPCLK_UCLK\n",
1886 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true);
1887 PP_ASSERT_WITH_CODE(!ret,
1888 "[GetMclks]: fail to get max PPCLK_UCLK\n",
1892 return (mem_clk * 100);
1895 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
1899 SmuMetrics_t metrics_table;
1901 ret = smum_smc_table_manager(hwmgr, (uint8_t *)&metrics_table, TABLE_SMU_METRICS, true);
1902 PP_ASSERT_WITH_CODE(!ret,
1903 "Failed to export SMU METRICS table!",
1906 *query = metrics_table.CurrSocketPower << 8;
1911 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr,
1912 PPCLK_e clk_id, uint32_t *clk_freq)
1918 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1919 PPSMC_MSG_GetDpmClockFreq, (clk_id << 16))) == 0,
1920 "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!",
1922 *clk_freq = smum_get_argument(hwmgr);
1924 *clk_freq = *clk_freq * 100;
1929 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr,
1930 uint32_t *activity_percent)
1933 SmuMetrics_t metrics_table;
1935 ret = smum_smc_table_manager(hwmgr, (uint8_t *)&metrics_table, TABLE_SMU_METRICS, true);
1936 PP_ASSERT_WITH_CODE(!ret,
1937 "Failed to export SMU METRICS table!",
1940 *activity_percent = metrics_table.AverageGfxActivity;
1945 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1946 void *value, int *size)
1948 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1949 struct amdgpu_device *adev = hwmgr->adev;
1954 case AMDGPU_PP_SENSOR_GFX_SCLK:
1955 ret = vega20_get_current_clk_freq(hwmgr,
1961 case AMDGPU_PP_SENSOR_GFX_MCLK:
1962 ret = vega20_get_current_clk_freq(hwmgr,
1968 case AMDGPU_PP_SENSOR_GPU_LOAD:
1969 ret = vega20_get_current_activity_percent(hwmgr, (uint32_t *)value);
1973 case AMDGPU_PP_SENSOR_GPU_TEMP:
1974 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr);
1977 case AMDGPU_PP_SENSOR_UVD_POWER:
1978 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
1981 case AMDGPU_PP_SENSOR_VCE_POWER:
1982 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
1985 case AMDGPU_PP_SENSOR_GPU_POWER:
1987 ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value);
1989 case AMDGPU_PP_SENSOR_VDDGFX:
1990 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
1991 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
1992 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
1993 *((uint32_t *)value) =
1994 (uint32_t)convert_to_vddc((uint8_t)val_vid);
1996 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
1997 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value);
2008 int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
2009 struct pp_display_clock_request *clock_req)
2012 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2013 enum amd_pp_clock_type clk_type = clock_req->clock_type;
2014 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
2015 PPCLK_e clk_select = 0;
2016 uint32_t clk_request = 0;
2018 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
2020 case amd_pp_dcef_clock:
2021 clk_select = PPCLK_DCEFCLK;
2023 case amd_pp_disp_clock:
2024 clk_select = PPCLK_DISPCLK;
2026 case amd_pp_pixel_clock:
2027 clk_select = PPCLK_PIXCLK;
2029 case amd_pp_phy_clock:
2030 clk_select = PPCLK_PHYCLK;
2033 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
2039 clk_request = (clk_select << 16) | clk_freq;
2040 result = smum_send_msg_to_smc_with_parameter(hwmgr,
2041 PPSMC_MSG_SetHardMinByFreq,
2049 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
2050 PHM_PerformanceLevelDesignation designation, uint32_t index,
2051 PHM_PerformanceLevel *level)
2056 static int vega20_notify_smc_display_config_after_ps_adjustment(
2057 struct pp_hwmgr *hwmgr)
2059 struct vega20_hwmgr *data =
2060 (struct vega20_hwmgr *)(hwmgr->backend);
2061 struct vega20_single_dpm_table *dpm_table =
2062 &data->dpm_table.mem_table;
2063 struct PP_Clocks min_clocks = {0};
2064 struct pp_display_clock_request clock_req;
2067 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
2068 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
2069 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
2071 if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
2072 clock_req.clock_type = amd_pp_dcef_clock;
2073 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
2074 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) {
2075 if (data->smu_features[GNLD_DS_DCEFCLK].supported)
2076 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(
2077 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
2078 min_clocks.dcefClockInSR / 100)) == 0,
2079 "Attempt to set divider for DCEFCLK Failed!",
2082 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2086 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2087 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100;
2088 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2089 PPSMC_MSG_SetHardMinByFreq,
2090 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
2091 "[SetHardMinFreq] Set hard min uclk failed!",
2098 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
2100 struct vega20_hwmgr *data =
2101 (struct vega20_hwmgr *)(hwmgr->backend);
2102 uint32_t soft_level;
2105 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2107 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2108 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2109 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2111 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2113 data->dpm_table.mem_table.dpm_state.soft_min_level =
2114 data->dpm_table.mem_table.dpm_state.soft_max_level =
2115 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2117 ret = vega20_upload_dpm_min_level(hwmgr);
2118 PP_ASSERT_WITH_CODE(!ret,
2119 "Failed to upload boot level to highest!",
2122 ret = vega20_upload_dpm_max_level(hwmgr);
2123 PP_ASSERT_WITH_CODE(!ret,
2124 "Failed to upload dpm max level to highest!",
2130 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
2132 struct vega20_hwmgr *data =
2133 (struct vega20_hwmgr *)(hwmgr->backend);
2134 uint32_t soft_level;
2137 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2139 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2140 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2141 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2143 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2145 data->dpm_table.mem_table.dpm_state.soft_min_level =
2146 data->dpm_table.mem_table.dpm_state.soft_max_level =
2147 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2149 ret = vega20_upload_dpm_min_level(hwmgr);
2150 PP_ASSERT_WITH_CODE(!ret,
2151 "Failed to upload boot level to highest!",
2154 ret = vega20_upload_dpm_max_level(hwmgr);
2155 PP_ASSERT_WITH_CODE(!ret,
2156 "Failed to upload dpm max level to highest!",
2163 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
2167 ret = vega20_upload_dpm_min_level(hwmgr);
2168 PP_ASSERT_WITH_CODE(!ret,
2169 "Failed to upload DPM Bootup Levels!",
2172 ret = vega20_upload_dpm_max_level(hwmgr);
2173 PP_ASSERT_WITH_CODE(!ret,
2174 "Failed to upload DPM Max Levels!",
2180 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
2181 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
2183 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2184 struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table);
2185 struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table);
2186 struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table);
2192 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
2193 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
2194 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
2195 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
2196 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2197 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2200 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2202 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2204 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2205 *sclk_mask = gfx_dpm_table->count - 1;
2206 *mclk_mask = mem_dpm_table->count - 1;
2207 *soc_mask = soc_dpm_table->count - 1;
2213 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
2214 enum pp_clock_type type, uint32_t mask)
2216 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2217 uint32_t soft_min_level, soft_max_level;
2222 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2223 soft_max_level = mask ? (fls(mask) - 1) : 0;
2225 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2226 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2227 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2228 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2230 ret = vega20_upload_dpm_min_level(hwmgr);
2231 PP_ASSERT_WITH_CODE(!ret,
2232 "Failed to upload boot level to lowest!",
2235 ret = vega20_upload_dpm_max_level(hwmgr);
2236 PP_ASSERT_WITH_CODE(!ret,
2237 "Failed to upload dpm max level to highest!",
2242 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2243 soft_max_level = mask ? (fls(mask) - 1) : 0;
2245 data->dpm_table.mem_table.dpm_state.soft_min_level =
2246 data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2247 data->dpm_table.mem_table.dpm_state.soft_max_level =
2248 data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2250 ret = vega20_upload_dpm_min_level(hwmgr);
2251 PP_ASSERT_WITH_CODE(!ret,
2252 "Failed to upload boot level to lowest!",
2255 ret = vega20_upload_dpm_max_level(hwmgr);
2256 PP_ASSERT_WITH_CODE(!ret,
2257 "Failed to upload dpm max level to highest!",
2272 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
2273 enum amd_dpm_forced_level level)
2276 uint32_t sclk_mask, mclk_mask, soc_mask;
2279 case AMD_DPM_FORCED_LEVEL_HIGH:
2280 ret = vega20_force_dpm_highest(hwmgr);
2283 case AMD_DPM_FORCED_LEVEL_LOW:
2284 ret = vega20_force_dpm_lowest(hwmgr);
2287 case AMD_DPM_FORCED_LEVEL_AUTO:
2288 ret = vega20_unforce_dpm_levels(hwmgr);
2291 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
2292 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
2293 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
2294 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
2295 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
2298 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
2299 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
2302 case AMD_DPM_FORCED_LEVEL_MANUAL:
2303 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
2311 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr)
2313 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2315 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
2316 return AMD_FAN_CTRL_MANUAL;
2318 return AMD_FAN_CTRL_AUTO;
2321 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
2324 case AMD_FAN_CTRL_NONE:
2325 vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
2327 case AMD_FAN_CTRL_MANUAL:
2328 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2329 vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
2331 case AMD_FAN_CTRL_AUTO:
2332 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2333 vega20_fan_ctrl_start_smc_fan_control(hwmgr);
2340 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr,
2341 struct amd_pp_simple_clock_info *info)
2344 struct phm_ppt_v2_information *table_info =
2345 (struct phm_ppt_v2_information *)hwmgr->pptable;
2346 struct phm_clock_and_voltage_limits *max_limits =
2347 &table_info->max_clock_voltage_on_ac;
2349 info->engine_max_clock = max_limits->sclk;
2350 info->memory_max_clock = max_limits->mclk;
2356 static int vega20_get_sclks(struct pp_hwmgr *hwmgr,
2357 struct pp_clock_levels_with_latency *clocks)
2359 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2360 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2363 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled,
2364 "[GetSclks]: gfxclk dpm not enabled!\n",
2367 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2368 clocks->num_levels = count;
2370 for (i = 0; i < count; i++) {
2371 clocks->data[i].clocks_in_khz =
2372 dpm_table->dpm_levels[i].value * 1000;
2373 clocks->data[i].latency_in_us = 0;
2379 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr,
2385 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr,
2386 struct pp_clock_levels_with_latency *clocks)
2388 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2389 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table);
2392 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled,
2393 "[GetMclks]: uclk dpm not enabled!\n",
2396 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2397 clocks->num_levels = data->mclk_latency_table.count = count;
2399 for (i = 0; i < count; i++) {
2400 clocks->data[i].clocks_in_khz =
2401 data->mclk_latency_table.entries[i].frequency =
2402 dpm_table->dpm_levels[i].value * 1000;
2403 clocks->data[i].latency_in_us =
2404 data->mclk_latency_table.entries[i].latency =
2405 vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
2411 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr,
2412 struct pp_clock_levels_with_latency *clocks)
2414 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2415 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table);
2418 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_DCEFCLK].enabled,
2419 "[GetDcfclocks]: dcefclk dpm not enabled!\n",
2422 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2423 clocks->num_levels = count;
2425 for (i = 0; i < count; i++) {
2426 clocks->data[i].clocks_in_khz =
2427 dpm_table->dpm_levels[i].value * 1000;
2428 clocks->data[i].latency_in_us = 0;
2434 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr,
2435 struct pp_clock_levels_with_latency *clocks)
2437 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2438 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table);
2441 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_SOCCLK].enabled,
2442 "[GetSocclks]: socclk dpm not enabled!\n",
2445 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2446 clocks->num_levels = count;
2448 for (i = 0; i < count; i++) {
2449 clocks->data[i].clocks_in_khz =
2450 dpm_table->dpm_levels[i].value * 1000;
2451 clocks->data[i].latency_in_us = 0;
2458 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
2459 enum amd_pp_clock_type type,
2460 struct pp_clock_levels_with_latency *clocks)
2465 case amd_pp_sys_clock:
2466 ret = vega20_get_sclks(hwmgr, clocks);
2468 case amd_pp_mem_clock:
2469 ret = vega20_get_memclocks(hwmgr, clocks);
2471 case amd_pp_dcef_clock:
2472 ret = vega20_get_dcefclocks(hwmgr, clocks);
2474 case amd_pp_soc_clock:
2475 ret = vega20_get_socclocks(hwmgr, clocks);
2484 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
2485 enum amd_pp_clock_type type,
2486 struct pp_clock_levels_with_voltage *clocks)
2488 clocks->num_levels = 0;
2493 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
2496 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2497 Watermarks_t *table = &(data->smc_state_table.water_marks_table);
2498 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
2500 if (!data->registry_data.disable_water_mark &&
2501 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2502 data->smu_features[GNLD_DPM_SOCCLK].supported) {
2503 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
2504 data->water_marks_bitmap |= WaterMarksExist;
2505 data->water_marks_bitmap &= ~WaterMarksLoaded;
2511 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2512 enum PP_OD_DPM_TABLE_COMMAND type,
2513 long *input, uint32_t size)
2515 struct vega20_hwmgr *data =
2516 (struct vega20_hwmgr *)(hwmgr->backend);
2517 struct vega20_od8_single_setting *od8_settings =
2518 data->od8_settings.od8_settings_array;
2519 OverDriveTable_t *od_table =
2520 &(data->smc_state_table.overdrive_table);
2521 struct pp_clock_levels_with_latency clocks;
2522 int32_t input_index, input_clk, input_vol, i;
2526 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
2530 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2531 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2532 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2533 pr_info("Sclk min/max frequency overdrive not supported\n");
2537 for (i = 0; i < size; i += 2) {
2539 pr_info("invalid number of input parameters %d\n",
2544 input_index = input[i];
2545 input_clk = input[i + 1];
2547 if (input_index != 0 && input_index != 1) {
2548 pr_info("Invalid index %d\n", input_index);
2549 pr_info("Support min/max sclk frequency setting only which index by 0/1\n");
2553 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2554 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2555 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2557 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2558 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2562 if ((input_index == 0 && od_table->GfxclkFmin != input_clk) ||
2563 (input_index == 1 && od_table->GfxclkFmax != input_clk))
2564 data->gfxclk_overdrive = true;
2566 if (input_index == 0)
2567 od_table->GfxclkFmin = input_clk;
2569 od_table->GfxclkFmax = input_clk;
2574 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2575 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2576 pr_info("Mclk max frequency overdrive not supported\n");
2580 ret = vega20_get_memclocks(hwmgr, &clocks);
2581 PP_ASSERT_WITH_CODE(!ret,
2582 "Attempt to get memory clk levels failed!",
2585 for (i = 0; i < size; i += 2) {
2587 pr_info("invalid number of input parameters %d\n",
2592 input_index = input[i];
2593 input_clk = input[i + 1];
2595 if (input_index != 1) {
2596 pr_info("Invalid index %d\n", input_index);
2597 pr_info("Support max Mclk frequency setting only which index by 1\n");
2601 if (input_clk < clocks.data[0].clocks_in_khz / 1000 ||
2602 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) {
2603 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2605 clocks.data[0].clocks_in_khz / 1000,
2606 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2610 if (input_index == 1 && od_table->UclkFmax != input_clk)
2611 data->memclk_overdrive = true;
2613 od_table->UclkFmax = input_clk;
2618 case PP_OD_EDIT_VDDC_CURVE:
2619 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2620 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2621 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2622 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2623 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2624 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2625 pr_info("Voltage curve calibrate not supported\n");
2629 for (i = 0; i < size; i += 3) {
2631 pr_info("invalid number of input parameters %d\n",
2636 input_index = input[i];
2637 input_clk = input[i + 1];
2638 input_vol = input[i + 2];
2640 if (input_index > 2) {
2641 pr_info("Setting for point %d is not supported\n",
2643 pr_info("Three supported points index by 0, 1, 2\n");
2647 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2648 if (input_clk < od8_settings[od8_id].min_value ||
2649 input_clk > od8_settings[od8_id].max_value) {
2650 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2652 od8_settings[od8_id].min_value,
2653 od8_settings[od8_id].max_value);
2657 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2658 if (input_vol < od8_settings[od8_id].min_value ||
2659 input_vol > od8_settings[od8_id].max_value) {
2660 pr_info("clock voltage %d is not within allowed range [%d - %d]\n",
2662 od8_settings[od8_id].min_value,
2663 od8_settings[od8_id].max_value);
2667 switch (input_index) {
2669 od_table->GfxclkFreq1 = input_clk;
2670 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2673 od_table->GfxclkFreq2 = input_clk;
2674 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2677 od_table->GfxclkFreq3 = input_clk;
2678 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2684 case PP_OD_RESTORE_DEFAULT_TABLE:
2685 data->gfxclk_overdrive = false;
2686 data->memclk_overdrive = false;
2688 ret = smum_smc_table_manager(hwmgr,
2689 (uint8_t *)od_table,
2690 TABLE_OVERDRIVE, true);
2691 PP_ASSERT_WITH_CODE(!ret,
2692 "Failed to export overdrive table!",
2696 case PP_OD_COMMIT_DPM_TABLE:
2697 ret = smum_smc_table_manager(hwmgr,
2698 (uint8_t *)od_table,
2699 TABLE_OVERDRIVE, false);
2700 PP_ASSERT_WITH_CODE(!ret,
2701 "Failed to import overdrive table!",
2704 /* retrieve updated gfxclk table */
2705 if (data->gfxclk_overdrive) {
2706 data->gfxclk_overdrive = false;
2708 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
2713 /* retrieve updated memclk table */
2714 if (data->memclk_overdrive) {
2715 data->memclk_overdrive = false;
2717 ret = vega20_setup_memclk_dpm_table(hwmgr);
2730 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2731 enum pp_clock_type type, char *buf)
2733 struct vega20_hwmgr *data =
2734 (struct vega20_hwmgr *)(hwmgr->backend);
2735 struct vega20_od8_single_setting *od8_settings =
2736 data->od8_settings.od8_settings_array;
2737 OverDriveTable_t *od_table =
2738 &(data->smc_state_table.overdrive_table);
2739 struct pp_clock_levels_with_latency clocks;
2740 int i, now, size = 0;
2745 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now);
2746 PP_ASSERT_WITH_CODE(!ret,
2747 "Attempt to get current gfx clk Failed!",
2750 ret = vega20_get_sclks(hwmgr, &clocks);
2751 PP_ASSERT_WITH_CODE(!ret,
2752 "Attempt to get gfx clk levels Failed!",
2755 for (i = 0; i < clocks.num_levels; i++)
2756 size += sprintf(buf + size, "%d: %uMhz %s\n",
2757 i, clocks.data[i].clocks_in_khz / 1000,
2758 (clocks.data[i].clocks_in_khz == now) ? "*" : "");
2762 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now);
2763 PP_ASSERT_WITH_CODE(!ret,
2764 "Attempt to get current mclk freq Failed!",
2767 ret = vega20_get_memclocks(hwmgr, &clocks);
2768 PP_ASSERT_WITH_CODE(!ret,
2769 "Attempt to get memory clk levels Failed!",
2772 for (i = 0; i < clocks.num_levels; i++)
2773 size += sprintf(buf + size, "%d: %uMhz %s\n",
2774 i, clocks.data[i].clocks_in_khz / 1000,
2775 (clocks.data[i].clocks_in_khz == now) ? "*" : "");
2782 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2783 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
2784 size = sprintf(buf, "%s:\n", "OD_SCLK");
2785 size += sprintf(buf + size, "0: %10uMhz\n",
2786 od_table->GfxclkFmin);
2787 size += sprintf(buf + size, "1: %10uMhz\n",
2788 od_table->GfxclkFmax);
2793 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2794 size = sprintf(buf, "%s:\n", "OD_MCLK");
2795 size += sprintf(buf + size, "1: %10uMhz\n",
2796 od_table->UclkFmax);
2802 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2803 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2804 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2805 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2806 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2807 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
2808 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
2809 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
2810 od_table->GfxclkFreq1,
2811 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
2812 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
2813 od_table->GfxclkFreq2,
2814 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
2815 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
2816 od_table->GfxclkFreq3,
2817 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
2823 size = sprintf(buf, "%s:\n", "OD_RANGE");
2825 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2826 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
2827 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
2828 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2829 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2832 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2833 ret = vega20_get_memclocks(hwmgr, &clocks);
2834 PP_ASSERT_WITH_CODE(!ret,
2835 "Fail to get memory clk levels!",
2838 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
2839 clocks.data[0].clocks_in_khz / 1000,
2840 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2843 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2844 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2845 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2846 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2847 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2848 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
2849 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
2850 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
2851 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
2852 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
2853 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
2854 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
2855 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
2856 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
2857 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
2858 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
2859 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
2860 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
2861 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
2862 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
2863 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
2864 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
2865 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
2866 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
2876 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
2877 struct vega20_single_dpm_table *dpm_table)
2879 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2882 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2883 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
2884 "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
2886 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
2887 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
2890 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2891 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2892 PPSMC_MSG_SetHardMinByFreq,
2893 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
2894 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
2901 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
2903 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2906 smum_send_msg_to_smc_with_parameter(hwmgr,
2907 PPSMC_MSG_NumOfDisplays, 0);
2909 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr,
2910 &data->dpm_table.mem_table);
2915 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
2917 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2919 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
2921 if ((data->water_marks_bitmap & WaterMarksExist) &&
2922 !(data->water_marks_bitmap & WaterMarksLoaded)) {
2923 result = smum_smc_table_manager(hwmgr,
2924 (uint8_t *)wm_table, TABLE_WATERMARKS, false);
2925 PP_ASSERT_WITH_CODE(!result,
2926 "Failed to update WMTABLE!",
2928 data->water_marks_bitmap |= WaterMarksLoaded;
2931 if ((data->water_marks_bitmap & WaterMarksExist) &&
2932 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2933 data->smu_features[GNLD_DPM_SOCCLK].supported) {
2934 result = smum_send_msg_to_smc_with_parameter(hwmgr,
2935 PPSMC_MSG_NumOfDisplays,
2936 hwmgr->display_config->num_display);
2942 int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
2944 struct vega20_hwmgr *data =
2945 (struct vega20_hwmgr *)(hwmgr->backend);
2948 if (data->smu_features[GNLD_DPM_UVD].supported) {
2949 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) {
2951 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n");
2953 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n");
2956 ret = vega20_enable_smc_features(hwmgr,
2958 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap);
2959 PP_ASSERT_WITH_CODE(!ret,
2960 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!",
2962 data->smu_features[GNLD_DPM_UVD].enabled = enable;
2968 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
2970 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2972 if (data->vce_power_gated == bgate)
2975 data->vce_power_gated = bgate;
2976 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
2979 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
2981 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2983 if (data->uvd_power_gated == bgate)
2986 data->uvd_power_gated = bgate;
2987 vega20_enable_disable_uvd_dpm(hwmgr, !bgate);
2990 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
2992 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2993 struct vega20_single_dpm_table *dpm_table;
2994 bool vblank_too_short = false;
2995 bool disable_mclk_switching;
2996 uint32_t i, latency;
2998 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
2999 !hwmgr->display_config->multi_monitor_in_sync) ||
3001 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3004 dpm_table = &(data->dpm_table.gfx_table);
3005 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3006 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3007 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3008 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3010 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3011 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
3012 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3013 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3016 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3017 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3018 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3021 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3022 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3023 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3028 dpm_table = &(data->dpm_table.mem_table);
3029 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3030 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3031 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3032 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3034 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3035 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
3036 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3037 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3040 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
3041 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3042 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3045 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3046 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3047 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3051 /* honour DAL's UCLK Hardmin */
3052 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
3053 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
3055 /* Hardmin is dependent on displayconfig */
3056 if (disable_mclk_switching) {
3057 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3058 for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
3059 if (data->mclk_latency_table.entries[i].latency <= latency) {
3060 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
3061 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
3068 if (hwmgr->display_config->nb_pstate_switch_disable)
3069 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3072 dpm_table = &(data->dpm_table.vclk_table);
3073 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3074 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3075 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3076 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3078 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3079 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3080 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3081 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3084 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3085 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3086 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3091 dpm_table = &(data->dpm_table.dclk_table);
3092 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3093 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3094 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3095 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3097 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3098 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3099 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3100 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3103 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3104 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3105 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3110 dpm_table = &(data->dpm_table.soc_table);
3111 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3112 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3113 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3114 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3116 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3117 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
3118 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3119 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3122 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3123 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3124 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3129 dpm_table = &(data->dpm_table.eclk_table);
3130 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3131 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3132 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3133 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3135 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3136 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
3137 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3138 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3141 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3142 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3143 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3151 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
3153 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3154 bool is_update_required = false;
3156 if (data->display_timing.num_existing_displays !=
3157 hwmgr->display_config->num_display)
3158 is_update_required = true;
3160 if (data->registry_data.gfx_clk_deep_sleep_support &&
3161 (data->display_timing.min_clock_in_sr !=
3162 hwmgr->display_config->min_core_set_clock_in_sr))
3163 is_update_required = true;
3165 return is_update_required;
3168 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
3172 ret = vega20_disable_all_smu_features(hwmgr);
3173 PP_ASSERT_WITH_CODE(!ret,
3174 "[DisableDpmTasks] Failed to disable all smu features!",
3180 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr)
3182 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3185 result = vega20_disable_dpm_tasks(hwmgr);
3186 PP_ASSERT_WITH_CODE((0 == result),
3187 "[PowerOffAsic] Failed to disable DPM!",
3189 data->water_marks_bitmap &= ~(WaterMarksLoaded);
3194 static int conv_power_profile_to_pplib_workload(int power_profile)
3196 int pplib_workload = 0;
3198 switch (power_profile) {
3199 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
3200 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
3202 case PP_SMC_POWER_PROFILE_POWERSAVING:
3203 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
3205 case PP_SMC_POWER_PROFILE_VIDEO:
3206 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
3208 case PP_SMC_POWER_PROFILE_VR:
3209 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
3211 case PP_SMC_POWER_PROFILE_COMPUTE:
3212 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
3214 case PP_SMC_POWER_PROFILE_CUSTOM:
3215 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
3219 return pplib_workload;
3222 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
3224 DpmActivityMonitorCoeffInt_t activity_monitor;
3225 uint32_t i, size = 0;
3226 uint16_t workload_type = 0;
3227 static const char *profile_name[] = {
3234 static const char *title[] = {
3235 "PROFILE_INDEX(NAME)",
3239 "MinActiveFreqType",
3244 "PD_Data_error_coeff",
3245 "PD_Data_error_rate_coeff"};
3251 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
3252 title[0], title[1], title[2], title[3], title[4], title[5],
3253 title[6], title[7], title[8], title[9], title[10]);
3255 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
3256 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
3257 workload_type = conv_power_profile_to_pplib_workload(i);
3258 result = vega20_get_activity_monitor_coeff(hwmgr,
3259 (uint8_t *)(&activity_monitor), workload_type);
3260 PP_ASSERT_WITH_CODE(!result,
3261 "[GetPowerProfile] Failed to get activity monitor!",
3264 size += sprintf(buf + size, "%2d %14s%s:\n",
3265 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
3267 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3271 activity_monitor.Gfx_FPS,
3272 activity_monitor.Gfx_UseRlcBusy,
3273 activity_monitor.Gfx_MinActiveFreqType,
3274 activity_monitor.Gfx_MinActiveFreq,
3275 activity_monitor.Gfx_BoosterFreqType,
3276 activity_monitor.Gfx_BoosterFreq,
3277 activity_monitor.Gfx_PD_Data_limit_c,
3278 activity_monitor.Gfx_PD_Data_error_coeff,
3279 activity_monitor.Gfx_PD_Data_error_rate_coeff);
3281 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3285 activity_monitor.Soc_FPS,
3286 activity_monitor.Soc_UseRlcBusy,
3287 activity_monitor.Soc_MinActiveFreqType,
3288 activity_monitor.Soc_MinActiveFreq,
3289 activity_monitor.Soc_BoosterFreqType,
3290 activity_monitor.Soc_BoosterFreq,
3291 activity_monitor.Soc_PD_Data_limit_c,
3292 activity_monitor.Soc_PD_Data_error_coeff,
3293 activity_monitor.Soc_PD_Data_error_rate_coeff);
3295 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3299 activity_monitor.Mem_FPS,
3300 activity_monitor.Mem_UseRlcBusy,
3301 activity_monitor.Mem_MinActiveFreqType,
3302 activity_monitor.Mem_MinActiveFreq,
3303 activity_monitor.Mem_BoosterFreqType,
3304 activity_monitor.Mem_BoosterFreq,
3305 activity_monitor.Mem_PD_Data_limit_c,
3306 activity_monitor.Mem_PD_Data_error_coeff,
3307 activity_monitor.Mem_PD_Data_error_rate_coeff);
3309 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3313 activity_monitor.Fclk_FPS,
3314 activity_monitor.Fclk_UseRlcBusy,
3315 activity_monitor.Fclk_MinActiveFreqType,
3316 activity_monitor.Fclk_MinActiveFreq,
3317 activity_monitor.Fclk_BoosterFreqType,
3318 activity_monitor.Fclk_BoosterFreq,
3319 activity_monitor.Fclk_PD_Data_limit_c,
3320 activity_monitor.Fclk_PD_Data_error_coeff,
3321 activity_monitor.Fclk_PD_Data_error_rate_coeff);
3327 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
3329 DpmActivityMonitorCoeffInt_t activity_monitor;
3330 int workload_type, result = 0;
3332 hwmgr->power_profile_mode = input[size];
3334 if (hwmgr->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
3335 pr_err("Invalid power profile mode %d\n", hwmgr->power_profile_mode);
3339 if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
3343 result = vega20_get_activity_monitor_coeff(hwmgr,
3344 (uint8_t *)(&activity_monitor),
3345 WORKLOAD_PPLIB_CUSTOM_BIT);
3346 PP_ASSERT_WITH_CODE(!result,
3347 "[SetPowerProfile] Failed to get activity monitor!",
3351 case 0: /* Gfxclk */
3352 activity_monitor.Gfx_FPS = input[1];
3353 activity_monitor.Gfx_UseRlcBusy = input[2];
3354 activity_monitor.Gfx_MinActiveFreqType = input[3];
3355 activity_monitor.Gfx_MinActiveFreq = input[4];
3356 activity_monitor.Gfx_BoosterFreqType = input[5];
3357 activity_monitor.Gfx_BoosterFreq = input[6];
3358 activity_monitor.Gfx_PD_Data_limit_c = input[7];
3359 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
3360 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
3362 case 1: /* Socclk */
3363 activity_monitor.Soc_FPS = input[1];
3364 activity_monitor.Soc_UseRlcBusy = input[2];
3365 activity_monitor.Soc_MinActiveFreqType = input[3];
3366 activity_monitor.Soc_MinActiveFreq = input[4];
3367 activity_monitor.Soc_BoosterFreqType = input[5];
3368 activity_monitor.Soc_BoosterFreq = input[6];
3369 activity_monitor.Soc_PD_Data_limit_c = input[7];
3370 activity_monitor.Soc_PD_Data_error_coeff = input[8];
3371 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
3374 activity_monitor.Mem_FPS = input[1];
3375 activity_monitor.Mem_UseRlcBusy = input[2];
3376 activity_monitor.Mem_MinActiveFreqType = input[3];
3377 activity_monitor.Mem_MinActiveFreq = input[4];
3378 activity_monitor.Mem_BoosterFreqType = input[5];
3379 activity_monitor.Mem_BoosterFreq = input[6];
3380 activity_monitor.Mem_PD_Data_limit_c = input[7];
3381 activity_monitor.Mem_PD_Data_error_coeff = input[8];
3382 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
3385 activity_monitor.Fclk_FPS = input[1];
3386 activity_monitor.Fclk_UseRlcBusy = input[2];
3387 activity_monitor.Fclk_MinActiveFreqType = input[3];
3388 activity_monitor.Fclk_MinActiveFreq = input[4];
3389 activity_monitor.Fclk_BoosterFreqType = input[5];
3390 activity_monitor.Fclk_BoosterFreq = input[6];
3391 activity_monitor.Fclk_PD_Data_limit_c = input[7];
3392 activity_monitor.Fclk_PD_Data_error_coeff = input[8];
3393 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
3397 result = vega20_set_activity_monitor_coeff(hwmgr,
3398 (uint8_t *)(&activity_monitor),
3399 WORKLOAD_PPLIB_CUSTOM_BIT);
3400 PP_ASSERT_WITH_CODE(!result,
3401 "[SetPowerProfile] Failed to set activity monitor!",
3405 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
3407 conv_power_profile_to_pplib_workload(hwmgr->power_profile_mode);
3408 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
3409 1 << workload_type);
3414 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
3415 uint32_t virtual_addr_low,
3416 uint32_t virtual_addr_hi,
3417 uint32_t mc_addr_low,
3418 uint32_t mc_addr_hi,
3421 smum_send_msg_to_smc_with_parameter(hwmgr,
3422 PPSMC_MSG_SetSystemVirtualDramAddrHigh,
3424 smum_send_msg_to_smc_with_parameter(hwmgr,
3425 PPSMC_MSG_SetSystemVirtualDramAddrLow,
3427 smum_send_msg_to_smc_with_parameter(hwmgr,
3428 PPSMC_MSG_DramLogSetDramAddrHigh,
3431 smum_send_msg_to_smc_with_parameter(hwmgr,
3432 PPSMC_MSG_DramLogSetDramAddrLow,
3435 smum_send_msg_to_smc_with_parameter(hwmgr,
3436 PPSMC_MSG_DramLogSetDramSize,
3441 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
3442 struct PP_TemperatureRange *thermal_data)
3444 struct phm_ppt_v3_information *pptable_information =
3445 (struct phm_ppt_v3_information *)hwmgr->pptable;
3447 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
3449 thermal_data->max = pptable_information->us_software_shutdown_temp *
3450 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
3455 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
3456 /* init/fini related */
3458 vega20_hwmgr_backend_init,
3460 vega20_hwmgr_backend_fini,
3462 vega20_setup_asic_task,
3464 vega20_power_off_asic,
3465 .dynamic_state_management_enable =
3466 vega20_enable_dpm_tasks,
3467 .dynamic_state_management_disable =
3468 vega20_disable_dpm_tasks,
3469 /* power state related */
3470 .apply_clocks_adjust_rules =
3471 vega20_apply_clocks_adjust_rules,
3472 .pre_display_config_changed =
3473 vega20_pre_display_configuration_changed_task,
3474 .display_config_changed =
3475 vega20_display_configuration_changed_task,
3476 .check_smc_update_required_for_display_configuration =
3477 vega20_check_smc_update_required_for_display_configuration,
3478 .notify_smc_display_config_after_ps_adjustment =
3479 vega20_notify_smc_display_config_after_ps_adjustment,
3482 vega20_dpm_get_sclk,
3484 vega20_dpm_get_mclk,
3485 .get_dal_power_level =
3486 vega20_get_dal_power_level,
3487 .get_clock_by_type_with_latency =
3488 vega20_get_clock_by_type_with_latency,
3489 .get_clock_by_type_with_voltage =
3490 vega20_get_clock_by_type_with_voltage,
3491 .set_watermarks_for_clocks_ranges =
3492 vega20_set_watermarks_for_clocks_ranges,
3493 .display_clock_voltage_request =
3494 vega20_display_clock_voltage_request,
3495 .get_performance_level =
3496 vega20_get_performance_level,
3497 /* UMD pstate, profile related */
3499 vega20_dpm_force_dpm_level,
3500 .get_power_profile_mode =
3501 vega20_get_power_profile_mode,
3502 .set_power_profile_mode =
3503 vega20_set_power_profile_mode,
3506 vega20_set_power_limit,
3515 .odn_edit_dpm_table =
3516 vega20_odn_edit_dpm_table,
3517 /* for sysfs to retrive/set gfxclk/memclk */
3518 .force_clock_level =
3519 vega20_force_clock_level,
3520 .print_clock_levels =
3521 vega20_print_clock_levels,
3524 /* powergate related */
3526 vega20_power_gate_uvd,
3528 vega20_power_gate_vce,
3529 /* thermal related */
3530 .start_thermal_controller =
3531 vega20_start_thermal_controller,
3532 .stop_thermal_controller =
3533 vega20_thermal_stop_thermal_controller,
3534 .get_thermal_temperature_range =
3535 vega20_get_thermal_temperature_range,
3536 .register_irq_handlers =
3537 smu9_register_irq_handlers,
3538 .disable_smc_firmware_ctf =
3539 vega20_thermal_disable_alert,
3540 /* fan control related */
3541 .get_fan_speed_percent =
3542 vega20_fan_ctrl_get_fan_speed_percent,
3543 .set_fan_speed_percent =
3544 vega20_fan_ctrl_set_fan_speed_percent,
3545 .get_fan_speed_info =
3546 vega20_fan_ctrl_get_fan_speed_info,
3547 .get_fan_speed_rpm =
3548 vega20_fan_ctrl_get_fan_speed_rpm,
3549 .set_fan_speed_rpm =
3550 vega20_fan_ctrl_set_fan_speed_rpm,
3551 .get_fan_control_mode =
3552 vega20_get_fan_control_mode,
3553 .set_fan_control_mode =
3554 vega20_set_fan_control_mode,
3555 /* smu memory related */
3556 .notify_cac_buffer_info =
3557 vega20_notify_cac_buffer_info,
3558 .enable_mgpu_fan_boost =
3559 vega20_enable_mgpu_fan_boost,
3562 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
3564 hwmgr->hwmgr_func = &vega20_hwmgr_funcs;
3565 hwmgr->pptable_func = &vega20_pptable_funcs;