root/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vega20_set_default_registry_data
  2. vega20_set_features_platform_caps
  3. vega20_init_dpm_defaults
  4. vega20_set_private_data_based_on_pptable
  5. vega20_hwmgr_backend_fini
  6. vega20_hwmgr_backend_init
  7. vega20_init_sclk_threshold
  8. vega20_setup_asic_task
  9. vega20_init_dpm_state
  10. vega20_get_number_of_dpm_level
  11. vega20_get_dpm_frequency_by_index
  12. vega20_setup_single_dpm_table
  13. vega20_setup_gfxclk_dpm_table
  14. vega20_setup_memclk_dpm_table
  15. vega20_setup_default_dpm_tables
  16. vega20_init_smc_table
  17. vega20_override_pcie_parameters
  18. vega20_set_allowed_featuresmask
  19. vega20_run_btc
  20. vega20_run_btc_afll
  21. vega20_enable_all_smu_features
  22. vega20_notify_smc_display_change
  23. vega20_send_clock_ratio
  24. vega20_disable_all_smu_features
  25. vega20_od8_set_feature_capabilities
  26. vega20_od8_set_feature_id
  27. vega20_od8_get_gfx_clock_base_voltage
  28. vega20_od8_initialize_default_settings
  29. vega20_od8_set_settings
  30. vega20_get_sclk_od
  31. vega20_set_sclk_od
  32. vega20_get_mclk_od
  33. vega20_set_mclk_od
  34. vega20_populate_umdpstate_clocks
  35. vega20_get_max_sustainable_clock
  36. vega20_init_max_sustainable_clocks
  37. vega20_enable_mgpu_fan_boost
  38. vega20_init_powergate_state
  39. vega20_enable_dpm_tasks
  40. vega20_find_lowest_dpm_level
  41. vega20_find_highest_dpm_level
  42. vega20_upload_dpm_min_level
  43. vega20_upload_dpm_max_level
  44. vega20_enable_disable_vce_dpm
  45. vega20_get_clock_ranges
  46. vega20_dpm_get_sclk
  47. vega20_dpm_get_mclk
  48. vega20_get_metrics_table
  49. vega20_get_gpu_power
  50. vega20_get_current_clk_freq
  51. vega20_get_current_activity_percent
  52. vega20_read_sensor
  53. vega20_display_clock_voltage_request
  54. vega20_get_performance_level
  55. vega20_notify_smc_display_config_after_ps_adjustment
  56. vega20_force_dpm_highest
  57. vega20_force_dpm_lowest
  58. vega20_unforce_dpm_levels
  59. vega20_get_profiling_clk_mask
  60. vega20_force_clock_level
  61. vega20_dpm_force_dpm_level
  62. vega20_get_fan_control_mode
  63. vega20_set_fan_control_mode
  64. vega20_get_dal_power_level
  65. vega20_get_sclks
  66. vega20_get_mem_latency
  67. vega20_get_memclocks
  68. vega20_get_dcefclocks
  69. vega20_get_socclocks
  70. vega20_get_clock_by_type_with_latency
  71. vega20_get_clock_by_type_with_voltage
  72. vega20_set_watermarks_for_clocks_ranges
  73. vega20_odn_edit_dpm_table
  74. vega20_set_mp1_state
  75. vega20_get_ppfeature_status
  76. vega20_set_ppfeature_status
  77. vega20_print_clock_levels
  78. vega20_set_uclk_to_highest_dpm_level
  79. vega20_set_fclk_to_highest_dpm_level
  80. vega20_pre_display_configuration_changed_task
  81. vega20_display_configuration_changed_task
  82. vega20_enable_disable_uvd_dpm
  83. vega20_power_gate_vce
  84. vega20_power_gate_uvd
  85. vega20_apply_clocks_adjust_rules
  86. vega20_check_smc_update_required_for_display_configuration
  87. vega20_disable_dpm_tasks
  88. vega20_power_off_asic
  89. conv_power_profile_to_pplib_workload
  90. vega20_get_power_profile_mode
  91. vega20_set_power_profile_mode
  92. vega20_notify_cac_buffer_info
  93. vega20_get_thermal_temperature_range
  94. vega20_smu_i2c_bus_access
  95. vega20_hwmgr_init

   1 /*
   2  * Copyright 2018 Advanced Micro Devices, Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  */
  23 
  24 #include <linux/delay.h>
  25 #include <linux/fb.h>
  26 #include <linux/module.h>
  27 #include <linux/slab.h>
  28 
  29 #include "hwmgr.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"
  44 #include "pp_debug.h"
  45 #include "amd_pcie_helpers.h"
  46 #include "ppinterrupt.h"
  47 #include "pp_overdriver.h"
  48 #include "pp_thermal.h"
  49 #include "soc15_common.h"
  50 #include "vega20_baco.h"
  51 #include "smuio/smuio_9_0_offset.h"
  52 #include "smuio/smuio_9_0_sh_mask.h"
  53 #include "nbio/nbio_7_4_sh_mask.h"
  54 
  55 #define smnPCIE_LC_SPEED_CNTL                   0x11140290
  56 #define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
  57 
  58 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
  59 {
  60         struct vega20_hwmgr *data =
  61                         (struct vega20_hwmgr *)(hwmgr->backend);
  62 
  63         data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT;
  64         data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT;
  65         data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT;
  66         data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT;
  67         data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT;
  68 
  69         data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT;
  70         data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  71         data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  72         data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  73         data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  74         data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  75         data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  76         data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  77         data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  78         data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  79         data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  80         data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  81         data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
  82 
  83         /*
  84          * Disable the following features for now:
  85          *   GFXCLK DS
  86          *   SOCLK DS
  87          *   LCLK DS
  88          *   DCEFCLK DS
  89          *   FCLK DS
  90          *   MP1CLK DS
  91          *   MP0CLK DS
  92          */
  93         data->registry_data.disallowed_features = 0xE0041C00;
  94         /* ECC feature should be disabled on old SMUs */
  95         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
  96         hwmgr->smu_version = smum_get_argument(hwmgr);
  97         if (hwmgr->smu_version < 0x282100)
  98                 data->registry_data.disallowed_features |= FEATURE_ECC_MASK;
  99 
 100         if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK))
 101                 data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK;
 102 
 103         if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK))
 104                 data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK;
 105 
 106         if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK))
 107                 data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK;
 108 
 109         if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK))
 110                 data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK;
 111 
 112         if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK))
 113                 data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK;
 114 
 115         if (!(hwmgr->feature_mask & PP_ULV_MASK))
 116                 data->registry_data.disallowed_features |= FEATURE_ULV_MASK;
 117 
 118         if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK))
 119                 data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK;
 120 
 121         data->registry_data.od_state_in_dc_support = 0;
 122         data->registry_data.thermal_support = 1;
 123         data->registry_data.skip_baco_hardware = 0;
 124 
 125         data->registry_data.log_avfs_param = 0;
 126         data->registry_data.sclk_throttle_low_notification = 1;
 127         data->registry_data.force_dpm_high = 0;
 128         data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
 129 
 130         data->registry_data.didt_support = 0;
 131         if (data->registry_data.didt_support) {
 132                 data->registry_data.didt_mode = 6;
 133                 data->registry_data.sq_ramping_support = 1;
 134                 data->registry_data.db_ramping_support = 0;
 135                 data->registry_data.td_ramping_support = 0;
 136                 data->registry_data.tcp_ramping_support = 0;
 137                 data->registry_data.dbr_ramping_support = 0;
 138                 data->registry_data.edc_didt_support = 1;
 139                 data->registry_data.gc_didt_support = 0;
 140                 data->registry_data.psm_didt_support = 0;
 141         }
 142 
 143         data->registry_data.pcie_lane_override = 0xff;
 144         data->registry_data.pcie_speed_override = 0xff;
 145         data->registry_data.pcie_clock_override = 0xffffffff;
 146         data->registry_data.regulator_hot_gpio_support = 1;
 147         data->registry_data.ac_dc_switch_gpio_support = 0;
 148         data->registry_data.quick_transition_support = 0;
 149         data->registry_data.zrpm_start_temp = 0xffff;
 150         data->registry_data.zrpm_stop_temp = 0xffff;
 151         data->registry_data.od8_feature_enable = 1;
 152         data->registry_data.disable_water_mark = 0;
 153         data->registry_data.disable_pp_tuning = 0;
 154         data->registry_data.disable_xlpp_tuning = 0;
 155         data->registry_data.disable_workload_policy = 0;
 156         data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
 157         data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
 158         data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
 159         data->registry_data.force_workload_policy_mask = 0;
 160         data->registry_data.disable_3d_fs_detection = 0;
 161         data->registry_data.fps_support = 1;
 162         data->registry_data.disable_auto_wattman = 1;
 163         data->registry_data.auto_wattman_debug = 0;
 164         data->registry_data.auto_wattman_sample_period = 100;
 165         data->registry_data.fclk_gfxclk_ratio = 0;
 166         data->registry_data.auto_wattman_threshold = 50;
 167         data->registry_data.gfxoff_controlled_by_driver = 1;
 168         data->gfxoff_allowed = false;
 169         data->counter_gfxoff = 0;
 170 }
 171 
 172 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
 173 {
 174         struct vega20_hwmgr *data =
 175                         (struct vega20_hwmgr *)(hwmgr->backend);
 176         struct amdgpu_device *adev = hwmgr->adev;
 177 
 178         if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE)
 179                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 180                                 PHM_PlatformCaps_ControlVDDCI);
 181 
 182         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 183                         PHM_PlatformCaps_TablelessHardwareInterface);
 184 
 185         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 186                         PHM_PlatformCaps_EnableSMU7ThermalManagement);
 187 
 188         if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
 189                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 190                                 PHM_PlatformCaps_UVDPowerGating);
 191 
 192         if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
 193                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 194                                 PHM_PlatformCaps_VCEPowerGating);
 195 
 196         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 197                         PHM_PlatformCaps_UnTabledHardwareInterface);
 198 
 199         if (data->registry_data.od8_feature_enable)
 200                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 201                                 PHM_PlatformCaps_OD8inACSupport);
 202 
 203         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 204                         PHM_PlatformCaps_ActivityReporting);
 205         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 206                         PHM_PlatformCaps_FanSpeedInTableIsRPM);
 207 
 208         if (data->registry_data.od_state_in_dc_support) {
 209                 if (data->registry_data.od8_feature_enable)
 210                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 211                                         PHM_PlatformCaps_OD8inDCSupport);
 212         }
 213 
 214         if (data->registry_data.thermal_support &&
 215             data->registry_data.fuzzy_fan_control_support &&
 216             hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
 217                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 218                                 PHM_PlatformCaps_ODFuzzyFanControlSupport);
 219 
 220         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 221                         PHM_PlatformCaps_DynamicPowerManagement);
 222         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 223                         PHM_PlatformCaps_SMC);
 224         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 225                         PHM_PlatformCaps_ThermalPolicyDelay);
 226 
 227         if (data->registry_data.force_dpm_high)
 228                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 229                                 PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
 230 
 231         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 232                         PHM_PlatformCaps_DynamicUVDState);
 233 
 234         if (data->registry_data.sclk_throttle_low_notification)
 235                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 236                                 PHM_PlatformCaps_SclkThrottleLowNotification);
 237 
 238         /* power tune caps */
 239         /* assume disabled */
 240         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 241                         PHM_PlatformCaps_PowerContainment);
 242         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 243                         PHM_PlatformCaps_DiDtSupport);
 244         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 245                         PHM_PlatformCaps_SQRamping);
 246         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 247                         PHM_PlatformCaps_DBRamping);
 248         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 249                         PHM_PlatformCaps_TDRamping);
 250         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 251                         PHM_PlatformCaps_TCPRamping);
 252         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 253                         PHM_PlatformCaps_DBRRamping);
 254         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 255                         PHM_PlatformCaps_DiDtEDCEnable);
 256         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 257                         PHM_PlatformCaps_GCEDC);
 258         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 259                         PHM_PlatformCaps_PSM);
 260 
 261         if (data->registry_data.didt_support) {
 262                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 263                                 PHM_PlatformCaps_DiDtSupport);
 264                 if (data->registry_data.sq_ramping_support)
 265                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 266                                         PHM_PlatformCaps_SQRamping);
 267                 if (data->registry_data.db_ramping_support)
 268                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 269                                         PHM_PlatformCaps_DBRamping);
 270                 if (data->registry_data.td_ramping_support)
 271                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 272                                         PHM_PlatformCaps_TDRamping);
 273                 if (data->registry_data.tcp_ramping_support)
 274                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 275                                         PHM_PlatformCaps_TCPRamping);
 276                 if (data->registry_data.dbr_ramping_support)
 277                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 278                                         PHM_PlatformCaps_DBRRamping);
 279                 if (data->registry_data.edc_didt_support)
 280                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 281                                         PHM_PlatformCaps_DiDtEDCEnable);
 282                 if (data->registry_data.gc_didt_support)
 283                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 284                                         PHM_PlatformCaps_GCEDC);
 285                 if (data->registry_data.psm_didt_support)
 286                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 287                                         PHM_PlatformCaps_PSM);
 288         }
 289 
 290         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 291                         PHM_PlatformCaps_RegulatorHot);
 292 
 293         if (data->registry_data.ac_dc_switch_gpio_support) {
 294                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 295                                 PHM_PlatformCaps_AutomaticDCTransition);
 296                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 297                                 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 298         }
 299 
 300         if (data->registry_data.quick_transition_support) {
 301                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 302                                 PHM_PlatformCaps_AutomaticDCTransition);
 303                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 304                                 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 305                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 306                                 PHM_PlatformCaps_Falcon_QuickTransition);
 307         }
 308 
 309         if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) {
 310                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 311                                 PHM_PlatformCaps_LowestUclkReservedForUlv);
 312                 if (data->lowest_uclk_reserved_for_ulv == 1)
 313                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 314                                         PHM_PlatformCaps_LowestUclkReservedForUlv);
 315         }
 316 
 317         if (data->registry_data.custom_fan_support)
 318                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 319                                 PHM_PlatformCaps_CustomFanControlSupport);
 320 
 321         return 0;
 322 }
 323 
 324 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 325 {
 326         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
 327         struct amdgpu_device *adev = hwmgr->adev;
 328         uint32_t top32, bottom32;
 329         int i;
 330 
 331         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
 332                         FEATURE_DPM_PREFETCHER_BIT;
 333         data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
 334                         FEATURE_DPM_GFXCLK_BIT;
 335         data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
 336                         FEATURE_DPM_UCLK_BIT;
 337         data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
 338                         FEATURE_DPM_SOCCLK_BIT;
 339         data->smu_features[GNLD_DPM_UVD].smu_feature_id =
 340                         FEATURE_DPM_UVD_BIT;
 341         data->smu_features[GNLD_DPM_VCE].smu_feature_id =
 342                         FEATURE_DPM_VCE_BIT;
 343         data->smu_features[GNLD_ULV].smu_feature_id =
 344                         FEATURE_ULV_BIT;
 345         data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
 346                         FEATURE_DPM_MP0CLK_BIT;
 347         data->smu_features[GNLD_DPM_LINK].smu_feature_id =
 348                         FEATURE_DPM_LINK_BIT;
 349         data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
 350                         FEATURE_DPM_DCEFCLK_BIT;
 351         data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
 352                         FEATURE_DS_GFXCLK_BIT;
 353         data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
 354                         FEATURE_DS_SOCCLK_BIT;
 355         data->smu_features[GNLD_DS_LCLK].smu_feature_id =
 356                         FEATURE_DS_LCLK_BIT;
 357         data->smu_features[GNLD_PPT].smu_feature_id =
 358                         FEATURE_PPT_BIT;
 359         data->smu_features[GNLD_TDC].smu_feature_id =
 360                         FEATURE_TDC_BIT;
 361         data->smu_features[GNLD_THERMAL].smu_feature_id =
 362                         FEATURE_THERMAL_BIT;
 363         data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
 364                         FEATURE_GFX_PER_CU_CG_BIT;
 365         data->smu_features[GNLD_RM].smu_feature_id =
 366                         FEATURE_RM_BIT;
 367         data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
 368                         FEATURE_DS_DCEFCLK_BIT;
 369         data->smu_features[GNLD_ACDC].smu_feature_id =
 370                         FEATURE_ACDC_BIT;
 371         data->smu_features[GNLD_VR0HOT].smu_feature_id =
 372                         FEATURE_VR0HOT_BIT;
 373         data->smu_features[GNLD_VR1HOT].smu_feature_id =
 374                         FEATURE_VR1HOT_BIT;
 375         data->smu_features[GNLD_FW_CTF].smu_feature_id =
 376                         FEATURE_FW_CTF_BIT;
 377         data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
 378                         FEATURE_LED_DISPLAY_BIT;
 379         data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
 380                         FEATURE_FAN_CONTROL_BIT;
 381         data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
 382         data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
 383         data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
 384         data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT;
 385         data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT;
 386         data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
 387         data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
 388         data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
 389         data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT;
 390 
 391         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 392                 data->smu_features[i].smu_feature_bitmap =
 393                         (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
 394                 data->smu_features[i].allowed =
 395                         ((data->registry_data.disallowed_features >> i) & 1) ?
 396                         false : true;
 397         }
 398 
 399         /* Get the SN to turn into a Unique ID */
 400         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32);
 401         top32 = smum_get_argument(hwmgr);
 402         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32);
 403         bottom32 = smum_get_argument(hwmgr);
 404 
 405         adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
 406 }
 407 
 408 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
 409 {
 410         return 0;
 411 }
 412 
 413 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 414 {
 415         kfree(hwmgr->backend);
 416         hwmgr->backend = NULL;
 417 
 418         return 0;
 419 }
 420 
 421 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 422 {
 423         struct vega20_hwmgr *data;
 424         struct amdgpu_device *adev = hwmgr->adev;
 425 
 426         data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL);
 427         if (data == NULL)
 428                 return -ENOMEM;
 429 
 430         hwmgr->backend = data;
 431 
 432         hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
 433         hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 434         hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 435 
 436         vega20_set_default_registry_data(hwmgr);
 437 
 438         data->disable_dpm_mask = 0xff;
 439 
 440         /* need to set voltage control types before EVV patching */
 441         data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE;
 442         data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE;
 443         data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE;
 444 
 445         data->water_marks_bitmap = 0;
 446         data->avfs_exist = false;
 447 
 448         vega20_set_features_platform_caps(hwmgr);
 449 
 450         vega20_init_dpm_defaults(hwmgr);
 451 
 452         /* Parse pptable data read from VBIOS */
 453         vega20_set_private_data_based_on_pptable(hwmgr);
 454 
 455         data->is_tlu_enabled = false;
 456 
 457         hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
 458                         VEGA20_MAX_HARDWARE_POWERLEVELS;
 459         hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
 460         hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
 461 
 462         hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
 463         /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
 464         hwmgr->platform_descriptor.clockStep.engineClock = 500;
 465         hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 466 
 467         data->total_active_cus = adev->gfx.cu_info.number;
 468         data->is_custom_profile_set = false;
 469 
 470         return 0;
 471 }
 472 
 473 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr)
 474 {
 475         struct vega20_hwmgr *data =
 476                         (struct vega20_hwmgr *)(hwmgr->backend);
 477 
 478         data->low_sclk_interrupt_threshold = 0;
 479 
 480         return 0;
 481 }
 482 
 483 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
 484 {
 485         struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
 486         int ret = 0;
 487 
 488         ret = vega20_init_sclk_threshold(hwmgr);
 489         PP_ASSERT_WITH_CODE(!ret,
 490                         "Failed to init sclk threshold!",
 491                         return ret);
 492 
 493         if (adev->in_baco_reset) {
 494                 adev->in_baco_reset = 0;
 495 
 496                 ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
 497                 if (ret)
 498                         pr_err("Failed to apply vega20 baco workaround!\n");
 499         }
 500 
 501         return ret;
 502 }
 503 
 504 /*
 505  * @fn vega20_init_dpm_state
 506  * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
 507  *
 508  * @param    dpm_state - the address of the DPM Table to initiailize.
 509  * @return   None.
 510  */
 511 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state)
 512 {
 513         dpm_state->soft_min_level = 0x0;
 514         dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT;
 515         dpm_state->hard_min_level = 0x0;
 516         dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT;
 517 }
 518 
 519 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
 520                 PPCLK_e clk_id, uint32_t *num_of_levels)
 521 {
 522         int ret = 0;
 523 
 524         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 525                         PPSMC_MSG_GetDpmFreqByIndex,
 526                         (clk_id << 16 | 0xFF));
 527         PP_ASSERT_WITH_CODE(!ret,
 528                         "[GetNumOfDpmLevel] failed to get dpm levels!",
 529                         return ret);
 530 
 531         *num_of_levels = smum_get_argument(hwmgr);
 532         PP_ASSERT_WITH_CODE(*num_of_levels > 0,
 533                         "[GetNumOfDpmLevel] number of clk levels is invalid!",
 534                         return -EINVAL);
 535 
 536         return ret;
 537 }
 538 
 539 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
 540                 PPCLK_e clk_id, uint32_t index, uint32_t *clk)
 541 {
 542         int ret = 0;
 543 
 544         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 545                         PPSMC_MSG_GetDpmFreqByIndex,
 546                         (clk_id << 16 | index));
 547         PP_ASSERT_WITH_CODE(!ret,
 548                         "[GetDpmFreqByIndex] failed to get dpm freq by index!",
 549                         return ret);
 550 
 551         *clk = smum_get_argument(hwmgr);
 552         PP_ASSERT_WITH_CODE(*clk,
 553                         "[GetDpmFreqByIndex] clk value is invalid!",
 554                         return -EINVAL);
 555 
 556         return ret;
 557 }
 558 
 559 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
 560                 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id)
 561 {
 562         int ret = 0;
 563         uint32_t i, num_of_levels, clk;
 564 
 565         ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
 566         PP_ASSERT_WITH_CODE(!ret,
 567                         "[SetupSingleDpmTable] failed to get clk levels!",
 568                         return ret);
 569 
 570         dpm_table->count = num_of_levels;
 571 
 572         for (i = 0; i < num_of_levels; i++) {
 573                 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
 574                 PP_ASSERT_WITH_CODE(!ret,
 575                         "[SetupSingleDpmTable] failed to get clk of specific level!",
 576                         return ret);
 577                 dpm_table->dpm_levels[i].value = clk;
 578                 dpm_table->dpm_levels[i].enabled = true;
 579         }
 580 
 581         return ret;
 582 }
 583 
 584 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
 585 {
 586         struct vega20_hwmgr *data =
 587                         (struct vega20_hwmgr *)(hwmgr->backend);
 588         struct vega20_single_dpm_table *dpm_table;
 589         int ret = 0;
 590 
 591         dpm_table = &(data->dpm_table.gfx_table);
 592         if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
 593                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
 594                 PP_ASSERT_WITH_CODE(!ret,
 595                                 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
 596                                 return ret);
 597         } else {
 598                 dpm_table->count = 1;
 599                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
 600         }
 601 
 602         return ret;
 603 }
 604 
 605 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
 606 {
 607         struct vega20_hwmgr *data =
 608                         (struct vega20_hwmgr *)(hwmgr->backend);
 609         struct vega20_single_dpm_table *dpm_table;
 610         int ret = 0;
 611 
 612         dpm_table = &(data->dpm_table.mem_table);
 613         if (data->smu_features[GNLD_DPM_UCLK].enabled) {
 614                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
 615                 PP_ASSERT_WITH_CODE(!ret,
 616                                 "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
 617                                 return ret);
 618         } else {
 619                 dpm_table->count = 1;
 620                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
 621         }
 622 
 623         return ret;
 624 }
 625 
 626 /*
 627  * This function is to initialize all DPM state tables
 628  * for SMU based on the dependency table.
 629  * Dynamic state patching function will then trim these
 630  * state tables to the allowed range based
 631  * on the power policy or external client requests,
 632  * such as UVD request, etc.
 633  */
 634 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 635 {
 636         struct vega20_hwmgr *data =
 637                         (struct vega20_hwmgr *)(hwmgr->backend);
 638         struct vega20_single_dpm_table *dpm_table;
 639         int ret = 0;
 640 
 641         memset(&data->dpm_table, 0, sizeof(data->dpm_table));
 642 
 643         /* socclk */
 644         dpm_table = &(data->dpm_table.soc_table);
 645         if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
 646                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
 647                 PP_ASSERT_WITH_CODE(!ret,
 648                                 "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
 649                                 return ret);
 650         } else {
 651                 dpm_table->count = 1;
 652                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
 653         }
 654         vega20_init_dpm_state(&(dpm_table->dpm_state));
 655 
 656         /* gfxclk */
 657         dpm_table = &(data->dpm_table.gfx_table);
 658         ret = vega20_setup_gfxclk_dpm_table(hwmgr);
 659         if (ret)
 660                 return ret;
 661         vega20_init_dpm_state(&(dpm_table->dpm_state));
 662 
 663         /* memclk */
 664         dpm_table = &(data->dpm_table.mem_table);
 665         ret = vega20_setup_memclk_dpm_table(hwmgr);
 666         if (ret)
 667                 return ret;
 668         vega20_init_dpm_state(&(dpm_table->dpm_state));
 669 
 670         /* eclk */
 671         dpm_table = &(data->dpm_table.eclk_table);
 672         if (data->smu_features[GNLD_DPM_VCE].enabled) {
 673                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
 674                 PP_ASSERT_WITH_CODE(!ret,
 675                                 "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
 676                                 return ret);
 677         } else {
 678                 dpm_table->count = 1;
 679                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
 680         }
 681         vega20_init_dpm_state(&(dpm_table->dpm_state));
 682 
 683         /* vclk */
 684         dpm_table = &(data->dpm_table.vclk_table);
 685         if (data->smu_features[GNLD_DPM_UVD].enabled) {
 686                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
 687                 PP_ASSERT_WITH_CODE(!ret,
 688                                 "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
 689                                 return ret);
 690         } else {
 691                 dpm_table->count = 1;
 692                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
 693         }
 694         vega20_init_dpm_state(&(dpm_table->dpm_state));
 695 
 696         /* dclk */
 697         dpm_table = &(data->dpm_table.dclk_table);
 698         if (data->smu_features[GNLD_DPM_UVD].enabled) {
 699                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
 700                 PP_ASSERT_WITH_CODE(!ret,
 701                                 "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
 702                                 return ret);
 703         } else {
 704                 dpm_table->count = 1;
 705                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
 706         }
 707         vega20_init_dpm_state(&(dpm_table->dpm_state));
 708 
 709         /* dcefclk */
 710         dpm_table = &(data->dpm_table.dcef_table);
 711         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 712                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
 713                 PP_ASSERT_WITH_CODE(!ret,
 714                                 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
 715                                 return ret);
 716         } else {
 717                 dpm_table->count = 1;
 718                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
 719         }
 720         vega20_init_dpm_state(&(dpm_table->dpm_state));
 721 
 722         /* pixclk */
 723         dpm_table = &(data->dpm_table.pixel_table);
 724         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 725                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
 726                 PP_ASSERT_WITH_CODE(!ret,
 727                                 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
 728                                 return ret);
 729         } else
 730                 dpm_table->count = 0;
 731         vega20_init_dpm_state(&(dpm_table->dpm_state));
 732 
 733         /* dispclk */
 734         dpm_table = &(data->dpm_table.display_table);
 735         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 736                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
 737                 PP_ASSERT_WITH_CODE(!ret,
 738                                 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
 739                                 return ret);
 740         } else
 741                 dpm_table->count = 0;
 742         vega20_init_dpm_state(&(dpm_table->dpm_state));
 743 
 744         /* phyclk */
 745         dpm_table = &(data->dpm_table.phy_table);
 746         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 747                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
 748                 PP_ASSERT_WITH_CODE(!ret,
 749                                 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
 750                                 return ret);
 751         } else
 752                 dpm_table->count = 0;
 753         vega20_init_dpm_state(&(dpm_table->dpm_state));
 754 
 755         /* fclk */
 756         dpm_table = &(data->dpm_table.fclk_table);
 757         if (data->smu_features[GNLD_DPM_FCLK].enabled) {
 758                 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK);
 759                 PP_ASSERT_WITH_CODE(!ret,
 760                                 "[SetupDefaultDpmTable] failed to get fclk dpm levels!",
 761                                 return ret);
 762         } else {
 763                 dpm_table->count = 1;
 764                 dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100;
 765         }
 766         vega20_init_dpm_state(&(dpm_table->dpm_state));
 767 
 768         /* save a copy of the default DPM table */
 769         memcpy(&(data->golden_dpm_table), &(data->dpm_table),
 770                         sizeof(struct vega20_dpm_table));
 771 
 772         return 0;
 773 }
 774 
 775 /**
 776 * Initializes the SMC table and uploads it
 777 *
 778 * @param    hwmgr  the address of the powerplay hardware manager.
 779 * @param    pInput  the pointer to input data (PowerState)
 780 * @return   always 0
 781 */
 782 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr)
 783 {
 784         int result;
 785         struct vega20_hwmgr *data =
 786                         (struct vega20_hwmgr *)(hwmgr->backend);
 787         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
 788         struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
 789         struct phm_ppt_v3_information *pptable_information =
 790                 (struct phm_ppt_v3_information *)hwmgr->pptable;
 791 
 792         result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
 793         PP_ASSERT_WITH_CODE(!result,
 794                         "[InitSMCTable] Failed to get vbios bootup values!",
 795                         return result);
 796 
 797         data->vbios_boot_state.vddc     = boot_up_values.usVddc;
 798         data->vbios_boot_state.vddci    = boot_up_values.usVddci;
 799         data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
 800         data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
 801         data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
 802         data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
 803         data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
 804         data->vbios_boot_state.eclock = boot_up_values.ulEClk;
 805         data->vbios_boot_state.vclock = boot_up_values.ulVClk;
 806         data->vbios_boot_state.dclock = boot_up_values.ulDClk;
 807         data->vbios_boot_state.fclock = boot_up_values.ulFClk;
 808         data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
 809 
 810         smum_send_msg_to_smc_with_parameter(hwmgr,
 811                         PPSMC_MSG_SetMinDeepSleepDcefclk,
 812                 (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
 813 
 814         memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
 815 
 816         result = smum_smc_table_manager(hwmgr,
 817                                         (uint8_t *)pp_table, TABLE_PPTABLE, false);
 818         PP_ASSERT_WITH_CODE(!result,
 819                         "[InitSMCTable] Failed to upload PPtable!",
 820                         return result);
 821 
 822         return 0;
 823 }
 824 
 825 /*
 826  * Override PCIe link speed and link width for DPM Level 1. PPTable entries
 827  * reflect the ASIC capabilities and not the system capabilities. For e.g.
 828  * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch
 829  * to DPM1, it fails as system doesn't support Gen4.
 830  */
 831 static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
 832 {
 833         struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
 834         struct vega20_hwmgr *data =
 835                         (struct vega20_hwmgr *)(hwmgr->backend);
 836         uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
 837         int ret;
 838 
 839         if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
 840                 pcie_gen = 3;
 841         else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
 842                 pcie_gen = 2;
 843         else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
 844                 pcie_gen = 1;
 845         else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
 846                 pcie_gen = 0;
 847 
 848         if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
 849                 pcie_width = 6;
 850         else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
 851                 pcie_width = 5;
 852         else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
 853                 pcie_width = 4;
 854         else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
 855                 pcie_width = 3;
 856         else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
 857                 pcie_width = 2;
 858         else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
 859                 pcie_width = 1;
 860 
 861         /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
 862          * Bit 15:8:  PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
 863          * Bit 7:0:   PCIE lane width, 1 to 7 corresponds is x1 to x32
 864          */
 865         smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
 866         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 867                         PPSMC_MSG_OverridePcieParameters, smu_pcie_arg);
 868         PP_ASSERT_WITH_CODE(!ret,
 869                 "[OverridePcieParameters] Attempt to override pcie params failed!",
 870                 return ret);
 871 
 872         data->pcie_parameters_override = 1;
 873         data->pcie_gen_level1 = pcie_gen;
 874         data->pcie_width_level1 = pcie_width;
 875 
 876         return 0;
 877 }
 878 
 879 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 880 {
 881         struct vega20_hwmgr *data =
 882                         (struct vega20_hwmgr *)(hwmgr->backend);
 883         uint32_t allowed_features_low = 0, allowed_features_high = 0;
 884         int i;
 885         int ret = 0;
 886 
 887         for (i = 0; i < GNLD_FEATURES_MAX; i++)
 888                 if (data->smu_features[i].allowed)
 889                         data->smu_features[i].smu_feature_id > 31 ?
 890                                 (allowed_features_high |=
 891                                  ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT)
 892                                   & 0xFFFFFFFF)) :
 893                                 (allowed_features_low |=
 894                                  ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT)
 895                                   & 0xFFFFFFFF));
 896 
 897         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 898                 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high);
 899         PP_ASSERT_WITH_CODE(!ret,
 900                 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!",
 901                 return ret);
 902 
 903         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 904                 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low);
 905         PP_ASSERT_WITH_CODE(!ret,
 906                 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
 907                 return ret);
 908 
 909         return 0;
 910 }
 911 
 912 static int vega20_run_btc(struct pp_hwmgr *hwmgr)
 913 {
 914         return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc);
 915 }
 916 
 917 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
 918 {
 919         return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc);
 920 }
 921 
 922 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)
 923 {
 924         struct vega20_hwmgr *data =
 925                         (struct vega20_hwmgr *)(hwmgr->backend);
 926         uint64_t features_enabled;
 927         int i;
 928         bool enabled;
 929         int ret = 0;
 930 
 931         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
 932                         PPSMC_MSG_EnableAllSmuFeatures)) == 0,
 933                         "[EnableAllSMUFeatures] Failed to enable all smu features!",
 934                         return ret);
 935 
 936         ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
 937         PP_ASSERT_WITH_CODE(!ret,
 938                         "[EnableAllSmuFeatures] Failed to get enabled smc features!",
 939                         return ret);
 940 
 941         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 942                 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
 943                         true : false;
 944                 data->smu_features[i].enabled = enabled;
 945                 data->smu_features[i].supported = enabled;
 946 
 947 #if 0
 948                 if (data->smu_features[i].allowed && !enabled)
 949                         pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i);
 950                 else if (!data->smu_features[i].allowed && enabled)
 951                         pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i);
 952 #endif
 953         }
 954 
 955         return 0;
 956 }
 957 
 958 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr)
 959 {
 960         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
 961 
 962         if (data->smu_features[GNLD_DPM_UCLK].enabled)
 963                 return smum_send_msg_to_smc_with_parameter(hwmgr,
 964                         PPSMC_MSG_SetUclkFastSwitch,
 965                         1);
 966 
 967         return 0;
 968 }
 969 
 970 static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr)
 971 {
 972         struct vega20_hwmgr *data =
 973                         (struct vega20_hwmgr *)(hwmgr->backend);
 974 
 975         return smum_send_msg_to_smc_with_parameter(hwmgr,
 976                         PPSMC_MSG_SetFclkGfxClkRatio,
 977                         data->registry_data.fclk_gfxclk_ratio);
 978 }
 979 
 980 static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr)
 981 {
 982         struct vega20_hwmgr *data =
 983                         (struct vega20_hwmgr *)(hwmgr->backend);
 984         uint64_t features_enabled;
 985         int i;
 986         bool enabled;
 987         int ret = 0;
 988 
 989         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
 990                         PPSMC_MSG_DisableAllSmuFeatures)) == 0,
 991                         "[DisableAllSMUFeatures] Failed to disable all smu features!",
 992                         return ret);
 993 
 994         ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
 995         PP_ASSERT_WITH_CODE(!ret,
 996                         "[DisableAllSMUFeatures] Failed to get enabled smc features!",
 997                         return ret);
 998 
 999         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
1000                 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
1001                         true : false;
1002                 data->smu_features[i].enabled = enabled;
1003                 data->smu_features[i].supported = enabled;
1004         }
1005 
1006         return 0;
1007 }
1008 
1009 static int vega20_od8_set_feature_capabilities(
1010                 struct pp_hwmgr *hwmgr)
1011 {
1012         struct phm_ppt_v3_information *pptable_information =
1013                 (struct phm_ppt_v3_information *)hwmgr->pptable;
1014         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1015         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1016         struct vega20_od8_settings *od_settings = &(data->od8_settings);
1017 
1018         od_settings->overdrive8_capabilities = 0;
1019 
1020         if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1021                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
1022                     pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
1023                     pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
1024                     (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
1025                     pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN]))
1026                         od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS;
1027 
1028                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
1029                     (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
1030                      pp_table->MinVoltageGfx / VOLTAGE_SCALE) &&
1031                     (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1032                      pp_table->MaxVoltageGfx / VOLTAGE_SCALE) &&
1033                     (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >=
1034                      pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1]))
1035                         od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE;
1036         }
1037 
1038         if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1039                 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] =
1040                         data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value;
1041                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1042                     pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1043                     pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1044                     (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1045                     pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX]))
1046                         od_settings->overdrive8_capabilities |= OD8_UCLK_MAX;
1047         }
1048 
1049         if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1050             pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1051             pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1052             pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1053             pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100)
1054                 od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT;
1055 
1056         if (data->smu_features[GNLD_FAN_CONTROL].enabled) {
1057                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1058                     pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1059                     pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1060                     (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1061                      pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT]))
1062                         od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK;
1063 
1064                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1065                     (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >=
1066                     (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) &&
1067                     pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1068                     (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1069                      pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED]))
1070                         od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN;
1071         }
1072 
1073         if (data->smu_features[GNLD_THERMAL].enabled) {
1074                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1075                     pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1076                     pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1077                     (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1078                      pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP]))
1079                         od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN;
1080 
1081                 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1082                     pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1083                     pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1084                     (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1085                      pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX]))
1086                         od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM;
1087         }
1088 
1089         if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE])
1090                 od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE;
1091 
1092         if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] &&
1093             pp_table->FanZeroRpmEnable)
1094                 od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
1095 
1096         if (!od_settings->overdrive8_capabilities)
1097                 hwmgr->od_enabled = false;
1098 
1099         return 0;
1100 }
1101 
1102 static int vega20_od8_set_feature_id(
1103                 struct pp_hwmgr *hwmgr)
1104 {
1105         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1106         struct vega20_od8_settings *od_settings = &(data->od8_settings);
1107 
1108         if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1109                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1110                         OD8_GFXCLK_LIMITS;
1111                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1112                         OD8_GFXCLK_LIMITS;
1113         } else {
1114                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1115                         0;
1116                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1117                         0;
1118         }
1119 
1120         if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1121                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1122                         OD8_GFXCLK_CURVE;
1123                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1124                         OD8_GFXCLK_CURVE;
1125                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1126                         OD8_GFXCLK_CURVE;
1127                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1128                         OD8_GFXCLK_CURVE;
1129                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1130                         OD8_GFXCLK_CURVE;
1131                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1132                         OD8_GFXCLK_CURVE;
1133         } else {
1134                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1135                         0;
1136                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1137                         0;
1138                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1139                         0;
1140                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1141                         0;
1142                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1143                         0;
1144                 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1145                         0;
1146         }
1147 
1148         if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1149                 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX;
1150         else
1151                 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0;
1152 
1153         if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1154                 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT;
1155         else
1156                 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0;
1157 
1158         if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1159                 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1160                         OD8_ACOUSTIC_LIMIT_SCLK;
1161         else
1162                 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1163                         0;
1164 
1165         if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1166                 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1167                         OD8_FAN_SPEED_MIN;
1168         else
1169                 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1170                         0;
1171 
1172         if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1173                 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1174                         OD8_TEMPERATURE_FAN;
1175         else
1176                 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1177                         0;
1178 
1179         if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1180                 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1181                         OD8_TEMPERATURE_SYSTEM;
1182         else
1183                 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1184                         0;
1185 
1186         return 0;
1187 }
1188 
1189 static int vega20_od8_get_gfx_clock_base_voltage(
1190                 struct pp_hwmgr *hwmgr,
1191                 uint32_t *voltage,
1192                 uint32_t freq)
1193 {
1194         int ret = 0;
1195 
1196         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1197                         PPSMC_MSG_GetAVFSVoltageByDpm,
1198                         ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1199         PP_ASSERT_WITH_CODE(!ret,
1200                         "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!",
1201                         return ret);
1202 
1203         *voltage = smum_get_argument(hwmgr);
1204         *voltage = *voltage / VOLTAGE_SCALE;
1205 
1206         return 0;
1207 }
1208 
1209 static int vega20_od8_initialize_default_settings(
1210                 struct pp_hwmgr *hwmgr)
1211 {
1212         struct phm_ppt_v3_information *pptable_information =
1213                 (struct phm_ppt_v3_information *)hwmgr->pptable;
1214         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1215         struct vega20_od8_settings *od8_settings = &(data->od8_settings);
1216         OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table);
1217         int i, ret = 0;
1218 
1219         /* Set Feature Capabilities */
1220         vega20_od8_set_feature_capabilities(hwmgr);
1221 
1222         /* Map FeatureID to individual settings */
1223         vega20_od8_set_feature_id(hwmgr);
1224 
1225         /* Set default values */
1226         ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true);
1227         PP_ASSERT_WITH_CODE(!ret,
1228                         "Failed to export over drive table!",
1229                         return ret);
1230 
1231         if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1232                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1233                         od_table->GfxclkFmin;
1234                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1235                         od_table->GfxclkFmax;
1236         } else {
1237                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1238                         0;
1239                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1240                         0;
1241         }
1242 
1243         if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1244                 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1245                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1246                         od_table->GfxclkFreq1;
1247 
1248                 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1249                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1250                         od_table->GfxclkFreq3;
1251 
1252                 od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2;
1253                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1254                         od_table->GfxclkFreq2;
1255 
1256                 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1257                                    &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value),
1258                                      od_table->GfxclkFreq1),
1259                                 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1260                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0);
1261                 od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1262                         * VOLTAGE_SCALE;
1263 
1264                 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1265                                    &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value),
1266                                      od_table->GfxclkFreq2),
1267                                 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1268                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0);
1269                 od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1270                         * VOLTAGE_SCALE;
1271 
1272                 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1273                                    &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value),
1274                                      od_table->GfxclkFreq3),
1275                                 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1276                                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0);
1277                 od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1278                         * VOLTAGE_SCALE;
1279         } else {
1280                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1281                         0;
1282                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value =
1283                         0;
1284                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1285                         0;
1286                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value =
1287                         0;
1288                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1289                         0;
1290                 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value =
1291                         0;
1292         }
1293 
1294         if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1295                 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1296                         od_table->UclkFmax;
1297         else
1298                 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1299                         0;
1300 
1301         if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1302                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1303                         od_table->OverDrivePct;
1304         else
1305                 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1306                         0;
1307 
1308         if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1309                 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1310                         od_table->FanMaximumRpm;
1311         else
1312                 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1313                         0;
1314 
1315         if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1316                 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1317                         od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100;
1318         else
1319                 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1320                         0;
1321 
1322         if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1323                 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1324                         od_table->FanTargetTemperature;
1325         else
1326                 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1327                         0;
1328 
1329         if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1330                 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1331                         od_table->MaxOpTemp;
1332         else
1333                 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1334                         0;
1335 
1336         for (i = 0; i < OD8_SETTING_COUNT; i++) {
1337                 if (od8_settings->od8_settings_array[i].feature_id) {
1338                         od8_settings->od8_settings_array[i].min_value =
1339                                 pptable_information->od_settings_min[i];
1340                         od8_settings->od8_settings_array[i].max_value =
1341                                 pptable_information->od_settings_max[i];
1342                         od8_settings->od8_settings_array[i].current_value =
1343                                 od8_settings->od8_settings_array[i].default_value;
1344                 } else {
1345                         od8_settings->od8_settings_array[i].min_value =
1346                                 0;
1347                         od8_settings->od8_settings_array[i].max_value =
1348                                 0;
1349                         od8_settings->od8_settings_array[i].current_value =
1350                                 0;
1351                 }
1352         }
1353 
1354         ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false);
1355         PP_ASSERT_WITH_CODE(!ret,
1356                         "Failed to import over drive table!",
1357                         return ret);
1358 
1359         return 0;
1360 }
1361 
1362 static int vega20_od8_set_settings(
1363                 struct pp_hwmgr *hwmgr,
1364                 uint32_t index,
1365                 uint32_t value)
1366 {
1367         OverDriveTable_t od_table;
1368         int ret = 0;
1369         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1370         struct vega20_od8_single_setting *od8_settings =
1371                         data->od8_settings.od8_settings_array;
1372 
1373         ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true);
1374         PP_ASSERT_WITH_CODE(!ret,
1375                         "Failed to export over drive table!",
1376                         return ret);
1377 
1378         switch(index) {
1379         case OD8_SETTING_GFXCLK_FMIN:
1380                 od_table.GfxclkFmin = (uint16_t)value;
1381                 break;
1382         case OD8_SETTING_GFXCLK_FMAX:
1383                 if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value ||
1384                     value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value)
1385                         return -EINVAL;
1386 
1387                 od_table.GfxclkFmax = (uint16_t)value;
1388                 break;
1389         case OD8_SETTING_GFXCLK_FREQ1:
1390                 od_table.GfxclkFreq1 = (uint16_t)value;
1391                 break;
1392         case OD8_SETTING_GFXCLK_VOLTAGE1:
1393                 od_table.GfxclkVolt1 = (uint16_t)value;
1394                 break;
1395         case OD8_SETTING_GFXCLK_FREQ2:
1396                 od_table.GfxclkFreq2 = (uint16_t)value;
1397                 break;
1398         case OD8_SETTING_GFXCLK_VOLTAGE2:
1399                 od_table.GfxclkVolt2 = (uint16_t)value;
1400                 break;
1401         case OD8_SETTING_GFXCLK_FREQ3:
1402                 od_table.GfxclkFreq3 = (uint16_t)value;
1403                 break;
1404         case OD8_SETTING_GFXCLK_VOLTAGE3:
1405                 od_table.GfxclkVolt3 = (uint16_t)value;
1406                 break;
1407         case OD8_SETTING_UCLK_FMAX:
1408                 if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
1409                     value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value)
1410                         return -EINVAL;
1411                 od_table.UclkFmax = (uint16_t)value;
1412                 break;
1413         case OD8_SETTING_POWER_PERCENTAGE:
1414                 od_table.OverDrivePct = (int16_t)value;
1415                 break;
1416         case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
1417                 od_table.FanMaximumRpm = (uint16_t)value;
1418                 break;
1419         case OD8_SETTING_FAN_MIN_SPEED:
1420                 od_table.FanMinimumPwm = (uint16_t)value;
1421                 break;
1422         case OD8_SETTING_FAN_TARGET_TEMP:
1423                 od_table.FanTargetTemperature = (uint16_t)value;
1424                 break;
1425         case OD8_SETTING_OPERATING_TEMP_MAX:
1426                 od_table.MaxOpTemp = (uint16_t)value;
1427                 break;
1428         }
1429 
1430         ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false);
1431         PP_ASSERT_WITH_CODE(!ret,
1432                         "Failed to import over drive table!",
1433                         return ret);
1434 
1435         return 0;
1436 }
1437 
1438 static int vega20_get_sclk_od(
1439                 struct pp_hwmgr *hwmgr)
1440 {
1441         struct vega20_hwmgr *data = hwmgr->backend;
1442         struct vega20_single_dpm_table *sclk_table =
1443                         &(data->dpm_table.gfx_table);
1444         struct vega20_single_dpm_table *golden_sclk_table =
1445                         &(data->golden_dpm_table.gfx_table);
1446         int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
1447         int golden_value = golden_sclk_table->dpm_levels
1448                         [golden_sclk_table->count - 1].value;
1449 
1450         /* od percentage */
1451         value -= golden_value;
1452         value = DIV_ROUND_UP(value * 100, golden_value);
1453 
1454         return value;
1455 }
1456 
1457 static int vega20_set_sclk_od(
1458                 struct pp_hwmgr *hwmgr, uint32_t value)
1459 {
1460         struct vega20_hwmgr *data = hwmgr->backend;
1461         struct vega20_single_dpm_table *golden_sclk_table =
1462                         &(data->golden_dpm_table.gfx_table);
1463         uint32_t od_sclk;
1464         int ret = 0;
1465 
1466         od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value;
1467         od_sclk /= 100;
1468         od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
1469 
1470         ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk);
1471         PP_ASSERT_WITH_CODE(!ret,
1472                         "[SetSclkOD] failed to set od gfxclk!",
1473                         return ret);
1474 
1475         /* retrieve updated gfxclk table */
1476         ret = vega20_setup_gfxclk_dpm_table(hwmgr);
1477         PP_ASSERT_WITH_CODE(!ret,
1478                         "[SetSclkOD] failed to refresh gfxclk table!",
1479                         return ret);
1480 
1481         return 0;
1482 }
1483 
1484 static int vega20_get_mclk_od(
1485                 struct pp_hwmgr *hwmgr)
1486 {
1487         struct vega20_hwmgr *data = hwmgr->backend;
1488         struct vega20_single_dpm_table *mclk_table =
1489                         &(data->dpm_table.mem_table);
1490         struct vega20_single_dpm_table *golden_mclk_table =
1491                         &(data->golden_dpm_table.mem_table);
1492         int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
1493         int golden_value = golden_mclk_table->dpm_levels
1494                         [golden_mclk_table->count - 1].value;
1495 
1496         /* od percentage */
1497         value -= golden_value;
1498         value = DIV_ROUND_UP(value * 100, golden_value);
1499 
1500         return value;
1501 }
1502 
1503 static int vega20_set_mclk_od(
1504                 struct pp_hwmgr *hwmgr, uint32_t value)
1505 {
1506         struct vega20_hwmgr *data = hwmgr->backend;
1507         struct vega20_single_dpm_table *golden_mclk_table =
1508                         &(data->golden_dpm_table.mem_table);
1509         uint32_t od_mclk;
1510         int ret = 0;
1511 
1512         od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value;
1513         od_mclk /= 100;
1514         od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
1515 
1516         ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk);
1517         PP_ASSERT_WITH_CODE(!ret,
1518                         "[SetMclkOD] failed to set od memclk!",
1519                         return ret);
1520 
1521         /* retrieve updated memclk table */
1522         ret = vega20_setup_memclk_dpm_table(hwmgr);
1523         PP_ASSERT_WITH_CODE(!ret,
1524                         "[SetMclkOD] failed to refresh memclk table!",
1525                         return ret);
1526 
1527         return 0;
1528 }
1529 
1530 static int vega20_populate_umdpstate_clocks(
1531                 struct pp_hwmgr *hwmgr)
1532 {
1533         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1534         struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table);
1535         struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table);
1536 
1537         hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value;
1538         hwmgr->pstate_mclk = mem_table->dpm_levels[0].value;
1539 
1540         if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1541             mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
1542                 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1543                 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1544         }
1545 
1546         hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100;
1547         hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100;
1548 
1549         return 0;
1550 }
1551 
1552 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr,
1553                 PP_Clock *clock, PPCLK_e clock_select)
1554 {
1555         int ret = 0;
1556 
1557         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1558                         PPSMC_MSG_GetDcModeMaxDpmFreq,
1559                         (clock_select << 16))) == 0,
1560                         "[GetMaxSustainableClock] Failed to get max DC clock from SMC!",
1561                         return ret);
1562         *clock = smum_get_argument(hwmgr);
1563 
1564         /* if DC limit is zero, return AC limit */
1565         if (*clock == 0) {
1566                 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1567                         PPSMC_MSG_GetMaxDpmFreq,
1568                         (clock_select << 16))) == 0,
1569                         "[GetMaxSustainableClock] failed to get max AC clock from SMC!",
1570                         return ret);
1571                 *clock = smum_get_argument(hwmgr);
1572         }
1573 
1574         return 0;
1575 }
1576 
1577 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr)
1578 {
1579         struct vega20_hwmgr *data =
1580                 (struct vega20_hwmgr *)(hwmgr->backend);
1581         struct vega20_max_sustainable_clocks *max_sustainable_clocks =
1582                 &(data->max_sustainable_clocks);
1583         int ret = 0;
1584 
1585         max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100;
1586         max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100;
1587         max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100;
1588         max_sustainable_clocks->display_clock = 0xFFFFFFFF;
1589         max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
1590         max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
1591 
1592         if (data->smu_features[GNLD_DPM_UCLK].enabled)
1593                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1594                                 &(max_sustainable_clocks->uclock),
1595                                 PPCLK_UCLK)) == 0,
1596                                 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!",
1597                                 return ret);
1598 
1599         if (data->smu_features[GNLD_DPM_SOCCLK].enabled)
1600                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1601                                 &(max_sustainable_clocks->soc_clock),
1602                                 PPCLK_SOCCLK)) == 0,
1603                                 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!",
1604                                 return ret);
1605 
1606         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1607                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1608                                 &(max_sustainable_clocks->dcef_clock),
1609                                 PPCLK_DCEFCLK)) == 0,
1610                                 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!",
1611                                 return ret);
1612                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1613                                 &(max_sustainable_clocks->display_clock),
1614                                 PPCLK_DISPCLK)) == 0,
1615                                 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!",
1616                                 return ret);
1617                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1618                                 &(max_sustainable_clocks->phy_clock),
1619                                 PPCLK_PHYCLK)) == 0,
1620                                 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!",
1621                                 return ret);
1622                 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1623                                 &(max_sustainable_clocks->pixel_clock),
1624                                 PPCLK_PIXCLK)) == 0,
1625                                 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!",
1626                                 return ret);
1627         }
1628 
1629         if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
1630                 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;
1631 
1632         return 0;
1633 }
1634 
1635 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
1636 {
1637         int result;
1638 
1639         result = smum_send_msg_to_smc(hwmgr,
1640                 PPSMC_MSG_SetMGpuFanBoostLimitRpm);
1641         PP_ASSERT_WITH_CODE(!result,
1642                         "[EnableMgpuFan] Failed to enable mgpu fan boost!",
1643                         return result);
1644 
1645         return 0;
1646 }
1647 
1648 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr)
1649 {
1650         struct vega20_hwmgr *data =
1651                 (struct vega20_hwmgr *)(hwmgr->backend);
1652 
1653         data->uvd_power_gated = true;
1654         data->vce_power_gated = true;
1655 
1656         if (data->smu_features[GNLD_DPM_UVD].enabled)
1657                 data->uvd_power_gated = false;
1658 
1659         if (data->smu_features[GNLD_DPM_VCE].enabled)
1660                 data->vce_power_gated = false;
1661 }
1662 
1663 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1664 {
1665         int result = 0;
1666 
1667         smum_send_msg_to_smc_with_parameter(hwmgr,
1668                         PPSMC_MSG_NumOfDisplays, 0);
1669 
1670         result = vega20_set_allowed_featuresmask(hwmgr);
1671         PP_ASSERT_WITH_CODE(!result,
1672                         "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
1673                         return result);
1674 
1675         result = vega20_init_smc_table(hwmgr);
1676         PP_ASSERT_WITH_CODE(!result,
1677                         "[EnableDPMTasks] Failed to initialize SMC table!",
1678                         return result);
1679 
1680         result = vega20_run_btc(hwmgr);
1681         PP_ASSERT_WITH_CODE(!result,
1682                         "[EnableDPMTasks] Failed to run btc!",
1683                         return result);
1684 
1685         result = vega20_run_btc_afll(hwmgr);
1686         PP_ASSERT_WITH_CODE(!result,
1687                         "[EnableDPMTasks] Failed to run btc afll!",
1688                         return result);
1689 
1690         result = vega20_enable_all_smu_features(hwmgr);
1691         PP_ASSERT_WITH_CODE(!result,
1692                         "[EnableDPMTasks] Failed to enable all smu features!",
1693                         return result);
1694 
1695         result = vega20_override_pcie_parameters(hwmgr);
1696         PP_ASSERT_WITH_CODE(!result,
1697                         "[EnableDPMTasks] Failed to override pcie parameters!",
1698                         return result);
1699 
1700         result = vega20_notify_smc_display_change(hwmgr);
1701         PP_ASSERT_WITH_CODE(!result,
1702                         "[EnableDPMTasks] Failed to notify smc display change!",
1703                         return result);
1704 
1705         result = vega20_send_clock_ratio(hwmgr);
1706         PP_ASSERT_WITH_CODE(!result,
1707                         "[EnableDPMTasks] Failed to send clock ratio!",
1708                         return result);
1709 
1710         /* Initialize UVD/VCE powergating state */
1711         vega20_init_powergate_state(hwmgr);
1712 
1713         result = vega20_setup_default_dpm_tables(hwmgr);
1714         PP_ASSERT_WITH_CODE(!result,
1715                         "[EnableDPMTasks] Failed to setup default DPM tables!",
1716                         return result);
1717 
1718         result = vega20_init_max_sustainable_clocks(hwmgr);
1719         PP_ASSERT_WITH_CODE(!result,
1720                         "[EnableDPMTasks] Failed to get maximum sustainable clocks!",
1721                         return result);
1722 
1723         result = vega20_power_control_set_level(hwmgr);
1724         PP_ASSERT_WITH_CODE(!result,
1725                         "[EnableDPMTasks] Failed to power control set level!",
1726                         return result);
1727 
1728         result = vega20_od8_initialize_default_settings(hwmgr);
1729         PP_ASSERT_WITH_CODE(!result,
1730                         "[EnableDPMTasks] Failed to initialize odn settings!",
1731                         return result);
1732 
1733         result = vega20_populate_umdpstate_clocks(hwmgr);
1734         PP_ASSERT_WITH_CODE(!result,
1735                         "[EnableDPMTasks] Failed to populate umdpstate clocks!",
1736                         return result);
1737 
1738         result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit,
1739                         POWER_SOURCE_AC << 16);
1740         PP_ASSERT_WITH_CODE(!result,
1741                         "[GetPptLimit] get default PPT limit failed!",
1742                         return result);
1743         hwmgr->power_limit =
1744                 hwmgr->default_power_limit = smum_get_argument(hwmgr);
1745 
1746         return 0;
1747 }
1748 
1749 static uint32_t vega20_find_lowest_dpm_level(
1750                 struct vega20_single_dpm_table *table)
1751 {
1752         uint32_t i;
1753 
1754         for (i = 0; i < table->count; i++) {
1755                 if (table->dpm_levels[i].enabled)
1756                         break;
1757         }
1758         if (i >= table->count) {
1759                 i = 0;
1760                 table->dpm_levels[i].enabled = true;
1761         }
1762 
1763         return i;
1764 }
1765 
1766 static uint32_t vega20_find_highest_dpm_level(
1767                 struct vega20_single_dpm_table *table)
1768 {
1769         int i = 0;
1770 
1771         PP_ASSERT_WITH_CODE(table != NULL,
1772                         "[FindHighestDPMLevel] DPM Table does not exist!",
1773                         return 0);
1774         PP_ASSERT_WITH_CODE(table->count > 0,
1775                         "[FindHighestDPMLevel] DPM Table has no entry!",
1776                         return 0);
1777         PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER,
1778                         "[FindHighestDPMLevel] DPM Table has too many entries!",
1779                         return MAX_REGULAR_DPM_NUMBER - 1);
1780 
1781         for (i = table->count - 1; i >= 0; i--) {
1782                 if (table->dpm_levels[i].enabled)
1783                         break;
1784         }
1785         if (i < 0) {
1786                 i = 0;
1787                 table->dpm_levels[i].enabled = true;
1788         }
1789 
1790         return i;
1791 }
1792 
1793 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1794 {
1795         struct vega20_hwmgr *data =
1796                         (struct vega20_hwmgr *)(hwmgr->backend);
1797         uint32_t min_freq;
1798         int ret = 0;
1799 
1800         if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1801            (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1802                 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
1803                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1804                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1805                                         (PPCLK_GFXCLK << 16) | (min_freq & 0xffff))),
1806                                         "Failed to set soft min gfxclk !",
1807                                         return ret);
1808         }
1809 
1810         if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1811            (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1812                 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
1813                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1814                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1815                                         (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
1816                                         "Failed to set soft min memclk !",
1817                                         return ret);
1818         }
1819 
1820         if (data->smu_features[GNLD_DPM_UVD].enabled &&
1821            (feature_mask & FEATURE_DPM_UVD_MASK)) {
1822                 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
1823 
1824                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1825                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1826                                         (PPCLK_VCLK << 16) | (min_freq & 0xffff))),
1827                                         "Failed to set soft min vclk!",
1828                                         return ret);
1829 
1830                 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level;
1831 
1832                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1833                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1834                                         (PPCLK_DCLK << 16) | (min_freq & 0xffff))),
1835                                         "Failed to set soft min dclk!",
1836                                         return ret);
1837         }
1838 
1839         if (data->smu_features[GNLD_DPM_VCE].enabled &&
1840            (feature_mask & FEATURE_DPM_VCE_MASK)) {
1841                 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
1842 
1843                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1844                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1845                                         (PPCLK_ECLK << 16) | (min_freq & 0xffff))),
1846                                         "Failed to set soft min eclk!",
1847                                         return ret);
1848         }
1849 
1850         if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1851            (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1852                 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
1853 
1854                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1855                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1856                                         (PPCLK_SOCCLK << 16) | (min_freq & 0xffff))),
1857                                         "Failed to set soft min socclk!",
1858                                         return ret);
1859         }
1860 
1861         if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1862            (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1863                 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
1864 
1865                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1866                                         hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1867                                         (PPCLK_FCLK << 16) | (min_freq & 0xffff))),
1868                                         "Failed to set soft min fclk!",
1869                                         return ret);
1870         }
1871 
1872         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
1873            (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1874                 min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
1875 
1876                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1877                                         hwmgr, PPSMC_MSG_SetHardMinByFreq,
1878                                         (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
1879                                         "Failed to set hard min dcefclk!",
1880                                         return ret);
1881         }
1882 
1883         return ret;
1884 }
1885 
1886 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1887 {
1888         struct vega20_hwmgr *data =
1889                         (struct vega20_hwmgr *)(hwmgr->backend);
1890         uint32_t max_freq;
1891         int ret = 0;
1892 
1893         if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1894            (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1895                 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
1896 
1897                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1898                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1899                                         (PPCLK_GFXCLK << 16) | (max_freq & 0xffff))),
1900                                         "Failed to set soft max gfxclk!",
1901                                         return ret);
1902         }
1903 
1904         if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1905            (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1906                 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
1907 
1908                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1909                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1910                                         (PPCLK_UCLK << 16) | (max_freq & 0xffff))),
1911                                         "Failed to set soft max memclk!",
1912                                         return ret);
1913         }
1914 
1915         if (data->smu_features[GNLD_DPM_UVD].enabled &&
1916            (feature_mask & FEATURE_DPM_UVD_MASK)) {
1917                 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
1918 
1919                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1920                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1921                                         (PPCLK_VCLK << 16) | (max_freq & 0xffff))),
1922                                         "Failed to set soft max vclk!",
1923                                         return ret);
1924 
1925                 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level;
1926                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1927                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1928                                         (PPCLK_DCLK << 16) | (max_freq & 0xffff))),
1929                                         "Failed to set soft max dclk!",
1930                                         return ret);
1931         }
1932 
1933         if (data->smu_features[GNLD_DPM_VCE].enabled &&
1934            (feature_mask & FEATURE_DPM_VCE_MASK)) {
1935                 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
1936 
1937                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1938                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1939                                         (PPCLK_ECLK << 16) | (max_freq & 0xffff))),
1940                                         "Failed to set soft max eclk!",
1941                                         return ret);
1942         }
1943 
1944         if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1945            (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1946                 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
1947 
1948                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1949                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1950                                         (PPCLK_SOCCLK << 16) | (max_freq & 0xffff))),
1951                                         "Failed to set soft max socclk!",
1952                                         return ret);
1953         }
1954 
1955         if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1956            (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1957                 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
1958 
1959                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1960                                         hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1961                                         (PPCLK_FCLK << 16) | (max_freq & 0xffff))),
1962                                         "Failed to set soft max fclk!",
1963                                         return ret);
1964         }
1965 
1966         return ret;
1967 }
1968 
1969 int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
1970 {
1971         struct vega20_hwmgr *data =
1972                         (struct vega20_hwmgr *)(hwmgr->backend);
1973         int ret = 0;
1974 
1975         if (data->smu_features[GNLD_DPM_VCE].supported) {
1976                 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) {
1977                         if (enable)
1978                                 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n");
1979                         else
1980                                 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n");
1981                 }
1982 
1983                 ret = vega20_enable_smc_features(hwmgr,
1984                                 enable,
1985                                 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap);
1986                 PP_ASSERT_WITH_CODE(!ret,
1987                                 "Attempt to Enable/Disable DPM VCE Failed!",
1988                                 return ret);
1989                 data->smu_features[GNLD_DPM_VCE].enabled = enable;
1990         }
1991 
1992         return 0;
1993 }
1994 
1995 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr,
1996                 uint32_t *clock,
1997                 PPCLK_e clock_select,
1998                 bool max)
1999 {
2000         int ret;
2001         *clock = 0;
2002 
2003         if (max) {
2004                 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2005                                 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16))) == 0,
2006                                 "[GetClockRanges] Failed to get max clock from SMC!",
2007                                 return ret);
2008                 *clock = smum_get_argument(hwmgr);
2009         } else {
2010                 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2011                                 PPSMC_MSG_GetMinDpmFreq,
2012                                 (clock_select << 16))) == 0,
2013                                 "[GetClockRanges] Failed to get min clock from SMC!",
2014                                 return ret);
2015                 *clock = smum_get_argument(hwmgr);
2016         }
2017 
2018         return 0;
2019 }
2020 
2021 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
2022 {
2023         struct vega20_hwmgr *data =
2024                         (struct vega20_hwmgr *)(hwmgr->backend);
2025         uint32_t gfx_clk;
2026         int ret = 0;
2027 
2028         PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled,
2029                         "[GetSclks]: gfxclk dpm not enabled!\n",
2030                         return -EPERM);
2031 
2032         if (low) {
2033                 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false);
2034                 PP_ASSERT_WITH_CODE(!ret,
2035                         "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
2036                         return ret);
2037         } else {
2038                 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true);
2039                 PP_ASSERT_WITH_CODE(!ret,
2040                         "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
2041                         return ret);
2042         }
2043 
2044         return (gfx_clk * 100);
2045 }
2046 
2047 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
2048 {
2049         struct vega20_hwmgr *data =
2050                         (struct vega20_hwmgr *)(hwmgr->backend);
2051         uint32_t mem_clk;
2052         int ret = 0;
2053 
2054         PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled,
2055                         "[MemMclks]: memclk dpm not enabled!\n",
2056                         return -EPERM);
2057 
2058         if (low) {
2059                 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false);
2060                 PP_ASSERT_WITH_CODE(!ret,
2061                         "[GetMclks]: fail to get min PPCLK_UCLK\n",
2062                         return ret);
2063         } else {
2064                 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true);
2065                 PP_ASSERT_WITH_CODE(!ret,
2066                         "[GetMclks]: fail to get max PPCLK_UCLK\n",
2067                         return ret);
2068         }
2069 
2070         return (mem_clk * 100);
2071 }
2072 
2073 static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table)
2074 {
2075         struct vega20_hwmgr *data =
2076                         (struct vega20_hwmgr *)(hwmgr->backend);
2077         int ret = 0;
2078 
2079         if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) {
2080                 ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table,
2081                                 TABLE_SMU_METRICS, true);
2082                 if (ret) {
2083                         pr_info("Failed to export SMU metrics table!\n");
2084                         return ret;
2085                 }
2086                 memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t));
2087                 data->metrics_time = jiffies;
2088         } else
2089                 memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t));
2090 
2091         return ret;
2092 }
2093 
2094 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
2095                 uint32_t *query)
2096 {
2097         int ret = 0;
2098         SmuMetrics_t metrics_table;
2099 
2100         ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2101         if (ret)
2102                 return ret;
2103 
2104         /* For the 40.46 release, they changed the value name */
2105         if (hwmgr->smu_version == 0x282e00)
2106                 *query = metrics_table.AverageSocketPower << 8;
2107         else
2108                 *query = metrics_table.CurrSocketPower << 8;
2109 
2110         return ret;
2111 }
2112 
2113 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr,
2114                 PPCLK_e clk_id, uint32_t *clk_freq)
2115 {
2116         int ret = 0;
2117 
2118         *clk_freq = 0;
2119 
2120         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2121                         PPSMC_MSG_GetDpmClockFreq, (clk_id << 16))) == 0,
2122                         "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!",
2123                         return ret);
2124         *clk_freq = smum_get_argument(hwmgr);
2125 
2126         *clk_freq = *clk_freq * 100;
2127 
2128         return 0;
2129 }
2130 
2131 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr,
2132                 int idx,
2133                 uint32_t *activity_percent)
2134 {
2135         int ret = 0;
2136         SmuMetrics_t metrics_table;
2137 
2138         ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2139         if (ret)
2140                 return ret;
2141 
2142         switch (idx) {
2143         case AMDGPU_PP_SENSOR_GPU_LOAD:
2144                 *activity_percent = metrics_table.AverageGfxActivity;
2145                 break;
2146         case AMDGPU_PP_SENSOR_MEM_LOAD:
2147                 *activity_percent = metrics_table.AverageUclkActivity;
2148                 break;
2149         default:
2150                 pr_err("Invalid index for retrieving clock activity\n");
2151                 return -EINVAL;
2152         }
2153 
2154         return ret;
2155 }
2156 
2157 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
2158                               void *value, int *size)
2159 {
2160         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2161         struct amdgpu_device *adev = hwmgr->adev;
2162         SmuMetrics_t metrics_table;
2163         uint32_t val_vid;
2164         int ret = 0;
2165 
2166         switch (idx) {
2167         case AMDGPU_PP_SENSOR_GFX_SCLK:
2168                 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2169                 if (ret)
2170                         return ret;
2171 
2172                 *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100;
2173                 *size = 4;
2174                 break;
2175         case AMDGPU_PP_SENSOR_GFX_MCLK:
2176                 ret = vega20_get_current_clk_freq(hwmgr,
2177                                 PPCLK_UCLK,
2178                                 (uint32_t *)value);
2179                 if (!ret)
2180                         *size = 4;
2181                 break;
2182         case AMDGPU_PP_SENSOR_GPU_LOAD:
2183         case AMDGPU_PP_SENSOR_MEM_LOAD:
2184                 ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value);
2185                 if (!ret)
2186                         *size = 4;
2187                 break;
2188         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2189                 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr);
2190                 *size = 4;
2191                 break;
2192         case AMDGPU_PP_SENSOR_EDGE_TEMP:
2193                 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2194                 if (ret)
2195                         return ret;
2196 
2197                 *((uint32_t *)value) = metrics_table.TemperatureEdge *
2198                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2199                 *size = 4;
2200                 break;
2201         case AMDGPU_PP_SENSOR_MEM_TEMP:
2202                 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2203                 if (ret)
2204                         return ret;
2205 
2206                 *((uint32_t *)value) = metrics_table.TemperatureHBM *
2207                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2208                 *size = 4;
2209                 break;
2210         case AMDGPU_PP_SENSOR_UVD_POWER:
2211                 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
2212                 *size = 4;
2213                 break;
2214         case AMDGPU_PP_SENSOR_VCE_POWER:
2215                 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
2216                 *size = 4;
2217                 break;
2218         case AMDGPU_PP_SENSOR_GPU_POWER:
2219                 *size = 16;
2220                 ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value);
2221                 break;
2222         case AMDGPU_PP_SENSOR_VDDGFX:
2223                 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
2224                         SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
2225                         SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
2226                 *((uint32_t *)value) =
2227                         (uint32_t)convert_to_vddc((uint8_t)val_vid);
2228                 break;
2229         case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
2230                 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value);
2231                 if (!ret)
2232                         *size = 8;
2233                 break;
2234         default:
2235                 ret = -EINVAL;
2236                 break;
2237         }
2238         return ret;
2239 }
2240 
2241 int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
2242                 struct pp_display_clock_request *clock_req)
2243 {
2244         int result = 0;
2245         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2246         enum amd_pp_clock_type clk_type = clock_req->clock_type;
2247         uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
2248         PPCLK_e clk_select = 0;
2249         uint32_t clk_request = 0;
2250 
2251         if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
2252                 switch (clk_type) {
2253                 case amd_pp_dcef_clock:
2254                         clk_select = PPCLK_DCEFCLK;
2255                         break;
2256                 case amd_pp_disp_clock:
2257                         clk_select = PPCLK_DISPCLK;
2258                         break;
2259                 case amd_pp_pixel_clock:
2260                         clk_select = PPCLK_PIXCLK;
2261                         break;
2262                 case amd_pp_phy_clock:
2263                         clk_select = PPCLK_PHYCLK;
2264                         break;
2265                 default:
2266                         pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
2267                         result = -EINVAL;
2268                         break;
2269                 }
2270 
2271                 if (!result) {
2272                         clk_request = (clk_select << 16) | clk_freq;
2273                         result = smum_send_msg_to_smc_with_parameter(hwmgr,
2274                                         PPSMC_MSG_SetHardMinByFreq,
2275                                         clk_request);
2276                 }
2277         }
2278 
2279         return result;
2280 }
2281 
2282 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
2283                                 PHM_PerformanceLevelDesignation designation, uint32_t index,
2284                                 PHM_PerformanceLevel *level)
2285 {
2286         return 0;
2287 }
2288 
2289 static int vega20_notify_smc_display_config_after_ps_adjustment(
2290                 struct pp_hwmgr *hwmgr)
2291 {
2292         struct vega20_hwmgr *data =
2293                         (struct vega20_hwmgr *)(hwmgr->backend);
2294         struct vega20_single_dpm_table *dpm_table =
2295                         &data->dpm_table.mem_table;
2296         struct PP_Clocks min_clocks = {0};
2297         struct pp_display_clock_request clock_req;
2298         int ret = 0;
2299 
2300         min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
2301         min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
2302         min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
2303 
2304         if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
2305                 clock_req.clock_type = amd_pp_dcef_clock;
2306                 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
2307                 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) {
2308                         if (data->smu_features[GNLD_DS_DCEFCLK].supported)
2309                                 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(
2310                                         hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
2311                                         min_clocks.dcefClockInSR / 100)) == 0,
2312                                         "Attempt to set divider for DCEFCLK Failed!",
2313                                         return ret);
2314                 } else {
2315                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2316                 }
2317         }
2318 
2319         if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2320                 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100;
2321                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2322                                 PPSMC_MSG_SetHardMinByFreq,
2323                                 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
2324                                 "[SetHardMinFreq] Set hard min uclk failed!",
2325                                 return ret);
2326         }
2327 
2328         return 0;
2329 }
2330 
2331 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
2332 {
2333         struct vega20_hwmgr *data =
2334                         (struct vega20_hwmgr *)(hwmgr->backend);
2335         uint32_t soft_level;
2336         int ret = 0;
2337 
2338         soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2339 
2340         data->dpm_table.gfx_table.dpm_state.soft_min_level =
2341                 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2342                 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2343 
2344         soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2345 
2346         data->dpm_table.mem_table.dpm_state.soft_min_level =
2347                 data->dpm_table.mem_table.dpm_state.soft_max_level =
2348                 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2349 
2350         soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
2351 
2352         data->dpm_table.soc_table.dpm_state.soft_min_level =
2353                 data->dpm_table.soc_table.dpm_state.soft_max_level =
2354                 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2355 
2356         ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2357                                                  FEATURE_DPM_UCLK_MASK |
2358                                                  FEATURE_DPM_SOCCLK_MASK);
2359         PP_ASSERT_WITH_CODE(!ret,
2360                         "Failed to upload boot level to highest!",
2361                         return ret);
2362 
2363         ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2364                                                  FEATURE_DPM_UCLK_MASK |
2365                                                  FEATURE_DPM_SOCCLK_MASK);
2366         PP_ASSERT_WITH_CODE(!ret,
2367                         "Failed to upload dpm max level to highest!",
2368                         return ret);
2369 
2370         return 0;
2371 }
2372 
2373 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
2374 {
2375         struct vega20_hwmgr *data =
2376                         (struct vega20_hwmgr *)(hwmgr->backend);
2377         uint32_t soft_level;
2378         int ret = 0;
2379 
2380         soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2381 
2382         data->dpm_table.gfx_table.dpm_state.soft_min_level =
2383                 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2384                 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2385 
2386         soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2387 
2388         data->dpm_table.mem_table.dpm_state.soft_min_level =
2389                 data->dpm_table.mem_table.dpm_state.soft_max_level =
2390                 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2391 
2392         soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
2393 
2394         data->dpm_table.soc_table.dpm_state.soft_min_level =
2395                 data->dpm_table.soc_table.dpm_state.soft_max_level =
2396                 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2397 
2398         ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2399                                                  FEATURE_DPM_UCLK_MASK |
2400                                                  FEATURE_DPM_SOCCLK_MASK);
2401         PP_ASSERT_WITH_CODE(!ret,
2402                         "Failed to upload boot level to highest!",
2403                         return ret);
2404 
2405         ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2406                                                  FEATURE_DPM_UCLK_MASK |
2407                                                  FEATURE_DPM_SOCCLK_MASK);
2408         PP_ASSERT_WITH_CODE(!ret,
2409                         "Failed to upload dpm max level to highest!",
2410                         return ret);
2411 
2412         return 0;
2413 
2414 }
2415 
2416 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
2417 {
2418         struct vega20_hwmgr *data =
2419                         (struct vega20_hwmgr *)(hwmgr->backend);
2420         uint32_t soft_min_level, soft_max_level;
2421         int ret = 0;
2422 
2423         /* gfxclk soft min/max settings */
2424         soft_min_level =
2425                 vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2426         soft_max_level =
2427                 vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2428 
2429         data->dpm_table.gfx_table.dpm_state.soft_min_level =
2430                 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2431         data->dpm_table.gfx_table.dpm_state.soft_max_level =
2432                 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2433 
2434         /* uclk soft min/max settings */
2435         soft_min_level =
2436                 vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2437         soft_max_level =
2438                 vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2439 
2440         data->dpm_table.mem_table.dpm_state.soft_min_level =
2441                 data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2442         data->dpm_table.mem_table.dpm_state.soft_max_level =
2443                 data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2444 
2445         /* socclk soft min/max settings */
2446         soft_min_level =
2447                 vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
2448         soft_max_level =
2449                 vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
2450 
2451         data->dpm_table.soc_table.dpm_state.soft_min_level =
2452                 data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
2453         data->dpm_table.soc_table.dpm_state.soft_max_level =
2454                 data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
2455 
2456         ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2457                                                  FEATURE_DPM_UCLK_MASK |
2458                                                  FEATURE_DPM_SOCCLK_MASK);
2459         PP_ASSERT_WITH_CODE(!ret,
2460                         "Failed to upload DPM Bootup Levels!",
2461                         return ret);
2462 
2463         ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
2464                                                  FEATURE_DPM_UCLK_MASK |
2465                                                  FEATURE_DPM_SOCCLK_MASK);
2466         PP_ASSERT_WITH_CODE(!ret,
2467                         "Failed to upload DPM Max Levels!",
2468                         return ret);
2469 
2470         return 0;
2471 }
2472 
2473 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
2474                                 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
2475 {
2476         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2477         struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table);
2478         struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table);
2479         struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table);
2480 
2481         *sclk_mask = 0;
2482         *mclk_mask = 0;
2483         *soc_mask  = 0;
2484 
2485         if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
2486             mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
2487             soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
2488                 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
2489                 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2490                 *soc_mask  = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2491         }
2492 
2493         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2494                 *sclk_mask = 0;
2495         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2496                 *mclk_mask = 0;
2497         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2498                 *sclk_mask = gfx_dpm_table->count - 1;
2499                 *mclk_mask = mem_dpm_table->count - 1;
2500                 *soc_mask  = soc_dpm_table->count - 1;
2501         }
2502 
2503         return 0;
2504 }
2505 
2506 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
2507                 enum pp_clock_type type, uint32_t mask)
2508 {
2509         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2510         uint32_t soft_min_level, soft_max_level, hard_min_level;
2511         int ret = 0;
2512 
2513         switch (type) {
2514         case PP_SCLK:
2515                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2516                 soft_max_level = mask ? (fls(mask) - 1) : 0;
2517 
2518                 if (soft_max_level >= data->dpm_table.gfx_table.count) {
2519                         pr_err("Clock level specified %d is over max allowed %d\n",
2520                                         soft_max_level,
2521                                         data->dpm_table.gfx_table.count - 1);
2522                         return -EINVAL;
2523                 }
2524 
2525                 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2526                         data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2527                 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2528                         data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2529 
2530                 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2531                 PP_ASSERT_WITH_CODE(!ret,
2532                         "Failed to upload boot level to lowest!",
2533                         return ret);
2534 
2535                 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2536                 PP_ASSERT_WITH_CODE(!ret,
2537                         "Failed to upload dpm max level to highest!",
2538                         return ret);
2539                 break;
2540 
2541         case PP_MCLK:
2542                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2543                 soft_max_level = mask ? (fls(mask) - 1) : 0;
2544 
2545                 if (soft_max_level >= data->dpm_table.mem_table.count) {
2546                         pr_err("Clock level specified %d is over max allowed %d\n",
2547                                         soft_max_level,
2548                                         data->dpm_table.mem_table.count - 1);
2549                         return -EINVAL;
2550                 }
2551 
2552                 data->dpm_table.mem_table.dpm_state.soft_min_level =
2553                         data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2554                 data->dpm_table.mem_table.dpm_state.soft_max_level =
2555                         data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2556 
2557                 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2558                 PP_ASSERT_WITH_CODE(!ret,
2559                         "Failed to upload boot level to lowest!",
2560                         return ret);
2561 
2562                 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2563                 PP_ASSERT_WITH_CODE(!ret,
2564                         "Failed to upload dpm max level to highest!",
2565                         return ret);
2566 
2567                 break;
2568 
2569         case PP_SOCCLK:
2570                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2571                 soft_max_level = mask ? (fls(mask) - 1) : 0;
2572 
2573                 if (soft_max_level >= data->dpm_table.soc_table.count) {
2574                         pr_err("Clock level specified %d is over max allowed %d\n",
2575                                         soft_max_level,
2576                                         data->dpm_table.soc_table.count - 1);
2577                         return -EINVAL;
2578                 }
2579 
2580                 data->dpm_table.soc_table.dpm_state.soft_min_level =
2581                         data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
2582                 data->dpm_table.soc_table.dpm_state.soft_max_level =
2583                         data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
2584 
2585                 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2586                 PP_ASSERT_WITH_CODE(!ret,
2587                         "Failed to upload boot level to lowest!",
2588                         return ret);
2589 
2590                 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2591                 PP_ASSERT_WITH_CODE(!ret,
2592                         "Failed to upload dpm max level to highest!",
2593                         return ret);
2594 
2595                 break;
2596 
2597         case PP_FCLK:
2598                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2599                 soft_max_level = mask ? (fls(mask) - 1) : 0;
2600 
2601                 if (soft_max_level >= data->dpm_table.fclk_table.count) {
2602                         pr_err("Clock level specified %d is over max allowed %d\n",
2603                                         soft_max_level,
2604                                         data->dpm_table.fclk_table.count - 1);
2605                         return -EINVAL;
2606                 }
2607 
2608                 data->dpm_table.fclk_table.dpm_state.soft_min_level =
2609                         data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
2610                 data->dpm_table.fclk_table.dpm_state.soft_max_level =
2611                         data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
2612 
2613                 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2614                 PP_ASSERT_WITH_CODE(!ret,
2615                         "Failed to upload boot level to lowest!",
2616                         return ret);
2617 
2618                 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2619                 PP_ASSERT_WITH_CODE(!ret,
2620                         "Failed to upload dpm max level to highest!",
2621                         return ret);
2622 
2623                 break;
2624 
2625         case PP_DCEFCLK:
2626                 hard_min_level = mask ? (ffs(mask) - 1) : 0;
2627 
2628                 if (hard_min_level >= data->dpm_table.dcef_table.count) {
2629                         pr_err("Clock level specified %d is over max allowed %d\n",
2630                                         hard_min_level,
2631                                         data->dpm_table.dcef_table.count - 1);
2632                         return -EINVAL;
2633                 }
2634 
2635                 data->dpm_table.dcef_table.dpm_state.hard_min_level =
2636                         data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
2637 
2638                 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
2639                 PP_ASSERT_WITH_CODE(!ret,
2640                         "Failed to upload boot level to lowest!",
2641                         return ret);
2642 
2643                 //TODO: Setting DCEFCLK max dpm level is not supported
2644 
2645                 break;
2646 
2647         case PP_PCIE:
2648                 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2649                 soft_max_level = mask ? (fls(mask) - 1) : 0;
2650                 if (soft_min_level >= NUM_LINK_LEVELS ||
2651                     soft_max_level >= NUM_LINK_LEVELS)
2652                         return -EINVAL;
2653 
2654                 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2655                         PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level);
2656                 PP_ASSERT_WITH_CODE(!ret,
2657                         "Failed to set min link dpm level!",
2658                         return ret);
2659 
2660                 break;
2661 
2662         default:
2663                 break;
2664         }
2665 
2666         return 0;
2667 }
2668 
2669 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
2670                                 enum amd_dpm_forced_level level)
2671 {
2672         int ret = 0;
2673         uint32_t sclk_mask, mclk_mask, soc_mask;
2674 
2675         switch (level) {
2676         case AMD_DPM_FORCED_LEVEL_HIGH:
2677                 ret = vega20_force_dpm_highest(hwmgr);
2678                 break;
2679 
2680         case AMD_DPM_FORCED_LEVEL_LOW:
2681                 ret = vega20_force_dpm_lowest(hwmgr);
2682                 break;
2683 
2684         case AMD_DPM_FORCED_LEVEL_AUTO:
2685                 ret = vega20_unforce_dpm_levels(hwmgr);
2686                 break;
2687 
2688         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
2689         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
2690         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
2691         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
2692                 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
2693                 if (ret)
2694                         return ret;
2695                 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
2696                 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
2697                 vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask);
2698                 break;
2699 
2700         case AMD_DPM_FORCED_LEVEL_MANUAL:
2701         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
2702         default:
2703                 break;
2704         }
2705 
2706         return ret;
2707 }
2708 
2709 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr)
2710 {
2711         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2712 
2713         if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
2714                 return AMD_FAN_CTRL_MANUAL;
2715         else
2716                 return AMD_FAN_CTRL_AUTO;
2717 }
2718 
2719 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
2720 {
2721         switch (mode) {
2722         case AMD_FAN_CTRL_NONE:
2723                 vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
2724                 break;
2725         case AMD_FAN_CTRL_MANUAL:
2726                 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2727                         vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
2728                 break;
2729         case AMD_FAN_CTRL_AUTO:
2730                 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2731                         vega20_fan_ctrl_start_smc_fan_control(hwmgr);
2732                 break;
2733         default:
2734                 break;
2735         }
2736 }
2737 
2738 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr,
2739                 struct amd_pp_simple_clock_info *info)
2740 {
2741 #if 0
2742         struct phm_ppt_v2_information *table_info =
2743                         (struct phm_ppt_v2_information *)hwmgr->pptable;
2744         struct phm_clock_and_voltage_limits *max_limits =
2745                         &table_info->max_clock_voltage_on_ac;
2746 
2747         info->engine_max_clock = max_limits->sclk;
2748         info->memory_max_clock = max_limits->mclk;
2749 #endif
2750         return 0;
2751 }
2752 
2753 
2754 static int vega20_get_sclks(struct pp_hwmgr *hwmgr,
2755                 struct pp_clock_levels_with_latency *clocks)
2756 {
2757         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2758         struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2759         int i, count;
2760 
2761         if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
2762                 return -1;
2763 
2764         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2765         clocks->num_levels = count;
2766 
2767         for (i = 0; i < count; i++) {
2768                 clocks->data[i].clocks_in_khz =
2769                         dpm_table->dpm_levels[i].value * 1000;
2770                 clocks->data[i].latency_in_us = 0;
2771         }
2772 
2773         return 0;
2774 }
2775 
2776 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr,
2777                 uint32_t clock)
2778 {
2779         return 25;
2780 }
2781 
2782 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr,
2783                 struct pp_clock_levels_with_latency *clocks)
2784 {
2785         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2786         struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table);
2787         int i, count;
2788 
2789         if (!data->smu_features[GNLD_DPM_UCLK].enabled)
2790                 return -1;
2791 
2792         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2793         clocks->num_levels = data->mclk_latency_table.count = count;
2794 
2795         for (i = 0; i < count; i++) {
2796                 clocks->data[i].clocks_in_khz =
2797                         data->mclk_latency_table.entries[i].frequency =
2798                         dpm_table->dpm_levels[i].value * 1000;
2799                 clocks->data[i].latency_in_us =
2800                         data->mclk_latency_table.entries[i].latency =
2801                         vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
2802         }
2803 
2804         return 0;
2805 }
2806 
2807 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr,
2808                 struct pp_clock_levels_with_latency *clocks)
2809 {
2810         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2811         struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table);
2812         int i, count;
2813 
2814         if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled)
2815                 return -1;
2816 
2817         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2818         clocks->num_levels = count;
2819 
2820         for (i = 0; i < count; i++) {
2821                 clocks->data[i].clocks_in_khz =
2822                         dpm_table->dpm_levels[i].value * 1000;
2823                 clocks->data[i].latency_in_us = 0;
2824         }
2825 
2826         return 0;
2827 }
2828 
2829 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr,
2830                 struct pp_clock_levels_with_latency *clocks)
2831 {
2832         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2833         struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table);
2834         int i, count;
2835 
2836         if (!data->smu_features[GNLD_DPM_SOCCLK].enabled)
2837                 return -1;
2838 
2839         count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2840         clocks->num_levels = count;
2841 
2842         for (i = 0; i < count; i++) {
2843                 clocks->data[i].clocks_in_khz =
2844                         dpm_table->dpm_levels[i].value * 1000;
2845                 clocks->data[i].latency_in_us = 0;
2846         }
2847 
2848         return 0;
2849 
2850 }
2851 
2852 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
2853                 enum amd_pp_clock_type type,
2854                 struct pp_clock_levels_with_latency *clocks)
2855 {
2856         int ret;
2857 
2858         switch (type) {
2859         case amd_pp_sys_clock:
2860                 ret = vega20_get_sclks(hwmgr, clocks);
2861                 break;
2862         case amd_pp_mem_clock:
2863                 ret = vega20_get_memclocks(hwmgr, clocks);
2864                 break;
2865         case amd_pp_dcef_clock:
2866                 ret = vega20_get_dcefclocks(hwmgr, clocks);
2867                 break;
2868         case amd_pp_soc_clock:
2869                 ret = vega20_get_socclocks(hwmgr, clocks);
2870                 break;
2871         default:
2872                 return -EINVAL;
2873         }
2874 
2875         return ret;
2876 }
2877 
2878 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
2879                 enum amd_pp_clock_type type,
2880                 struct pp_clock_levels_with_voltage *clocks)
2881 {
2882         clocks->num_levels = 0;
2883 
2884         return 0;
2885 }
2886 
2887 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
2888                                                    void *clock_ranges)
2889 {
2890         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2891         Watermarks_t *table = &(data->smc_state_table.water_marks_table);
2892         struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
2893 
2894         if (!data->registry_data.disable_water_mark &&
2895             data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2896             data->smu_features[GNLD_DPM_SOCCLK].supported) {
2897                 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
2898                 data->water_marks_bitmap |= WaterMarksExist;
2899                 data->water_marks_bitmap &= ~WaterMarksLoaded;
2900         }
2901 
2902         return 0;
2903 }
2904 
2905 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2906                                         enum PP_OD_DPM_TABLE_COMMAND type,
2907                                         long *input, uint32_t size)
2908 {
2909         struct vega20_hwmgr *data =
2910                         (struct vega20_hwmgr *)(hwmgr->backend);
2911         struct vega20_od8_single_setting *od8_settings =
2912                         data->od8_settings.od8_settings_array;
2913         OverDriveTable_t *od_table =
2914                         &(data->smc_state_table.overdrive_table);
2915         int32_t input_index, input_clk, input_vol, i;
2916         int od8_id;
2917         int ret;
2918 
2919         PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
2920                                 return -EINVAL);
2921 
2922         switch (type) {
2923         case PP_OD_EDIT_SCLK_VDDC_TABLE:
2924                 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2925                       od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2926                         pr_info("Sclk min/max frequency overdrive not supported\n");
2927                         return -EOPNOTSUPP;
2928                 }
2929 
2930                 for (i = 0; i < size; i += 2) {
2931                         if (i + 2 > size) {
2932                                 pr_info("invalid number of input parameters %d\n",
2933                                         size);
2934                                 return -EINVAL;
2935                         }
2936 
2937                         input_index = input[i];
2938                         input_clk = input[i + 1];
2939 
2940                         if (input_index != 0 && input_index != 1) {
2941                                 pr_info("Invalid index %d\n", input_index);
2942                                 pr_info("Support min/max sclk frequency setting only which index by 0/1\n");
2943                                 return -EINVAL;
2944                         }
2945 
2946                         if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2947                             input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2948                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2949                                         input_clk,
2950                                         od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2951                                         od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2952                                 return -EINVAL;
2953                         }
2954 
2955                         if ((input_index == 0 && od_table->GfxclkFmin != input_clk) ||
2956                             (input_index == 1 && od_table->GfxclkFmax != input_clk))
2957                                 data->gfxclk_overdrive = true;
2958 
2959                         if (input_index == 0)
2960                                 od_table->GfxclkFmin = input_clk;
2961                         else
2962                                 od_table->GfxclkFmax = input_clk;
2963                 }
2964 
2965                 break;
2966 
2967         case PP_OD_EDIT_MCLK_VDDC_TABLE:
2968                 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2969                         pr_info("Mclk max frequency overdrive not supported\n");
2970                         return -EOPNOTSUPP;
2971                 }
2972 
2973                 for (i = 0; i < size; i += 2) {
2974                         if (i + 2 > size) {
2975                                 pr_info("invalid number of input parameters %d\n",
2976                                         size);
2977                                 return -EINVAL;
2978                         }
2979 
2980                         input_index = input[i];
2981                         input_clk = input[i + 1];
2982 
2983                         if (input_index != 1) {
2984                                 pr_info("Invalid index %d\n", input_index);
2985                                 pr_info("Support max Mclk frequency setting only which index by 1\n");
2986                                 return -EINVAL;
2987                         }
2988 
2989                         if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
2990                             input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) {
2991                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2992                                         input_clk,
2993                                         od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
2994                                         od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2995                                 return -EINVAL;
2996                         }
2997 
2998                         if (input_index == 1 && od_table->UclkFmax != input_clk)
2999                                 data->memclk_overdrive = true;
3000 
3001                         od_table->UclkFmax = input_clk;
3002                 }
3003 
3004                 break;
3005 
3006         case PP_OD_EDIT_VDDC_CURVE:
3007                 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3008                     od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3009                     od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3010                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3011                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3012                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
3013                         pr_info("Voltage curve calibrate not supported\n");
3014                         return -EOPNOTSUPP;
3015                 }
3016 
3017                 for (i = 0; i < size; i += 3) {
3018                         if (i + 3 > size) {
3019                                 pr_info("invalid number of input parameters %d\n",
3020                                         size);
3021                                 return -EINVAL;
3022                         }
3023 
3024                         input_index = input[i];
3025                         input_clk = input[i + 1];
3026                         input_vol = input[i + 2];
3027 
3028                         if (input_index > 2) {
3029                                 pr_info("Setting for point %d is not supported\n",
3030                                                 input_index + 1);
3031                                 pr_info("Three supported points index by 0, 1, 2\n");
3032                                 return -EINVAL;
3033                         }
3034 
3035                         od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
3036                         if (input_clk < od8_settings[od8_id].min_value ||
3037                             input_clk > od8_settings[od8_id].max_value) {
3038                                 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
3039                                         input_clk,
3040                                         od8_settings[od8_id].min_value,
3041                                         od8_settings[od8_id].max_value);
3042                                 return -EINVAL;
3043                         }
3044 
3045                         od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
3046                         if (input_vol < od8_settings[od8_id].min_value ||
3047                             input_vol > od8_settings[od8_id].max_value) {
3048                                 pr_info("clock voltage %d is not within allowed range [%d - %d]\n",
3049                                         input_vol,
3050                                         od8_settings[od8_id].min_value,
3051                                         od8_settings[od8_id].max_value);
3052                                 return -EINVAL;
3053                         }
3054 
3055                         switch (input_index) {
3056                         case 0:
3057                                 od_table->GfxclkFreq1 = input_clk;
3058                                 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
3059                                 break;
3060                         case 1:
3061                                 od_table->GfxclkFreq2 = input_clk;
3062                                 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
3063                                 break;
3064                         case 2:
3065                                 od_table->GfxclkFreq3 = input_clk;
3066                                 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
3067                                 break;
3068                         }
3069                 }
3070                 break;
3071 
3072         case PP_OD_RESTORE_DEFAULT_TABLE:
3073                 data->gfxclk_overdrive = false;
3074                 data->memclk_overdrive = false;
3075 
3076                 ret = smum_smc_table_manager(hwmgr,
3077                                              (uint8_t *)od_table,
3078                                              TABLE_OVERDRIVE, true);
3079                 PP_ASSERT_WITH_CODE(!ret,
3080                                 "Failed to export overdrive table!",
3081                                 return ret);
3082                 break;
3083 
3084         case PP_OD_COMMIT_DPM_TABLE:
3085                 ret = smum_smc_table_manager(hwmgr,
3086                                              (uint8_t *)od_table,
3087                                              TABLE_OVERDRIVE, false);
3088                 PP_ASSERT_WITH_CODE(!ret,
3089                                 "Failed to import overdrive table!",
3090                                 return ret);
3091 
3092                 /* retrieve updated gfxclk table */
3093                 if (data->gfxclk_overdrive) {
3094                         data->gfxclk_overdrive = false;
3095 
3096                         ret = vega20_setup_gfxclk_dpm_table(hwmgr);
3097                         if (ret)
3098                                 return ret;
3099                 }
3100 
3101                 /* retrieve updated memclk table */
3102                 if (data->memclk_overdrive) {
3103                         data->memclk_overdrive = false;
3104 
3105                         ret = vega20_setup_memclk_dpm_table(hwmgr);
3106                         if (ret)
3107                                 return ret;
3108                 }
3109                 break;
3110 
3111         default:
3112                 return -EINVAL;
3113         }
3114 
3115         return 0;
3116 }
3117 
3118 static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr,
3119                                 enum pp_mp1_state mp1_state)
3120 {
3121         uint16_t msg;
3122         int ret;
3123 
3124         switch (mp1_state) {
3125         case PP_MP1_STATE_SHUTDOWN:
3126                 msg = PPSMC_MSG_PrepareMp1ForShutdown;
3127                 break;
3128         case PP_MP1_STATE_UNLOAD:
3129                 msg = PPSMC_MSG_PrepareMp1ForUnload;
3130                 break;
3131         case PP_MP1_STATE_RESET:
3132                 msg = PPSMC_MSG_PrepareMp1ForReset;
3133                 break;
3134         case PP_MP1_STATE_NONE:
3135         default:
3136                 return 0;
3137         }
3138 
3139         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg)) == 0,
3140                             "[PrepareMp1] Failed!",
3141                             return ret);
3142 
3143         return 0;
3144 }
3145 
3146 static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
3147 {
3148         static const char *ppfeature_name[] = {
3149                                 "DPM_PREFETCHER",
3150                                 "GFXCLK_DPM",
3151                                 "UCLK_DPM",
3152                                 "SOCCLK_DPM",
3153                                 "UVD_DPM",
3154                                 "VCE_DPM",
3155                                 "ULV",
3156                                 "MP0CLK_DPM",
3157                                 "LINK_DPM",
3158                                 "DCEFCLK_DPM",
3159                                 "GFXCLK_DS",
3160                                 "SOCCLK_DS",
3161                                 "LCLK_DS",
3162                                 "PPT",
3163                                 "TDC",
3164                                 "THERMAL",
3165                                 "GFX_PER_CU_CG",
3166                                 "RM",
3167                                 "DCEFCLK_DS",
3168                                 "ACDC",
3169                                 "VR0HOT",
3170                                 "VR1HOT",
3171                                 "FW_CTF",
3172                                 "LED_DISPLAY",
3173                                 "FAN_CONTROL",
3174                                 "GFX_EDC",
3175                                 "GFXOFF",
3176                                 "CG",
3177                                 "FCLK_DPM",
3178                                 "FCLK_DS",
3179                                 "MP1CLK_DS",
3180                                 "MP0CLK_DS",
3181                                 "XGMI",
3182                                 "ECC"};
3183         static const char *output_title[] = {
3184                                 "FEATURES",
3185                                 "BITMASK",
3186                                 "ENABLEMENT"};
3187         uint64_t features_enabled;
3188         int i;
3189         int ret = 0;
3190         int size = 0;
3191 
3192         ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3193         PP_ASSERT_WITH_CODE(!ret,
3194                         "[EnableAllSmuFeatures] Failed to get enabled smc features!",
3195                         return ret);
3196 
3197         size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
3198         size += sprintf(buf + size, "%-19s %-22s %s\n",
3199                                 output_title[0],
3200                                 output_title[1],
3201                                 output_title[2]);
3202         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3203                 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
3204                                         ppfeature_name[i],
3205                                         1ULL << i,
3206                                         (features_enabled & (1ULL << i)) ? "Y" : "N");
3207         }
3208 
3209         return size;
3210 }
3211 
3212 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
3213 {
3214         uint64_t features_enabled;
3215         uint64_t features_to_enable;
3216         uint64_t features_to_disable;
3217         int ret = 0;
3218 
3219         if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
3220                 return -EINVAL;
3221 
3222         ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3223         if (ret)
3224                 return ret;
3225 
3226         features_to_disable =
3227                 features_enabled & ~new_ppfeature_masks;
3228         features_to_enable =
3229                 ~features_enabled & new_ppfeature_masks;
3230 
3231         pr_debug("features_to_disable 0x%llx\n", features_to_disable);
3232         pr_debug("features_to_enable 0x%llx\n", features_to_enable);
3233 
3234         if (features_to_disable) {
3235                 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
3236                 if (ret)
3237                         return ret;
3238         }
3239 
3240         if (features_to_enable) {
3241                 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
3242                 if (ret)
3243                         return ret;
3244         }
3245 
3246         return 0;
3247 }
3248 
3249 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
3250                 enum pp_clock_type type, char *buf)
3251 {
3252         struct vega20_hwmgr *data =
3253                         (struct vega20_hwmgr *)(hwmgr->backend);
3254         struct vega20_od8_single_setting *od8_settings =
3255                         data->od8_settings.od8_settings_array;
3256         OverDriveTable_t *od_table =
3257                         &(data->smc_state_table.overdrive_table);
3258         struct phm_ppt_v3_information *pptable_information =
3259                 (struct phm_ppt_v3_information *)hwmgr->pptable;
3260         PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
3261         struct amdgpu_device *adev = hwmgr->adev;
3262         struct pp_clock_levels_with_latency clocks;
3263         struct vega20_single_dpm_table *fclk_dpm_table =
3264                         &(data->dpm_table.fclk_table);
3265         int i, now, size = 0;
3266         int ret = 0;
3267         uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
3268 
3269         switch (type) {
3270         case PP_SCLK:
3271                 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now);
3272                 PP_ASSERT_WITH_CODE(!ret,
3273                                 "Attempt to get current gfx clk Failed!",
3274                                 return ret);
3275 
3276                 if (vega20_get_sclks(hwmgr, &clocks)) {
3277                         size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3278                                 now / 100);
3279                         break;
3280                 }
3281 
3282                 for (i = 0; i < clocks.num_levels; i++)
3283                         size += sprintf(buf + size, "%d: %uMhz %s\n",
3284                                 i, clocks.data[i].clocks_in_khz / 1000,
3285                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3286                 break;
3287 
3288         case PP_MCLK:
3289                 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now);
3290                 PP_ASSERT_WITH_CODE(!ret,
3291                                 "Attempt to get current mclk freq Failed!",
3292                                 return ret);
3293 
3294                 if (vega20_get_memclocks(hwmgr, &clocks)) {
3295                         size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3296                                 now / 100);
3297                         break;
3298                 }
3299 
3300                 for (i = 0; i < clocks.num_levels; i++)
3301                         size += sprintf(buf + size, "%d: %uMhz %s\n",
3302                                 i, clocks.data[i].clocks_in_khz / 1000,
3303                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3304                 break;
3305 
3306         case PP_SOCCLK:
3307                 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
3308                 PP_ASSERT_WITH_CODE(!ret,
3309                                 "Attempt to get current socclk freq Failed!",
3310                                 return ret);
3311 
3312                 if (vega20_get_socclocks(hwmgr, &clocks)) {
3313                         size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3314                                 now / 100);
3315                         break;
3316                 }
3317 
3318                 for (i = 0; i < clocks.num_levels; i++)
3319                         size += sprintf(buf + size, "%d: %uMhz %s\n",
3320                                 i, clocks.data[i].clocks_in_khz / 1000,
3321                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3322                 break;
3323 
3324         case PP_FCLK:
3325                 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
3326                 PP_ASSERT_WITH_CODE(!ret,
3327                                 "Attempt to get current fclk freq Failed!",
3328                                 return ret);
3329 
3330                 for (i = 0; i < fclk_dpm_table->count; i++)
3331                         size += sprintf(buf + size, "%d: %uMhz %s\n",
3332                                 i, fclk_dpm_table->dpm_levels[i].value,
3333                                 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
3334                 break;
3335 
3336         case PP_DCEFCLK:
3337                 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
3338                 PP_ASSERT_WITH_CODE(!ret,
3339                                 "Attempt to get current dcefclk freq Failed!",
3340                                 return ret);
3341 
3342                 if (vega20_get_dcefclocks(hwmgr, &clocks)) {
3343                         size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3344                                 now / 100);
3345                         break;
3346                 }
3347 
3348                 for (i = 0; i < clocks.num_levels; i++)
3349                         size += sprintf(buf + size, "%d: %uMhz %s\n",
3350                                 i, clocks.data[i].clocks_in_khz / 1000,
3351                                 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3352                 break;
3353 
3354         case PP_PCIE:
3355                 current_gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
3356                              PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
3357                             >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
3358                 current_lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
3359                               PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
3360                             >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
3361                 for (i = 0; i < NUM_LINK_LEVELS; i++) {
3362                         if (i == 1 && data->pcie_parameters_override) {
3363                                 gen_speed = data->pcie_gen_level1;
3364                                 lane_width = data->pcie_width_level1;
3365                         } else {
3366                                 gen_speed = pptable->PcieGenSpeed[i];
3367                                 lane_width = pptable->PcieLaneCount[i];
3368                         }
3369                         size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
3370                                         (gen_speed == 0) ? "2.5GT/s," :
3371                                         (gen_speed == 1) ? "5.0GT/s," :
3372                                         (gen_speed == 2) ? "8.0GT/s," :
3373                                         (gen_speed == 3) ? "16.0GT/s," : "",
3374                                         (lane_width == 1) ? "x1" :
3375                                         (lane_width == 2) ? "x2" :
3376                                         (lane_width == 3) ? "x4" :
3377                                         (lane_width == 4) ? "x8" :
3378                                         (lane_width == 5) ? "x12" :
3379                                         (lane_width == 6) ? "x16" : "",
3380                                         pptable->LclkFreq[i],
3381                                         (current_gen_speed == gen_speed) &&
3382                                         (current_lane_width == lane_width) ?
3383                                         "*" : "");
3384                 }
3385                 break;
3386 
3387         case OD_SCLK:
3388                 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3389                     od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3390                         size = sprintf(buf, "%s:\n", "OD_SCLK");
3391                         size += sprintf(buf + size, "0: %10uMhz\n",
3392                                 od_table->GfxclkFmin);
3393                         size += sprintf(buf + size, "1: %10uMhz\n",
3394                                 od_table->GfxclkFmax);
3395                 }
3396                 break;
3397 
3398         case OD_MCLK:
3399                 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3400                         size = sprintf(buf, "%s:\n", "OD_MCLK");
3401                         size += sprintf(buf + size, "1: %10uMhz\n",
3402                                 od_table->UclkFmax);
3403                 }
3404 
3405                 break;
3406 
3407         case OD_VDDC_CURVE:
3408                 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3409                     od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3410                     od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3411                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3412                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3413                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3414                         size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
3415                         size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
3416                                 od_table->GfxclkFreq1,
3417                                 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
3418                         size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
3419                                 od_table->GfxclkFreq2,
3420                                 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
3421                         size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
3422                                 od_table->GfxclkFreq3,
3423                                 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
3424                 }
3425 
3426                 break;
3427 
3428         case OD_RANGE:
3429                 size = sprintf(buf, "%s:\n", "OD_RANGE");
3430 
3431                 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3432                     od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3433                         size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
3434                                 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
3435                                 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
3436                 }
3437 
3438                 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3439                         size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
3440                                 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
3441                                 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
3442                 }
3443 
3444                 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3445                     od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3446                     od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3447                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3448                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3449                     od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3450                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
3451                                 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
3452                                 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
3453                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
3454                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
3455                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
3456                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
3457                                 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
3458                                 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
3459                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
3460                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
3461                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
3462                         size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
3463                                 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
3464                                 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
3465                         size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
3466                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
3467                                 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
3468                 }
3469 
3470                 break;
3471         default:
3472                 break;
3473         }
3474         return size;
3475 }
3476 
3477 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
3478                 struct vega20_single_dpm_table *dpm_table)
3479 {
3480         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3481         int ret = 0;
3482 
3483         if (data->smu_features[GNLD_DPM_UCLK].enabled) {
3484                 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3485                                 "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
3486                                 return -EINVAL);
3487                 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
3488                                 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
3489                                 return -EINVAL);
3490 
3491                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3492                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3493                                 PPSMC_MSG_SetHardMinByFreq,
3494                                 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
3495                                 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
3496                                 return ret);
3497         }
3498 
3499         return ret;
3500 }
3501 
3502 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr)
3503 {
3504         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3505         struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table);
3506         int ret = 0;
3507 
3508         if (data->smu_features[GNLD_DPM_FCLK].enabled) {
3509                 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3510                                 "[SetFclkToHightestDpmLevel] Dpm table has no entry!",
3511                                 return -EINVAL);
3512                 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS,
3513                                 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!",
3514                                 return -EINVAL);
3515 
3516                 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3517                 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3518                                 PPSMC_MSG_SetSoftMinByFreq,
3519                                 (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level)),
3520                                 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!",
3521                                 return ret);
3522         }
3523 
3524         return ret;
3525 }
3526 
3527 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3528 {
3529         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3530         int ret = 0;
3531 
3532         smum_send_msg_to_smc_with_parameter(hwmgr,
3533                         PPSMC_MSG_NumOfDisplays, 0);
3534 
3535         ret = vega20_set_uclk_to_highest_dpm_level(hwmgr,
3536                         &data->dpm_table.mem_table);
3537         if (ret)
3538                 return ret;
3539 
3540         return vega20_set_fclk_to_highest_dpm_level(hwmgr);
3541 }
3542 
3543 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3544 {
3545         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3546         int result = 0;
3547         Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
3548 
3549         if ((data->water_marks_bitmap & WaterMarksExist) &&
3550             !(data->water_marks_bitmap & WaterMarksLoaded)) {
3551                 result = smum_smc_table_manager(hwmgr,
3552                                                 (uint8_t *)wm_table, TABLE_WATERMARKS, false);
3553                 PP_ASSERT_WITH_CODE(!result,
3554                                 "Failed to update WMTABLE!",
3555                                 return result);
3556                 data->water_marks_bitmap |= WaterMarksLoaded;
3557         }
3558 
3559         if ((data->water_marks_bitmap & WaterMarksExist) &&
3560             data->smu_features[GNLD_DPM_DCEFCLK].supported &&
3561             data->smu_features[GNLD_DPM_SOCCLK].supported) {
3562                 result = smum_send_msg_to_smc_with_parameter(hwmgr,
3563                         PPSMC_MSG_NumOfDisplays,
3564                         hwmgr->display_config->num_display);
3565         }
3566 
3567         return result;
3568 }
3569 
3570 int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
3571 {
3572         struct vega20_hwmgr *data =
3573                         (struct vega20_hwmgr *)(hwmgr->backend);
3574         int ret = 0;
3575 
3576         if (data->smu_features[GNLD_DPM_UVD].supported) {
3577                 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) {
3578                         if (enable)
3579                                 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n");
3580                         else
3581                                 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n");
3582                 }
3583 
3584                 ret = vega20_enable_smc_features(hwmgr,
3585                                 enable,
3586                                 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap);
3587                 PP_ASSERT_WITH_CODE(!ret,
3588                                 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!",
3589                                 return ret);
3590                 data->smu_features[GNLD_DPM_UVD].enabled = enable;
3591         }
3592 
3593         return 0;
3594 }
3595 
3596 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
3597 {
3598         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3599 
3600         if (data->vce_power_gated == bgate)
3601                 return ;
3602 
3603         data->vce_power_gated = bgate;
3604         if (bgate) {
3605                 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3606                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3607                                                 AMD_IP_BLOCK_TYPE_VCE,
3608                                                 AMD_PG_STATE_GATE);
3609         } else {
3610                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3611                                                 AMD_IP_BLOCK_TYPE_VCE,
3612                                                 AMD_PG_STATE_UNGATE);
3613                 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3614         }
3615 
3616 }
3617 
3618 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
3619 {
3620         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3621 
3622         if (data->uvd_power_gated == bgate)
3623                 return ;
3624 
3625         data->uvd_power_gated = bgate;
3626         vega20_enable_disable_uvd_dpm(hwmgr, !bgate);
3627 }
3628 
3629 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
3630 {
3631         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3632         struct vega20_single_dpm_table *dpm_table;
3633         bool vblank_too_short = false;
3634         bool disable_mclk_switching;
3635         bool disable_fclk_switching;
3636         uint32_t i, latency;
3637 
3638         disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
3639                            !hwmgr->display_config->multi_monitor_in_sync) ||
3640                             vblank_too_short;
3641         latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3642 
3643         /* gfxclk */
3644         dpm_table = &(data->dpm_table.gfx_table);
3645         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3646         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3647         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3648         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3649 
3650         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3651                 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
3652                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3653                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3654                 }
3655 
3656                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3657                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3658                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3659                 }
3660 
3661                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3662                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3663                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3664                 }
3665         }
3666 
3667         /* memclk */
3668         dpm_table = &(data->dpm_table.mem_table);
3669         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3670         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3671         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3672         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3673 
3674         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3675                 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
3676                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3677                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3678                 }
3679 
3680                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
3681                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3682                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3683                 }
3684 
3685                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3686                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3687                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3688                 }
3689         }
3690 
3691         /* honour DAL's UCLK Hardmin */
3692         if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
3693                 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
3694 
3695         /* Hardmin is dependent on displayconfig */
3696         if (disable_mclk_switching) {
3697                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3698                 for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
3699                         if (data->mclk_latency_table.entries[i].latency <= latency) {
3700                                 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
3701                                         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
3702                                         break;
3703                                 }
3704                         }
3705                 }
3706         }
3707 
3708         if (hwmgr->display_config->nb_pstate_switch_disable)
3709                 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3710 
3711         if ((disable_mclk_switching &&
3712             (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) ||
3713              hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value)
3714                 disable_fclk_switching = true;
3715         else
3716                 disable_fclk_switching = false;
3717 
3718         /* fclk */
3719         dpm_table = &(data->dpm_table.fclk_table);
3720         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3721         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3722         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3723         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3724         if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching)
3725                 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3726 
3727         /* vclk */
3728         dpm_table = &(data->dpm_table.vclk_table);
3729         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3730         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3731         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3732         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3733 
3734         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3735                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3736                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3737                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3738                 }
3739 
3740                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3741                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3742                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3743                 }
3744         }
3745 
3746         /* dclk */
3747         dpm_table = &(data->dpm_table.dclk_table);
3748         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3749         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3750         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3751         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3752 
3753         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3754                 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3755                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3756                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3757                 }
3758 
3759                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3760                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3761                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3762                 }
3763         }
3764 
3765         /* socclk */
3766         dpm_table = &(data->dpm_table.soc_table);
3767         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3768         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3769         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3770         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3771 
3772         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3773                 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
3774                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3775                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3776                 }
3777 
3778                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3779                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3780                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3781                 }
3782         }
3783 
3784         /* eclk */
3785         dpm_table = &(data->dpm_table.eclk_table);
3786         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3787         dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3788         dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3789         dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3790 
3791         if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3792                 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
3793                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3794                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3795                 }
3796 
3797                 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3798                         dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3799                         dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3800                 }
3801         }
3802 
3803         return 0;
3804 }
3805 
3806 static bool
3807 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
3808 {
3809         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3810         bool is_update_required = false;
3811 
3812         if (data->display_timing.num_existing_displays !=
3813                         hwmgr->display_config->num_display)
3814                 is_update_required = true;
3815 
3816         if (data->registry_data.gfx_clk_deep_sleep_support &&
3817            (data->display_timing.min_clock_in_sr !=
3818             hwmgr->display_config->min_core_set_clock_in_sr))
3819                 is_update_required = true;
3820 
3821         return is_update_required;
3822 }
3823 
3824 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
3825 {
3826         int ret = 0;
3827 
3828         ret = vega20_disable_all_smu_features(hwmgr);
3829         PP_ASSERT_WITH_CODE(!ret,
3830                         "[DisableDpmTasks] Failed to disable all smu features!",
3831                         return ret);
3832 
3833         return 0;
3834 }
3835 
3836 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr)
3837 {
3838         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3839         int result;
3840 
3841         result = vega20_disable_dpm_tasks(hwmgr);
3842         PP_ASSERT_WITH_CODE((0 == result),
3843                         "[PowerOffAsic] Failed to disable DPM!",
3844                         );
3845         data->water_marks_bitmap &= ~(WaterMarksLoaded);
3846 
3847         return result;
3848 }
3849 
3850 static int conv_power_profile_to_pplib_workload(int power_profile)
3851 {
3852         int pplib_workload = 0;
3853 
3854         switch (power_profile) {
3855         case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
3856                 pplib_workload = WORKLOAD_DEFAULT_BIT;
3857                 break;
3858         case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
3859                 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
3860                 break;
3861         case PP_SMC_POWER_PROFILE_POWERSAVING:
3862                 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
3863                 break;
3864         case PP_SMC_POWER_PROFILE_VIDEO:
3865                 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
3866                 break;
3867         case PP_SMC_POWER_PROFILE_VR:
3868                 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
3869                 break;
3870         case PP_SMC_POWER_PROFILE_COMPUTE:
3871                 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
3872                 break;
3873         case PP_SMC_POWER_PROFILE_CUSTOM:
3874                 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
3875                 break;
3876         }
3877 
3878         return pplib_workload;
3879 }
3880 
3881 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
3882 {
3883         DpmActivityMonitorCoeffInt_t activity_monitor;
3884         uint32_t i, size = 0;
3885         uint16_t workload_type = 0;
3886         static const char *profile_name[] = {
3887                                         "BOOTUP_DEFAULT",
3888                                         "3D_FULL_SCREEN",
3889                                         "POWER_SAVING",
3890                                         "VIDEO",
3891                                         "VR",
3892                                         "COMPUTE",
3893                                         "CUSTOM"};
3894         static const char *title[] = {
3895                         "PROFILE_INDEX(NAME)",
3896                         "CLOCK_TYPE(NAME)",
3897                         "FPS",
3898                         "UseRlcBusy",
3899                         "MinActiveFreqType",
3900                         "MinActiveFreq",
3901                         "BoosterFreqType",
3902                         "BoosterFreq",
3903                         "PD_Data_limit_c",
3904                         "PD_Data_error_coeff",
3905                         "PD_Data_error_rate_coeff"};
3906         int result = 0;
3907 
3908         if (!buf)
3909                 return -EINVAL;
3910 
3911         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
3912                         title[0], title[1], title[2], title[3], title[4], title[5],
3913                         title[6], title[7], title[8], title[9], title[10]);
3914 
3915         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
3916                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
3917                 workload_type = conv_power_profile_to_pplib_workload(i);
3918                 result = vega20_get_activity_monitor_coeff(hwmgr,
3919                                 (uint8_t *)(&activity_monitor), workload_type);
3920                 PP_ASSERT_WITH_CODE(!result,
3921                                 "[GetPowerProfile] Failed to get activity monitor!",
3922                                 return result);
3923 
3924                 size += sprintf(buf + size, "%2d %14s%s:\n",
3925                         i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
3926 
3927                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3928                         " ",
3929                         0,
3930                         "GFXCLK",
3931                         activity_monitor.Gfx_FPS,
3932                         activity_monitor.Gfx_UseRlcBusy,
3933                         activity_monitor.Gfx_MinActiveFreqType,
3934                         activity_monitor.Gfx_MinActiveFreq,
3935                         activity_monitor.Gfx_BoosterFreqType,
3936                         activity_monitor.Gfx_BoosterFreq,
3937                         activity_monitor.Gfx_PD_Data_limit_c,
3938                         activity_monitor.Gfx_PD_Data_error_coeff,
3939                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
3940 
3941                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3942                         " ",
3943                         1,
3944                         "SOCCLK",
3945                         activity_monitor.Soc_FPS,
3946                         activity_monitor.Soc_UseRlcBusy,
3947                         activity_monitor.Soc_MinActiveFreqType,
3948                         activity_monitor.Soc_MinActiveFreq,
3949                         activity_monitor.Soc_BoosterFreqType,
3950                         activity_monitor.Soc_BoosterFreq,
3951                         activity_monitor.Soc_PD_Data_limit_c,
3952                         activity_monitor.Soc_PD_Data_error_coeff,
3953                         activity_monitor.Soc_PD_Data_error_rate_coeff);
3954 
3955                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3956                         " ",
3957                         2,
3958                         "UCLK",
3959                         activity_monitor.Mem_FPS,
3960                         activity_monitor.Mem_UseRlcBusy,
3961                         activity_monitor.Mem_MinActiveFreqType,
3962                         activity_monitor.Mem_MinActiveFreq,
3963                         activity_monitor.Mem_BoosterFreqType,
3964                         activity_monitor.Mem_BoosterFreq,
3965                         activity_monitor.Mem_PD_Data_limit_c,
3966                         activity_monitor.Mem_PD_Data_error_coeff,
3967                         activity_monitor.Mem_PD_Data_error_rate_coeff);
3968 
3969                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3970                         " ",
3971                         3,
3972                         "FCLK",
3973                         activity_monitor.Fclk_FPS,
3974                         activity_monitor.Fclk_UseRlcBusy,
3975                         activity_monitor.Fclk_MinActiveFreqType,
3976                         activity_monitor.Fclk_MinActiveFreq,
3977                         activity_monitor.Fclk_BoosterFreqType,
3978                         activity_monitor.Fclk_BoosterFreq,
3979                         activity_monitor.Fclk_PD_Data_limit_c,
3980                         activity_monitor.Fclk_PD_Data_error_coeff,
3981                         activity_monitor.Fclk_PD_Data_error_rate_coeff);
3982         }
3983 
3984         return size;
3985 }
3986 
3987 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
3988 {
3989         DpmActivityMonitorCoeffInt_t activity_monitor;
3990         int workload_type, result = 0;
3991         uint32_t power_profile_mode = input[size];
3992 
3993         if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
3994                 pr_err("Invalid power profile mode %d\n", power_profile_mode);
3995                 return -EINVAL;
3996         }
3997 
3998         if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
3999                 struct vega20_hwmgr *data =
4000                         (struct vega20_hwmgr *)(hwmgr->backend);
4001                 if (size == 0 && !data->is_custom_profile_set)
4002                         return -EINVAL;
4003                 if (size < 10 && size != 0)
4004                         return -EINVAL;
4005 
4006                 result = vega20_get_activity_monitor_coeff(hwmgr,
4007                                 (uint8_t *)(&activity_monitor),
4008                                 WORKLOAD_PPLIB_CUSTOM_BIT);
4009                 PP_ASSERT_WITH_CODE(!result,
4010                                 "[SetPowerProfile] Failed to get activity monitor!",
4011                                 return result);
4012 
4013                 /* If size==0, then we want to apply the already-configured
4014                  * CUSTOM profile again. Just apply it, since we checked its
4015                  * validity above
4016                  */
4017                 if (size == 0)
4018                         goto out;
4019 
4020                 switch (input[0]) {
4021                 case 0: /* Gfxclk */
4022                         activity_monitor.Gfx_FPS = input[1];
4023                         activity_monitor.Gfx_UseRlcBusy = input[2];
4024                         activity_monitor.Gfx_MinActiveFreqType = input[3];
4025                         activity_monitor.Gfx_MinActiveFreq = input[4];
4026                         activity_monitor.Gfx_BoosterFreqType = input[5];
4027                         activity_monitor.Gfx_BoosterFreq = input[6];
4028                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
4029                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
4030                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
4031                         break;
4032                 case 1: /* Socclk */
4033                         activity_monitor.Soc_FPS = input[1];
4034                         activity_monitor.Soc_UseRlcBusy = input[2];
4035                         activity_monitor.Soc_MinActiveFreqType = input[3];
4036                         activity_monitor.Soc_MinActiveFreq = input[4];
4037                         activity_monitor.Soc_BoosterFreqType = input[5];
4038                         activity_monitor.Soc_BoosterFreq = input[6];
4039                         activity_monitor.Soc_PD_Data_limit_c = input[7];
4040                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
4041                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
4042                         break;
4043                 case 2: /* Uclk */
4044                         activity_monitor.Mem_FPS = input[1];
4045                         activity_monitor.Mem_UseRlcBusy = input[2];
4046                         activity_monitor.Mem_MinActiveFreqType = input[3];
4047                         activity_monitor.Mem_MinActiveFreq = input[4];
4048                         activity_monitor.Mem_BoosterFreqType = input[5];
4049                         activity_monitor.Mem_BoosterFreq = input[6];
4050                         activity_monitor.Mem_PD_Data_limit_c = input[7];
4051                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
4052                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
4053                         break;
4054                 case 3: /* Fclk */
4055                         activity_monitor.Fclk_FPS = input[1];
4056                         activity_monitor.Fclk_UseRlcBusy = input[2];
4057                         activity_monitor.Fclk_MinActiveFreqType = input[3];
4058                         activity_monitor.Fclk_MinActiveFreq = input[4];
4059                         activity_monitor.Fclk_BoosterFreqType = input[5];
4060                         activity_monitor.Fclk_BoosterFreq = input[6];
4061                         activity_monitor.Fclk_PD_Data_limit_c = input[7];
4062                         activity_monitor.Fclk_PD_Data_error_coeff = input[8];
4063                         activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
4064                         break;
4065                 }
4066 
4067                 result = vega20_set_activity_monitor_coeff(hwmgr,
4068                                 (uint8_t *)(&activity_monitor),
4069                                 WORKLOAD_PPLIB_CUSTOM_BIT);
4070                 data->is_custom_profile_set = true;
4071                 PP_ASSERT_WITH_CODE(!result,
4072                                 "[SetPowerProfile] Failed to set activity monitor!",
4073                                 return result);
4074         }
4075 
4076 out:
4077         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
4078         workload_type =
4079                 conv_power_profile_to_pplib_workload(power_profile_mode);
4080         smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
4081                                                 1 << workload_type);
4082 
4083         hwmgr->power_profile_mode = power_profile_mode;
4084 
4085         return 0;
4086 }
4087 
4088 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
4089                                         uint32_t virtual_addr_low,
4090                                         uint32_t virtual_addr_hi,
4091                                         uint32_t mc_addr_low,
4092                                         uint32_t mc_addr_hi,
4093                                         uint32_t size)
4094 {
4095         smum_send_msg_to_smc_with_parameter(hwmgr,
4096                                         PPSMC_MSG_SetSystemVirtualDramAddrHigh,
4097                                         virtual_addr_hi);
4098         smum_send_msg_to_smc_with_parameter(hwmgr,
4099                                         PPSMC_MSG_SetSystemVirtualDramAddrLow,
4100                                         virtual_addr_low);
4101         smum_send_msg_to_smc_with_parameter(hwmgr,
4102                                         PPSMC_MSG_DramLogSetDramAddrHigh,
4103                                         mc_addr_hi);
4104 
4105         smum_send_msg_to_smc_with_parameter(hwmgr,
4106                                         PPSMC_MSG_DramLogSetDramAddrLow,
4107                                         mc_addr_low);
4108 
4109         smum_send_msg_to_smc_with_parameter(hwmgr,
4110                                         PPSMC_MSG_DramLogSetDramSize,
4111                                         size);
4112         return 0;
4113 }
4114 
4115 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
4116                 struct PP_TemperatureRange *thermal_data)
4117 {
4118         struct vega20_hwmgr *data =
4119                         (struct vega20_hwmgr *)(hwmgr->backend);
4120         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
4121 
4122         memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
4123 
4124         thermal_data->max = pp_table->TedgeLimit *
4125                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4126         thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
4127                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4128         thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
4129                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4130         thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
4131                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4132         thermal_data->mem_crit_max = pp_table->ThbmLimit *
4133                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4134         thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
4135                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4136 
4137         return 0;
4138 }
4139 
4140 static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire)
4141 {
4142         int res;
4143 
4144         /* I2C bus access can happen very early, when SMU not loaded yet */
4145         if (!vega20_is_smc_ram_running(hwmgr))
4146                 return 0;
4147 
4148         res = smum_send_msg_to_smc_with_parameter(hwmgr,
4149                                                   (acquire ?
4150                                                   PPSMC_MSG_RequestI2CBus :
4151                                                   PPSMC_MSG_ReleaseI2CBus),
4152                                                   0);
4153 
4154         PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res);
4155         return res;
4156 }
4157 
4158 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
4159         /* init/fini related */
4160         .backend_init = vega20_hwmgr_backend_init,
4161         .backend_fini = vega20_hwmgr_backend_fini,
4162         .asic_setup = vega20_setup_asic_task,
4163         .power_off_asic = vega20_power_off_asic,
4164         .dynamic_state_management_enable = vega20_enable_dpm_tasks,
4165         .dynamic_state_management_disable = vega20_disable_dpm_tasks,
4166         /* power state related */
4167         .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
4168         .pre_display_config_changed = vega20_pre_display_configuration_changed_task,
4169         .display_config_changed = vega20_display_configuration_changed_task,
4170         .check_smc_update_required_for_display_configuration =
4171                 vega20_check_smc_update_required_for_display_configuration,
4172         .notify_smc_display_config_after_ps_adjustment =
4173                 vega20_notify_smc_display_config_after_ps_adjustment,
4174         /* export to DAL */
4175         .get_sclk = vega20_dpm_get_sclk,
4176         .get_mclk = vega20_dpm_get_mclk,
4177         .get_dal_power_level = vega20_get_dal_power_level,
4178         .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
4179         .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage,
4180         .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges,
4181         .display_clock_voltage_request = vega20_display_clock_voltage_request,
4182         .get_performance_level = vega20_get_performance_level,
4183         /* UMD pstate, profile related */
4184         .force_dpm_level = vega20_dpm_force_dpm_level,
4185         .get_power_profile_mode = vega20_get_power_profile_mode,
4186         .set_power_profile_mode = vega20_set_power_profile_mode,
4187         /* od related */
4188         .set_power_limit = vega20_set_power_limit,
4189         .get_sclk_od = vega20_get_sclk_od,
4190         .set_sclk_od = vega20_set_sclk_od,
4191         .get_mclk_od = vega20_get_mclk_od,
4192         .set_mclk_od = vega20_set_mclk_od,
4193         .odn_edit_dpm_table = vega20_odn_edit_dpm_table,
4194         /* for sysfs to retrive/set gfxclk/memclk */
4195         .force_clock_level = vega20_force_clock_level,
4196         .print_clock_levels = vega20_print_clock_levels,
4197         .read_sensor = vega20_read_sensor,
4198         .get_ppfeature_status = vega20_get_ppfeature_status,
4199         .set_ppfeature_status = vega20_set_ppfeature_status,
4200         /* powergate related */
4201         .powergate_uvd = vega20_power_gate_uvd,
4202         .powergate_vce = vega20_power_gate_vce,
4203         /* thermal related */
4204         .start_thermal_controller = vega20_start_thermal_controller,
4205         .stop_thermal_controller = vega20_thermal_stop_thermal_controller,
4206         .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
4207         .register_irq_handlers = smu9_register_irq_handlers,
4208         .disable_smc_firmware_ctf = vega20_thermal_disable_alert,
4209         /* fan control related */
4210         .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent,
4211         .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent,
4212         .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info,
4213         .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm,
4214         .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm,
4215         .get_fan_control_mode = vega20_get_fan_control_mode,
4216         .set_fan_control_mode = vega20_set_fan_control_mode,
4217         /* smu memory related */
4218         .notify_cac_buffer_info = vega20_notify_cac_buffer_info,
4219         .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost,
4220         /* BACO related */
4221         .get_asic_baco_capability = vega20_baco_get_capability,
4222         .get_asic_baco_state = vega20_baco_get_state,
4223         .set_asic_baco_state = vega20_baco_set_state,
4224         .set_mp1_state = vega20_set_mp1_state,
4225         .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
4226 };
4227 
4228 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
4229 {
4230         hwmgr->hwmgr_func = &vega20_hwmgr_funcs;
4231         hwmgr->pptable_func = &vega20_pptable_funcs;
4232 
4233         return 0;
4234 }

/* [<][>][^][v][top][bottom][index][help] */