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

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

DEFINITIONS

This source file includes following definitions.
  1. cast_phw_vega10_power_state
  2. cast_const_phw_vega10_power_state
  3. vega10_set_default_registry_data
  4. vega10_set_features_platform_caps
  5. vega10_odn_initial_default_setting
  6. vega10_init_dpm_defaults
  7. vega10_get_socclk_for_voltage_evv
  8. vega10_get_evv_voltages
  9. vega10_patch_with_vdd_leakage
  10. vega10_patch_lookup_table_with_leakage
  11. vega10_patch_clock_voltage_limits_with_vddc_leakage
  12. vega10_patch_voltage_dependency_tables_with_lookup_table
  13. vega10_sort_lookup_table
  14. vega10_complete_dependency_tables
  15. vega10_set_private_data_based_on_pptable
  16. vega10_hwmgr_backend_fini
  17. vega10_hwmgr_backend_init
  18. vega10_init_sclk_threshold
  19. vega10_setup_dpm_led_config
  20. vega10_setup_asic_task
  21. vega10_trim_voltage_table
  22. vega10_get_mvdd_voltage_table
  23. vega10_get_vddci_voltage_table
  24. vega10_get_vdd_voltage_table
  25. vega10_trim_voltage_table_to_fit_state_table
  26. vega10_construct_voltage_tables
  27. vega10_init_dpm_state
  28. vega10_setup_default_single_dpm_table
  29. vega10_setup_default_pcie_table
  30. vega10_setup_default_dpm_tables
  31. vega10_populate_ulv_state
  32. vega10_populate_single_lclk_level
  33. vega10_populate_smc_link_levels
  34. vega10_populate_single_gfx_level
  35. vega10_populate_single_soc_level
  36. vega10_populate_all_graphic_levels
  37. vega10_populate_vddc_soc_levels
  38. vega10_populate_single_memory_level
  39. vega10_populate_all_memory_levels
  40. vega10_populate_single_display_type
  41. vega10_populate_all_display_clock_levels
  42. vega10_populate_single_eclock_level
  43. vega10_populate_smc_vce_levels
  44. vega10_populate_single_vclock_level
  45. vega10_populate_single_dclock_level
  46. vega10_populate_smc_uvd_levels
  47. vega10_populate_clock_stretcher_table
  48. vega10_populate_avfs_parameters
  49. vega10_acg_enable
  50. vega10_acg_disable
  51. vega10_populate_gpio_parameters
  52. vega10_avfs_enable
  53. vega10_update_avfs
  54. vega10_populate_and_upload_avfs_fuse_override
  55. vega10_check_dpm_table_updated
  56. vega10_init_smc_table
  57. vega10_enable_thermal_protection
  58. vega10_disable_thermal_protection
  59. vega10_enable_vrhot_feature
  60. vega10_enable_ulv
  61. vega10_disable_ulv
  62. vega10_enable_deep_sleep_master_switch
  63. vega10_disable_deep_sleep_master_switch
  64. vega10_stop_dpm
  65. vega10_start_dpm
  66. vega10_enable_disable_PCC_limit_feature
  67. vega10_enable_dpm_tasks
  68. vega10_get_power_state_size
  69. vega10_get_pp_table_entry_callback_func
  70. vega10_get_pp_table_entry
  71. vega10_patch_boot_state
  72. vega10_apply_state_adjust_rules
  73. vega10_find_dpm_states_clocks_in_dpm_table
  74. vega10_populate_and_upload_sclk_mclk_dpm_levels
  75. vega10_trim_single_dpm_states
  76. vega10_trim_single_dpm_states_with_mask
  77. vega10_trim_dpm_states
  78. vega10_find_lowest_dpm_level
  79. vega10_find_highest_dpm_level
  80. vega10_apply_dal_minimum_voltage_request
  81. vega10_get_soc_index_for_max_uclk
  82. vega10_upload_dpm_bootup_level
  83. vega10_upload_dpm_max_level
  84. vega10_generate_dpm_level_enable_mask
  85. vega10_enable_disable_vce_dpm
  86. vega10_update_sclk_threshold
  87. vega10_set_power_state_tasks
  88. vega10_dpm_get_sclk
  89. vega10_dpm_get_mclk
  90. vega10_get_gpu_power
  91. vega10_read_sensor
  92. vega10_notify_smc_display_change
  93. vega10_display_clock_voltage_request
  94. vega10_get_uclk_index
  95. vega10_notify_smc_display_config_after_ps_adjustment
  96. vega10_force_dpm_highest
  97. vega10_force_dpm_lowest
  98. vega10_unforce_dpm_levels
  99. vega10_get_profiling_clk_mask
  100. vega10_set_fan_control_mode
  101. vega10_force_clock_level
  102. vega10_dpm_force_dpm_level
  103. vega10_get_fan_control_mode
  104. vega10_get_dal_power_level
  105. vega10_get_sclks
  106. vega10_get_memclocks
  107. vega10_get_dcefclocks
  108. vega10_get_socclocks
  109. vega10_get_clock_by_type_with_latency
  110. vega10_get_clock_by_type_with_voltage
  111. vega10_set_watermarks_for_clocks_ranges
  112. vega10_get_ppfeature_status
  113. vega10_set_ppfeature_status
  114. vega10_print_clock_levels
  115. vega10_display_configuration_changed_task
  116. vega10_enable_disable_uvd_dpm
  117. vega10_power_gate_vce
  118. vega10_power_gate_uvd
  119. vega10_are_power_levels_equal
  120. vega10_check_states_equal
  121. vega10_check_smc_update_required_for_display_configuration
  122. vega10_disable_dpm_tasks
  123. vega10_power_off_asic
  124. vega10_get_sclk_od
  125. vega10_set_sclk_od
  126. vega10_get_mclk_od
  127. vega10_set_mclk_od
  128. vega10_notify_cac_buffer_info
  129. vega10_get_thermal_temperature_range
  130. vega10_get_power_profile_mode
  131. vega10_set_power_profile_mode
  132. vega10_check_clk_voltage_valid
  133. vega10_odn_update_power_state
  134. vega10_odn_update_soc_table
  135. vega10_odn_edit_dpm_table
  136. vega10_set_mp1_state
  137. vega10_get_performance_level
  138. vega10_hwmgr_init

   1 /*
   2  * Copyright 2016 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/pci.h>
  28 #include <linux/slab.h>
  29 
  30 #include "hwmgr.h"
  31 #include "amd_powerplay.h"
  32 #include "hardwaremanager.h"
  33 #include "ppatomfwctrl.h"
  34 #include "atomfirmware.h"
  35 #include "cgs_common.h"
  36 #include "vega10_powertune.h"
  37 #include "smu9.h"
  38 #include "smu9_driver_if.h"
  39 #include "vega10_inc.h"
  40 #include "soc15_common.h"
  41 #include "pppcielanes.h"
  42 #include "vega10_hwmgr.h"
  43 #include "vega10_smumgr.h"
  44 #include "vega10_processpptables.h"
  45 #include "vega10_pptable.h"
  46 #include "vega10_thermal.h"
  47 #include "pp_debug.h"
  48 #include "amd_pcie_helpers.h"
  49 #include "ppinterrupt.h"
  50 #include "pp_overdriver.h"
  51 #include "pp_thermal.h"
  52 #include "vega10_baco.h"
  53 
  54 #include "smuio/smuio_9_0_offset.h"
  55 #include "smuio/smuio_9_0_sh_mask.h"
  56 
  57 #define HBM_MEMORY_CHANNEL_WIDTH    128
  58 
  59 static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
  60 
  61 #define mmDF_CS_AON0_DramBaseAddress0                                                                  0x0044
  62 #define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX                                                         0
  63 
  64 //DF_CS_AON0_DramBaseAddress0
  65 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT                                                        0x0
  66 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT                                                    0x1
  67 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT                                                      0x4
  68 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT                                                      0x8
  69 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT                                                      0xc
  70 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK                                                          0x00000001L
  71 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK                                                      0x00000002L
  72 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK                                                        0x000000F0L
  73 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK                                                        0x00000700L
  74 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK                                                        0xFFFFF000L
  75 
  76 typedef enum {
  77         CLK_SMNCLK = 0,
  78         CLK_SOCCLK,
  79         CLK_MP0CLK,
  80         CLK_MP1CLK,
  81         CLK_LCLK,
  82         CLK_DCEFCLK,
  83         CLK_VCLK,
  84         CLK_DCLK,
  85         CLK_ECLK,
  86         CLK_UCLK,
  87         CLK_GFXCLK,
  88         CLK_COUNT,
  89 } CLOCK_ID_e;
  90 
  91 static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic);
  92 
  93 struct vega10_power_state *cast_phw_vega10_power_state(
  94                                   struct pp_hw_power_state *hw_ps)
  95 {
  96         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
  97                                 "Invalid Powerstate Type!",
  98                                  return NULL;);
  99 
 100         return (struct vega10_power_state *)hw_ps;
 101 }
 102 
 103 const struct vega10_power_state *cast_const_phw_vega10_power_state(
 104                                  const struct pp_hw_power_state *hw_ps)
 105 {
 106         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
 107                                 "Invalid Powerstate Type!",
 108                                  return NULL;);
 109 
 110         return (const struct vega10_power_state *)hw_ps;
 111 }
 112 
 113 static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
 114 {
 115         struct vega10_hwmgr *data = hwmgr->backend;
 116 
 117         data->registry_data.sclk_dpm_key_disabled =
 118                         hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
 119         data->registry_data.socclk_dpm_key_disabled =
 120                         hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true;
 121         data->registry_data.mclk_dpm_key_disabled =
 122                         hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
 123         data->registry_data.pcie_dpm_key_disabled =
 124                         hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
 125 
 126         data->registry_data.dcefclk_dpm_key_disabled =
 127                         hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true;
 128 
 129         if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
 130                 data->registry_data.power_containment_support = 1;
 131                 data->registry_data.enable_pkg_pwr_tracking_feature = 1;
 132                 data->registry_data.enable_tdc_limit_feature = 1;
 133         }
 134 
 135         data->registry_data.clock_stretcher_support =
 136                         hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false;
 137 
 138         data->registry_data.ulv_support =
 139                         hwmgr->feature_mask & PP_ULV_MASK ? true : false;
 140 
 141         data->registry_data.sclk_deep_sleep_support =
 142                         hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false;
 143 
 144         data->registry_data.disable_water_mark = 0;
 145 
 146         data->registry_data.fan_control_support = 1;
 147         data->registry_data.thermal_support = 1;
 148         data->registry_data.fw_ctf_enabled = 1;
 149 
 150         data->registry_data.avfs_support =
 151                 hwmgr->feature_mask & PP_AVFS_MASK ? true : false;
 152         data->registry_data.led_dpm_enabled = 1;
 153 
 154         data->registry_data.vr0hot_enabled = 1;
 155         data->registry_data.vr1hot_enabled = 1;
 156         data->registry_data.regulator_hot_gpio_support = 1;
 157 
 158         data->registry_data.didt_support = 1;
 159         if (data->registry_data.didt_support) {
 160                 data->registry_data.didt_mode = 6;
 161                 data->registry_data.sq_ramping_support = 1;
 162                 data->registry_data.db_ramping_support = 0;
 163                 data->registry_data.td_ramping_support = 0;
 164                 data->registry_data.tcp_ramping_support = 0;
 165                 data->registry_data.dbr_ramping_support = 0;
 166                 data->registry_data.edc_didt_support = 1;
 167                 data->registry_data.gc_didt_support = 0;
 168                 data->registry_data.psm_didt_support = 0;
 169         }
 170 
 171         data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT;
 172         data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 173         data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 174         data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 175         data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 176         data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 177         data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 178         data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 179         data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 180         data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 181         data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 182         data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 183         data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
 184 
 185         data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT;
 186         data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT;
 187         data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT;
 188         data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT;
 189 }
 190 
 191 static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
 192 {
 193         struct vega10_hwmgr *data = hwmgr->backend;
 194         struct phm_ppt_v2_information *table_info =
 195                         (struct phm_ppt_v2_information *)hwmgr->pptable;
 196         struct amdgpu_device *adev = hwmgr->adev;
 197 
 198         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 199                         PHM_PlatformCaps_SclkDeepSleep);
 200 
 201         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 202                         PHM_PlatformCaps_DynamicPatchPowerState);
 203 
 204         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE)
 205                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 206                                 PHM_PlatformCaps_ControlVDDCI);
 207 
 208         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 209                         PHM_PlatformCaps_EnableSMU7ThermalManagement);
 210 
 211         if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
 212                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 213                                 PHM_PlatformCaps_UVDPowerGating);
 214 
 215         if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
 216                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 217                                 PHM_PlatformCaps_VCEPowerGating);
 218 
 219         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 220                         PHM_PlatformCaps_UnTabledHardwareInterface);
 221 
 222         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 223                         PHM_PlatformCaps_FanSpeedInTableIsRPM);
 224 
 225         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 226                         PHM_PlatformCaps_ODFuzzyFanControlSupport);
 227 
 228         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 229                                 PHM_PlatformCaps_DynamicPowerManagement);
 230 
 231         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 232                         PHM_PlatformCaps_SMC);
 233 
 234         /* power tune caps */
 235         /* assume disabled */
 236         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 237                         PHM_PlatformCaps_PowerContainment);
 238         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 239                         PHM_PlatformCaps_DiDtSupport);
 240         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 241                         PHM_PlatformCaps_SQRamping);
 242         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 243                         PHM_PlatformCaps_DBRamping);
 244         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 245                         PHM_PlatformCaps_TDRamping);
 246         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 247                         PHM_PlatformCaps_TCPRamping);
 248         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 249                         PHM_PlatformCaps_DBRRamping);
 250         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 251                         PHM_PlatformCaps_DiDtEDCEnable);
 252         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 253                         PHM_PlatformCaps_GCEDC);
 254         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 255                         PHM_PlatformCaps_PSM);
 256 
 257         if (data->registry_data.didt_support) {
 258                 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport);
 259                 if (data->registry_data.sq_ramping_support)
 260                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping);
 261                 if (data->registry_data.db_ramping_support)
 262                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping);
 263                 if (data->registry_data.td_ramping_support)
 264                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping);
 265                 if (data->registry_data.tcp_ramping_support)
 266                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping);
 267                 if (data->registry_data.dbr_ramping_support)
 268                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping);
 269                 if (data->registry_data.edc_didt_support)
 270                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable);
 271                 if (data->registry_data.gc_didt_support)
 272                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC);
 273                 if (data->registry_data.psm_didt_support)
 274                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM);
 275         }
 276 
 277         if (data->registry_data.power_containment_support)
 278                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 279                                 PHM_PlatformCaps_PowerContainment);
 280         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 281                         PHM_PlatformCaps_CAC);
 282 
 283         if (table_info->tdp_table->usClockStretchAmount &&
 284                         data->registry_data.clock_stretcher_support)
 285                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 286                                 PHM_PlatformCaps_ClockStretcher);
 287 
 288         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 289                         PHM_PlatformCaps_RegulatorHot);
 290         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 291                         PHM_PlatformCaps_AutomaticDCTransition);
 292 
 293         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 294                         PHM_PlatformCaps_UVDDPM);
 295         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 296                         PHM_PlatformCaps_VCEDPM);
 297 
 298         return 0;
 299 }
 300 
 301 static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
 302 {
 303         struct vega10_hwmgr *data = hwmgr->backend;
 304         struct phm_ppt_v2_information *table_info =
 305                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
 306         struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
 307         struct vega10_odn_vddc_lookup_table *od_lookup_table;
 308         struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
 309         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table[3];
 310         struct phm_ppt_v1_clock_voltage_dependency_table *od_table[3];
 311         struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
 312         uint32_t i;
 313         int result;
 314 
 315         result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
 316         if (!result) {
 317                 data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc;
 318                 data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc;
 319         }
 320 
 321         od_lookup_table = &odn_table->vddc_lookup_table;
 322         vddc_lookup_table = table_info->vddc_lookup_table;
 323 
 324         for (i = 0; i < vddc_lookup_table->count; i++)
 325                 od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd;
 326 
 327         od_lookup_table->count = vddc_lookup_table->count;
 328 
 329         dep_table[0] = table_info->vdd_dep_on_sclk;
 330         dep_table[1] = table_info->vdd_dep_on_mclk;
 331         dep_table[2] = table_info->vdd_dep_on_socclk;
 332         od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk;
 333         od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk;
 334         od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk;
 335 
 336         for (i = 0; i < 3; i++)
 337                 smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]);
 338 
 339         if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000)
 340                 odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc;
 341         if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000)
 342                 odn_table->min_vddc = dep_table[0]->entries[0].vddc;
 343 
 344         i = od_table[2]->count - 1;
 345         od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ?
 346                                         hwmgr->platform_descriptor.overdriveLimit.memoryClock :
 347                                         od_table[2]->entries[i].clk;
 348         od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ?
 349                                         odn_table->max_vddc :
 350                                         od_table[2]->entries[i].vddc;
 351 
 352         return 0;
 353 }
 354 
 355 static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 356 {
 357         struct vega10_hwmgr *data = hwmgr->backend;
 358         int i;
 359         uint32_t sub_vendor_id, hw_revision;
 360         uint32_t top32, bottom32;
 361         struct amdgpu_device *adev = hwmgr->adev;
 362 
 363         vega10_initialize_power_tune_defaults(hwmgr);
 364 
 365         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 366                 data->smu_features[i].smu_feature_id = 0xffff;
 367                 data->smu_features[i].smu_feature_bitmap = 1 << i;
 368                 data->smu_features[i].enabled = false;
 369                 data->smu_features[i].supported = false;
 370         }
 371 
 372         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
 373                         FEATURE_DPM_PREFETCHER_BIT;
 374         data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
 375                         FEATURE_DPM_GFXCLK_BIT;
 376         data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
 377                         FEATURE_DPM_UCLK_BIT;
 378         data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
 379                         FEATURE_DPM_SOCCLK_BIT;
 380         data->smu_features[GNLD_DPM_UVD].smu_feature_id =
 381                         FEATURE_DPM_UVD_BIT;
 382         data->smu_features[GNLD_DPM_VCE].smu_feature_id =
 383                         FEATURE_DPM_VCE_BIT;
 384         data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
 385                         FEATURE_DPM_MP0CLK_BIT;
 386         data->smu_features[GNLD_DPM_LINK].smu_feature_id =
 387                         FEATURE_DPM_LINK_BIT;
 388         data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
 389                         FEATURE_DPM_DCEFCLK_BIT;
 390         data->smu_features[GNLD_ULV].smu_feature_id =
 391                         FEATURE_ULV_BIT;
 392         data->smu_features[GNLD_AVFS].smu_feature_id =
 393                         FEATURE_AVFS_BIT;
 394         data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
 395                         FEATURE_DS_GFXCLK_BIT;
 396         data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
 397                         FEATURE_DS_SOCCLK_BIT;
 398         data->smu_features[GNLD_DS_LCLK].smu_feature_id =
 399                         FEATURE_DS_LCLK_BIT;
 400         data->smu_features[GNLD_PPT].smu_feature_id =
 401                         FEATURE_PPT_BIT;
 402         data->smu_features[GNLD_TDC].smu_feature_id =
 403                         FEATURE_TDC_BIT;
 404         data->smu_features[GNLD_THERMAL].smu_feature_id =
 405                         FEATURE_THERMAL_BIT;
 406         data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
 407                         FEATURE_GFX_PER_CU_CG_BIT;
 408         data->smu_features[GNLD_RM].smu_feature_id =
 409                         FEATURE_RM_BIT;
 410         data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
 411                         FEATURE_DS_DCEFCLK_BIT;
 412         data->smu_features[GNLD_ACDC].smu_feature_id =
 413                         FEATURE_ACDC_BIT;
 414         data->smu_features[GNLD_VR0HOT].smu_feature_id =
 415                         FEATURE_VR0HOT_BIT;
 416         data->smu_features[GNLD_VR1HOT].smu_feature_id =
 417                         FEATURE_VR1HOT_BIT;
 418         data->smu_features[GNLD_FW_CTF].smu_feature_id =
 419                         FEATURE_FW_CTF_BIT;
 420         data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
 421                         FEATURE_LED_DISPLAY_BIT;
 422         data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
 423                         FEATURE_FAN_CONTROL_BIT;
 424         data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
 425         data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
 426         data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT;
 427 
 428         if (!data->registry_data.prefetcher_dpm_key_disabled)
 429                 data->smu_features[GNLD_DPM_PREFETCHER].supported = true;
 430 
 431         if (!data->registry_data.sclk_dpm_key_disabled)
 432                 data->smu_features[GNLD_DPM_GFXCLK].supported = true;
 433 
 434         if (!data->registry_data.mclk_dpm_key_disabled)
 435                 data->smu_features[GNLD_DPM_UCLK].supported = true;
 436 
 437         if (!data->registry_data.socclk_dpm_key_disabled)
 438                 data->smu_features[GNLD_DPM_SOCCLK].supported = true;
 439 
 440         if (PP_CAP(PHM_PlatformCaps_UVDDPM))
 441                 data->smu_features[GNLD_DPM_UVD].supported = true;
 442 
 443         if (PP_CAP(PHM_PlatformCaps_VCEDPM))
 444                 data->smu_features[GNLD_DPM_VCE].supported = true;
 445 
 446         if (!data->registry_data.pcie_dpm_key_disabled)
 447                 data->smu_features[GNLD_DPM_LINK].supported = true;
 448 
 449         if (!data->registry_data.dcefclk_dpm_key_disabled)
 450                 data->smu_features[GNLD_DPM_DCEFCLK].supported = true;
 451 
 452         if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) &&
 453             data->registry_data.sclk_deep_sleep_support) {
 454                 data->smu_features[GNLD_DS_GFXCLK].supported = true;
 455                 data->smu_features[GNLD_DS_SOCCLK].supported = true;
 456                 data->smu_features[GNLD_DS_LCLK].supported = true;
 457                 data->smu_features[GNLD_DS_DCEFCLK].supported = true;
 458         }
 459 
 460         if (data->registry_data.enable_pkg_pwr_tracking_feature)
 461                 data->smu_features[GNLD_PPT].supported = true;
 462 
 463         if (data->registry_data.enable_tdc_limit_feature)
 464                 data->smu_features[GNLD_TDC].supported = true;
 465 
 466         if (data->registry_data.thermal_support)
 467                 data->smu_features[GNLD_THERMAL].supported = true;
 468 
 469         if (data->registry_data.fan_control_support)
 470                 data->smu_features[GNLD_FAN_CONTROL].supported = true;
 471 
 472         if (data->registry_data.fw_ctf_enabled)
 473                 data->smu_features[GNLD_FW_CTF].supported = true;
 474 
 475         if (data->registry_data.avfs_support)
 476                 data->smu_features[GNLD_AVFS].supported = true;
 477 
 478         if (data->registry_data.led_dpm_enabled)
 479                 data->smu_features[GNLD_LED_DISPLAY].supported = true;
 480 
 481         if (data->registry_data.vr1hot_enabled)
 482                 data->smu_features[GNLD_VR1HOT].supported = true;
 483 
 484         if (data->registry_data.vr0hot_enabled)
 485                 data->smu_features[GNLD_VR0HOT].supported = true;
 486 
 487         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
 488         hwmgr->smu_version = smum_get_argument(hwmgr);
 489                 /* ACG firmware has major version 5 */
 490         if ((hwmgr->smu_version & 0xff000000) == 0x5000000)
 491                 data->smu_features[GNLD_ACG].supported = true;
 492         if (data->registry_data.didt_support)
 493                 data->smu_features[GNLD_DIDT].supported = true;
 494 
 495         hw_revision = adev->pdev->revision;
 496         sub_vendor_id = adev->pdev->subsystem_vendor;
 497 
 498         if ((hwmgr->chip_id == 0x6862 ||
 499                 hwmgr->chip_id == 0x6861 ||
 500                 hwmgr->chip_id == 0x6868) &&
 501                 (hw_revision == 0) &&
 502                 (sub_vendor_id != 0x1002))
 503                 data->smu_features[GNLD_PCC_LIMIT].supported = true;
 504 
 505         /* Get the SN to turn into a Unique ID */
 506         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32);
 507         top32 = smum_get_argument(hwmgr);
 508         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32);
 509         bottom32 = smum_get_argument(hwmgr);
 510 
 511         adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
 512 }
 513 
 514 #ifdef PPLIB_VEGA10_EVV_SUPPORT
 515 static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
 516         phm_ppt_v1_voltage_lookup_table *lookup_table,
 517         uint16_t virtual_voltage_id, int32_t *socclk)
 518 {
 519         uint8_t entry_id;
 520         uint8_t voltage_id;
 521         struct phm_ppt_v2_information *table_info =
 522                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
 523 
 524         PP_ASSERT_WITH_CODE(lookup_table->count != 0,
 525                         "Lookup table is empty",
 526                         return -EINVAL);
 527 
 528         /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */
 529         for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) {
 530                 voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd;
 531                 if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id)
 532                         break;
 533         }
 534 
 535         PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count,
 536                         "Can't find requested voltage id in vdd_dep_on_socclk table!",
 537                         return -EINVAL);
 538 
 539         *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk;
 540 
 541         return 0;
 542 }
 543 
 544 #define ATOM_VIRTUAL_VOLTAGE_ID0             0xff01
 545 /**
 546 * Get Leakage VDDC based on leakage ID.
 547 *
 548 * @param    hwmgr  the address of the powerplay hardware manager.
 549 * @return   always 0.
 550 */
 551 static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr)
 552 {
 553         struct vega10_hwmgr *data = hwmgr->backend;
 554         uint16_t vv_id;
 555         uint32_t vddc = 0;
 556         uint16_t i, j;
 557         uint32_t sclk = 0;
 558         struct phm_ppt_v2_information *table_info =
 559                         (struct phm_ppt_v2_information *)hwmgr->pptable;
 560         struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table =
 561                         table_info->vdd_dep_on_socclk;
 562         int result;
 563 
 564         for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) {
 565                 vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
 566 
 567                 if (!vega10_get_socclk_for_voltage_evv(hwmgr,
 568                                 table_info->vddc_lookup_table, vv_id, &sclk)) {
 569                         if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) {
 570                                 for (j = 1; j < socclk_table->count; j++) {
 571                                         if (socclk_table->entries[j].clk == sclk &&
 572                                                         socclk_table->entries[j].cks_enable == 0) {
 573                                                 sclk += 5000;
 574                                                 break;
 575                                         }
 576                                 }
 577                         }
 578 
 579                         PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr,
 580                                         VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc),
 581                                         "Error retrieving EVV voltage value!",
 582                                         continue);
 583 
 584 
 585                         /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
 586                         PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0),
 587                                         "Invalid VDDC value", result = -EINVAL;);
 588 
 589                         /* the voltage should not be zero nor equal to leakage ID */
 590                         if (vddc != 0 && vddc != vv_id) {
 591                                 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100);
 592                                 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
 593                                 data->vddc_leakage.count++;
 594                         }
 595                 }
 596         }
 597 
 598         return 0;
 599 }
 600 
 601 /**
 602  * Change virtual leakage voltage to actual value.
 603  *
 604  * @param     hwmgr  the address of the powerplay hardware manager.
 605  * @param     pointer to changing voltage
 606  * @param     pointer to leakage table
 607  */
 608 static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
 609                 uint16_t *voltage, struct vega10_leakage_voltage *leakage_table)
 610 {
 611         uint32_t index;
 612 
 613         /* search for leakage voltage ID 0xff01 ~ 0xff08 */
 614         for (index = 0; index < leakage_table->count; index++) {
 615                 /* if this voltage matches a leakage voltage ID */
 616                 /* patch with actual leakage voltage */
 617                 if (leakage_table->leakage_id[index] == *voltage) {
 618                         *voltage = leakage_table->actual_voltage[index];
 619                         break;
 620                 }
 621         }
 622 
 623         if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
 624                 pr_info("Voltage value looks like a Leakage ID but it's not patched\n");
 625 }
 626 
 627 /**
 628 * Patch voltage lookup table by EVV leakages.
 629 *
 630 * @param     hwmgr  the address of the powerplay hardware manager.
 631 * @param     pointer to voltage lookup table
 632 * @param     pointer to leakage table
 633 * @return     always 0
 634 */
 635 static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
 636                 phm_ppt_v1_voltage_lookup_table *lookup_table,
 637                 struct vega10_leakage_voltage *leakage_table)
 638 {
 639         uint32_t i;
 640 
 641         for (i = 0; i < lookup_table->count; i++)
 642                 vega10_patch_with_vdd_leakage(hwmgr,
 643                                 &lookup_table->entries[i].us_vdd, leakage_table);
 644 
 645         return 0;
 646 }
 647 
 648 static int vega10_patch_clock_voltage_limits_with_vddc_leakage(
 649                 struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table,
 650                 uint16_t *vddc)
 651 {
 652         vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
 653 
 654         return 0;
 655 }
 656 #endif
 657 
 658 static int vega10_patch_voltage_dependency_tables_with_lookup_table(
 659                 struct pp_hwmgr *hwmgr)
 660 {
 661         uint8_t entry_id, voltage_id;
 662         unsigned i;
 663         struct phm_ppt_v2_information *table_info =
 664                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
 665         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
 666                         table_info->mm_dep_table;
 667         struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
 668                         table_info->vdd_dep_on_mclk;
 669 
 670         for (i = 0; i < 6; i++) {
 671                 struct phm_ppt_v1_clock_voltage_dependency_table *vdt;
 672                 switch (i) {
 673                         case 0: vdt = table_info->vdd_dep_on_socclk; break;
 674                         case 1: vdt = table_info->vdd_dep_on_sclk; break;
 675                         case 2: vdt = table_info->vdd_dep_on_dcefclk; break;
 676                         case 3: vdt = table_info->vdd_dep_on_pixclk; break;
 677                         case 4: vdt = table_info->vdd_dep_on_dispclk; break;
 678                         case 5: vdt = table_info->vdd_dep_on_phyclk; break;
 679                 }
 680 
 681                 for (entry_id = 0; entry_id < vdt->count; entry_id++) {
 682                         voltage_id = vdt->entries[entry_id].vddInd;
 683                         vdt->entries[entry_id].vddc =
 684                                         table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
 685                 }
 686         }
 687 
 688         for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
 689                 voltage_id = mm_table->entries[entry_id].vddcInd;
 690                 mm_table->entries[entry_id].vddc =
 691                         table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
 692         }
 693 
 694         for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
 695                 voltage_id = mclk_table->entries[entry_id].vddInd;
 696                 mclk_table->entries[entry_id].vddc =
 697                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
 698                 voltage_id = mclk_table->entries[entry_id].vddciInd;
 699                 mclk_table->entries[entry_id].vddci =
 700                                 table_info->vddci_lookup_table->entries[voltage_id].us_vdd;
 701                 voltage_id = mclk_table->entries[entry_id].mvddInd;
 702                 mclk_table->entries[entry_id].mvdd =
 703                                 table_info->vddmem_lookup_table->entries[voltage_id].us_vdd;
 704         }
 705 
 706 
 707         return 0;
 708 
 709 }
 710 
 711 static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr,
 712                 struct phm_ppt_v1_voltage_lookup_table *lookup_table)
 713 {
 714         uint32_t table_size, i, j;
 715         struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
 716 
 717         PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count,
 718                 "Lookup table is empty", return -EINVAL);
 719 
 720         table_size = lookup_table->count;
 721 
 722         /* Sorting voltages */
 723         for (i = 0; i < table_size - 1; i++) {
 724                 for (j = i + 1; j > 0; j--) {
 725                         if (lookup_table->entries[j].us_vdd <
 726                                         lookup_table->entries[j - 1].us_vdd) {
 727                                 tmp_voltage_lookup_record = lookup_table->entries[j - 1];
 728                                 lookup_table->entries[j - 1] = lookup_table->entries[j];
 729                                 lookup_table->entries[j] = tmp_voltage_lookup_record;
 730                         }
 731                 }
 732         }
 733 
 734         return 0;
 735 }
 736 
 737 static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr)
 738 {
 739         int result = 0;
 740         int tmp_result;
 741         struct phm_ppt_v2_information *table_info =
 742                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
 743 #ifdef PPLIB_VEGA10_EVV_SUPPORT
 744         struct vega10_hwmgr *data = hwmgr->backend;
 745 
 746         tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr,
 747                         table_info->vddc_lookup_table, &(data->vddc_leakage));
 748         if (tmp_result)
 749                 result = tmp_result;
 750 
 751         tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
 752                         &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
 753         if (tmp_result)
 754                 result = tmp_result;
 755 #endif
 756 
 757         tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
 758         if (tmp_result)
 759                 result = tmp_result;
 760 
 761         tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
 762         if (tmp_result)
 763                 result = tmp_result;
 764 
 765         return result;
 766 }
 767 
 768 static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
 769 {
 770         struct phm_ppt_v2_information *table_info =
 771                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
 772         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
 773                         table_info->vdd_dep_on_socclk;
 774         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
 775                         table_info->vdd_dep_on_mclk;
 776 
 777         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table,
 778                 "VDD dependency on SCLK table is missing. This table is mandatory", return -EINVAL);
 779         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
 780                 "VDD dependency on SCLK table is empty. This table is mandatory", return -EINVAL);
 781 
 782         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table,
 783                 "VDD dependency on MCLK table is missing.  This table is mandatory", return -EINVAL);
 784         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
 785                 "VDD dependency on MCLK table is empty.  This table is mandatory", return -EINVAL);
 786 
 787         table_info->max_clock_voltage_on_ac.sclk =
 788                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
 789         table_info->max_clock_voltage_on_ac.mclk =
 790                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
 791         table_info->max_clock_voltage_on_ac.vddc =
 792                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
 793         table_info->max_clock_voltage_on_ac.vddci =
 794                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
 795 
 796         hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
 797                 table_info->max_clock_voltage_on_ac.sclk;
 798         hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
 799                 table_info->max_clock_voltage_on_ac.mclk;
 800         hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
 801                 table_info->max_clock_voltage_on_ac.vddc;
 802         hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
 803                 table_info->max_clock_voltage_on_ac.vddci;
 804 
 805         return 0;
 806 }
 807 
 808 static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 809 {
 810         kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
 811         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
 812 
 813         kfree(hwmgr->backend);
 814         hwmgr->backend = NULL;
 815 
 816         return 0;
 817 }
 818 
 819 static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 820 {
 821         int result = 0;
 822         struct vega10_hwmgr *data;
 823         uint32_t config_telemetry = 0;
 824         struct pp_atomfwctrl_voltage_table vol_table;
 825         struct amdgpu_device *adev = hwmgr->adev;
 826 
 827         data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
 828         if (data == NULL)
 829                 return -ENOMEM;
 830 
 831         hwmgr->backend = data;
 832 
 833         hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
 834         hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 835         hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 836 
 837         vega10_set_default_registry_data(hwmgr);
 838         data->disable_dpm_mask = 0xff;
 839 
 840         /* need to set voltage control types before EVV patching */
 841         data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
 842         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE;
 843         data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE;
 844 
 845         /* VDDCR_SOC */
 846         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
 847                         VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
 848                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
 849                                 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2,
 850                                 &vol_table)) {
 851                         config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) |
 852                                         (vol_table.telemetry_offset & 0xff);
 853                         data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
 854                 }
 855         } else {
 856                 kfree(hwmgr->backend);
 857                 hwmgr->backend = NULL;
 858                 PP_ASSERT_WITH_CODE(false,
 859                                 "VDDCR_SOC is not SVID2!",
 860                                 return -1);
 861         }
 862 
 863         /* MVDDC */
 864         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
 865                         VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) {
 866                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
 867                                 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2,
 868                                 &vol_table)) {
 869                         config_telemetry |=
 870                                         ((vol_table.telemetry_slope << 24) & 0xff000000) |
 871                                         ((vol_table.telemetry_offset << 16) & 0xff0000);
 872                         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
 873                 }
 874         }
 875 
 876          /* VDDCI_MEM */
 877         if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) {
 878                 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
 879                                 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
 880                         data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO;
 881         }
 882 
 883         data->config_telemetry = config_telemetry;
 884 
 885         vega10_set_features_platform_caps(hwmgr);
 886 
 887         vega10_init_dpm_defaults(hwmgr);
 888 
 889 #ifdef PPLIB_VEGA10_EVV_SUPPORT
 890         /* Get leakage voltage based on leakage ID. */
 891         PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr),
 892                         "Get EVV Voltage Failed.  Abort Driver loading!",
 893                         return -1);
 894 #endif
 895 
 896         /* Patch our voltage dependency table with actual leakage voltage
 897          * We need to perform leakage translation before it's used by other functions
 898          */
 899         vega10_complete_dependency_tables(hwmgr);
 900 
 901         /* Parse pptable data read from VBIOS */
 902         vega10_set_private_data_based_on_pptable(hwmgr);
 903 
 904         data->is_tlu_enabled = false;
 905 
 906         hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
 907                         VEGA10_MAX_HARDWARE_POWERLEVELS;
 908         hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
 909         hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
 910 
 911         hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
 912         /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
 913         hwmgr->platform_descriptor.clockStep.engineClock = 500;
 914         hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 915 
 916         data->total_active_cus = adev->gfx.cu_info.number;
 917         /* Setup default Overdrive Fan control settings */
 918         data->odn_fan_table.target_fan_speed =
 919                         hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
 920         data->odn_fan_table.target_temperature =
 921                         hwmgr->thermal_controller.
 922                         advanceFanControlParameters.ucTargetTemperature;
 923         data->odn_fan_table.min_performance_clock =
 924                         hwmgr->thermal_controller.advanceFanControlParameters.
 925                         ulMinFanSCLKAcousticLimit;
 926         data->odn_fan_table.min_fan_limit =
 927                         hwmgr->thermal_controller.
 928                         advanceFanControlParameters.usFanPWMMinLimit *
 929                         hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
 930 
 931         data->mem_channels = (RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0) &
 932                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
 933                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
 934         PP_ASSERT_WITH_CODE(data->mem_channels < ARRAY_SIZE(channel_number),
 935                         "Mem Channel Index Exceeded maximum!",
 936                         return -EINVAL);
 937 
 938         return result;
 939 }
 940 
 941 static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr)
 942 {
 943         struct vega10_hwmgr *data = hwmgr->backend;
 944 
 945         data->low_sclk_interrupt_threshold = 0;
 946 
 947         return 0;
 948 }
 949 
 950 static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
 951 {
 952         struct vega10_hwmgr *data = hwmgr->backend;
 953         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
 954 
 955         struct pp_atomfwctrl_voltage_table table;
 956         uint8_t i, j;
 957         uint32_t mask = 0;
 958         uint32_t tmp;
 959         int32_t ret = 0;
 960 
 961         ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM,
 962                                                 VOLTAGE_OBJ_GPIO_LUT, &table);
 963 
 964         if (!ret) {
 965                 tmp = table.mask_low;
 966                 for (i = 0, j = 0; i < 32; i++) {
 967                         if (tmp & 1) {
 968                                 mask |= (uint32_t)(i << (8 * j));
 969                                 if (++j >= 3)
 970                                         break;
 971                         }
 972                         tmp >>= 1;
 973                 }
 974         }
 975 
 976         pp_table->LedPin0 = (uint8_t)(mask & 0xff);
 977         pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff);
 978         pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff);
 979         return 0;
 980 }
 981 
 982 static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr)
 983 {
 984         PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr),
 985                         "Failed to init sclk threshold!",
 986                         return -EINVAL);
 987 
 988         PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr),
 989                         "Failed to set up led dpm config!",
 990                         return -EINVAL);
 991 
 992         smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_NumOfDisplays, 0);
 993 
 994         return 0;
 995 }
 996 
 997 /**
 998 * Remove repeated voltage values and create table with unique values.
 999 *
1000 * @param    hwmgr  the address of the powerplay hardware manager.
1001 * @param    vol_table  the pointer to changing voltage table
1002 * @return    0 in success
1003 */
1004 
1005 static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr,
1006                 struct pp_atomfwctrl_voltage_table *vol_table)
1007 {
1008         uint32_t i, j;
1009         uint16_t vvalue;
1010         bool found = false;
1011         struct pp_atomfwctrl_voltage_table *table;
1012 
1013         PP_ASSERT_WITH_CODE(vol_table,
1014                         "Voltage Table empty.", return -EINVAL);
1015         table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table),
1016                         GFP_KERNEL);
1017 
1018         if (!table)
1019                 return -ENOMEM;
1020 
1021         table->mask_low = vol_table->mask_low;
1022         table->phase_delay = vol_table->phase_delay;
1023 
1024         for (i = 0; i < vol_table->count; i++) {
1025                 vvalue = vol_table->entries[i].value;
1026                 found = false;
1027 
1028                 for (j = 0; j < table->count; j++) {
1029                         if (vvalue == table->entries[j].value) {
1030                                 found = true;
1031                                 break;
1032                         }
1033                 }
1034 
1035                 if (!found) {
1036                         table->entries[table->count].value = vvalue;
1037                         table->entries[table->count].smio_low =
1038                                         vol_table->entries[i].smio_low;
1039                         table->count++;
1040                 }
1041         }
1042 
1043         memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table));
1044         kfree(table);
1045 
1046         return 0;
1047 }
1048 
1049 static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
1050                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1051                 struct pp_atomfwctrl_voltage_table *vol_table)
1052 {
1053         int i;
1054 
1055         PP_ASSERT_WITH_CODE(dep_table->count,
1056                         "Voltage Dependency Table empty.",
1057                         return -EINVAL);
1058 
1059         vol_table->mask_low = 0;
1060         vol_table->phase_delay = 0;
1061         vol_table->count = dep_table->count;
1062 
1063         for (i = 0; i < vol_table->count; i++) {
1064                 vol_table->entries[i].value = dep_table->entries[i].mvdd;
1065                 vol_table->entries[i].smio_low = 0;
1066         }
1067 
1068         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr,
1069                         vol_table),
1070                         "Failed to trim MVDD Table!",
1071                         return -1);
1072 
1073         return 0;
1074 }
1075 
1076 static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr,
1077                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1078                 struct pp_atomfwctrl_voltage_table *vol_table)
1079 {
1080         uint32_t i;
1081 
1082         PP_ASSERT_WITH_CODE(dep_table->count,
1083                         "Voltage Dependency Table empty.",
1084                         return -EINVAL);
1085 
1086         vol_table->mask_low = 0;
1087         vol_table->phase_delay = 0;
1088         vol_table->count = dep_table->count;
1089 
1090         for (i = 0; i < dep_table->count; i++) {
1091                 vol_table->entries[i].value = dep_table->entries[i].vddci;
1092                 vol_table->entries[i].smio_low = 0;
1093         }
1094 
1095         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table),
1096                         "Failed to trim VDDCI table.",
1097                         return -1);
1098 
1099         return 0;
1100 }
1101 
1102 static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr,
1103                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1104                 struct pp_atomfwctrl_voltage_table *vol_table)
1105 {
1106         int i;
1107 
1108         PP_ASSERT_WITH_CODE(dep_table->count,
1109                         "Voltage Dependency Table empty.",
1110                         return -EINVAL);
1111 
1112         vol_table->mask_low = 0;
1113         vol_table->phase_delay = 0;
1114         vol_table->count = dep_table->count;
1115 
1116         for (i = 0; i < vol_table->count; i++) {
1117                 vol_table->entries[i].value = dep_table->entries[i].vddc;
1118                 vol_table->entries[i].smio_low = 0;
1119         }
1120 
1121         return 0;
1122 }
1123 
1124 /* ---- Voltage Tables ----
1125  * If the voltage table would be bigger than
1126  * what will fit into the state table on
1127  * the SMC keep only the higher entries.
1128  */
1129 static void vega10_trim_voltage_table_to_fit_state_table(
1130                 struct pp_hwmgr *hwmgr,
1131                 uint32_t max_vol_steps,
1132                 struct pp_atomfwctrl_voltage_table *vol_table)
1133 {
1134         unsigned int i, diff;
1135 
1136         if (vol_table->count <= max_vol_steps)
1137                 return;
1138 
1139         diff = vol_table->count - max_vol_steps;
1140 
1141         for (i = 0; i < max_vol_steps; i++)
1142                 vol_table->entries[i] = vol_table->entries[i + diff];
1143 
1144         vol_table->count = max_vol_steps;
1145 }
1146 
1147 /**
1148 * Create Voltage Tables.
1149 *
1150 * @param    hwmgr  the address of the powerplay hardware manager.
1151 * @return   always 0
1152 */
1153 static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr)
1154 {
1155         struct vega10_hwmgr *data = hwmgr->backend;
1156         struct phm_ppt_v2_information *table_info =
1157                         (struct phm_ppt_v2_information *)hwmgr->pptable;
1158         int result;
1159 
1160         if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1161                         data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1162                 result = vega10_get_mvdd_voltage_table(hwmgr,
1163                                 table_info->vdd_dep_on_mclk,
1164                                 &(data->mvdd_voltage_table));
1165                 PP_ASSERT_WITH_CODE(!result,
1166                                 "Failed to retrieve MVDDC table!",
1167                                 return result);
1168         }
1169 
1170         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1171                 result = vega10_get_vddci_voltage_table(hwmgr,
1172                                 table_info->vdd_dep_on_mclk,
1173                                 &(data->vddci_voltage_table));
1174                 PP_ASSERT_WITH_CODE(!result,
1175                                 "Failed to retrieve VDDCI_MEM table!",
1176                                 return result);
1177         }
1178 
1179         if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1180                         data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1181                 result = vega10_get_vdd_voltage_table(hwmgr,
1182                                 table_info->vdd_dep_on_sclk,
1183                                 &(data->vddc_voltage_table));
1184                 PP_ASSERT_WITH_CODE(!result,
1185                                 "Failed to retrieve VDDCR_SOC table!",
1186                                 return result);
1187         }
1188 
1189         PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16,
1190                         "Too many voltage values for VDDC. Trimming to fit state table.",
1191                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1192                                         16, &(data->vddc_voltage_table)));
1193 
1194         PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16,
1195                         "Too many voltage values for VDDCI. Trimming to fit state table.",
1196                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1197                                         16, &(data->vddci_voltage_table)));
1198 
1199         PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16,
1200                         "Too many voltage values for MVDD. Trimming to fit state table.",
1201                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1202                                         16, &(data->mvdd_voltage_table)));
1203 
1204 
1205         return 0;
1206 }
1207 
1208 /*
1209  * @fn vega10_init_dpm_state
1210  * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
1211  *
1212  * @param    dpm_state - the address of the DPM Table to initiailize.
1213  * @return   None.
1214  */
1215 static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state)
1216 {
1217         dpm_state->soft_min_level = 0xff;
1218         dpm_state->soft_max_level = 0xff;
1219         dpm_state->hard_min_level = 0xff;
1220         dpm_state->hard_max_level = 0xff;
1221 }
1222 
1223 static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr,
1224                 struct vega10_single_dpm_table *dpm_table,
1225                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1226 {
1227         int i;
1228 
1229         dpm_table->count = 0;
1230 
1231         for (i = 0; i < dep_table->count; i++) {
1232                 if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
1233                                 dep_table->entries[i].clk) {
1234                         dpm_table->dpm_levels[dpm_table->count].value =
1235                                         dep_table->entries[i].clk;
1236                         dpm_table->dpm_levels[dpm_table->count].enabled = true;
1237                         dpm_table->count++;
1238                 }
1239         }
1240 }
1241 static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
1242 {
1243         struct vega10_hwmgr *data = hwmgr->backend;
1244         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
1245         struct phm_ppt_v2_information *table_info =
1246                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1247         struct phm_ppt_v1_pcie_table *bios_pcie_table =
1248                         table_info->pcie_table;
1249         uint32_t i;
1250 
1251         PP_ASSERT_WITH_CODE(bios_pcie_table->count,
1252                         "Incorrect number of PCIE States from VBIOS!",
1253                         return -1);
1254 
1255         for (i = 0; i < NUM_LINK_LEVELS; i++) {
1256                 if (data->registry_data.pcieSpeedOverride)
1257                         pcie_table->pcie_gen[i] =
1258                                         data->registry_data.pcieSpeedOverride;
1259                 else
1260                         pcie_table->pcie_gen[i] =
1261                                         bios_pcie_table->entries[i].gen_speed;
1262 
1263                 if (data->registry_data.pcieLaneOverride)
1264                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1265                                         data->registry_data.pcieLaneOverride);
1266                 else
1267                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1268                                                         bios_pcie_table->entries[i].lane_width);
1269                 if (data->registry_data.pcieClockOverride)
1270                         pcie_table->lclk[i] =
1271                                         data->registry_data.pcieClockOverride;
1272                 else
1273                         pcie_table->lclk[i] =
1274                                         bios_pcie_table->entries[i].pcie_sclk;
1275         }
1276 
1277         pcie_table->count = NUM_LINK_LEVELS;
1278 
1279         return 0;
1280 }
1281 
1282 /*
1283  * This function is to initialize all DPM state tables
1284  * for SMU based on the dependency table.
1285  * Dynamic state patching function will then trim these
1286  * state tables to the allowed range based
1287  * on the power policy or external client requests,
1288  * such as UVD request, etc.
1289  */
1290 static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1291 {
1292         struct vega10_hwmgr *data = hwmgr->backend;
1293         struct phm_ppt_v2_information *table_info =
1294                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1295         struct vega10_single_dpm_table *dpm_table;
1296         uint32_t i;
1297 
1298         struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table =
1299                         table_info->vdd_dep_on_socclk;
1300         struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table =
1301                         table_info->vdd_dep_on_sclk;
1302         struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
1303                         table_info->vdd_dep_on_mclk;
1304         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table =
1305                         table_info->mm_dep_table;
1306         struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table =
1307                         table_info->vdd_dep_on_dcefclk;
1308         struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table =
1309                         table_info->vdd_dep_on_pixclk;
1310         struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table =
1311                         table_info->vdd_dep_on_dispclk;
1312         struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table =
1313                         table_info->vdd_dep_on_phyclk;
1314 
1315         PP_ASSERT_WITH_CODE(dep_soc_table,
1316                         "SOCCLK dependency table is missing. This table is mandatory",
1317                         return -EINVAL);
1318         PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1,
1319                         "SOCCLK dependency table is empty. This table is mandatory",
1320                         return -EINVAL);
1321 
1322         PP_ASSERT_WITH_CODE(dep_gfx_table,
1323                         "GFXCLK dependency table is missing. This table is mandatory",
1324                         return -EINVAL);
1325         PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1,
1326                         "GFXCLK dependency table is empty. This table is mandatory",
1327                         return -EINVAL);
1328 
1329         PP_ASSERT_WITH_CODE(dep_mclk_table,
1330                         "MCLK dependency table is missing. This table is mandatory",
1331                         return -EINVAL);
1332         PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
1333                         "MCLK dependency table has to have is missing. This table is mandatory",
1334                         return -EINVAL);
1335 
1336         /* Initialize Sclk DPM table based on allow Sclk values */
1337         dpm_table = &(data->dpm_table.soc_table);
1338         vega10_setup_default_single_dpm_table(hwmgr,
1339                         dpm_table,
1340                         dep_soc_table);
1341 
1342         vega10_init_dpm_state(&(dpm_table->dpm_state));
1343 
1344         dpm_table = &(data->dpm_table.gfx_table);
1345         vega10_setup_default_single_dpm_table(hwmgr,
1346                         dpm_table,
1347                         dep_gfx_table);
1348         if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
1349                 hwmgr->platform_descriptor.overdriveLimit.engineClock =
1350                                         dpm_table->dpm_levels[dpm_table->count-1].value;
1351         vega10_init_dpm_state(&(dpm_table->dpm_state));
1352 
1353         /* Initialize Mclk DPM table based on allow Mclk values */
1354         data->dpm_table.mem_table.count = 0;
1355         dpm_table = &(data->dpm_table.mem_table);
1356         vega10_setup_default_single_dpm_table(hwmgr,
1357                         dpm_table,
1358                         dep_mclk_table);
1359         if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
1360                 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1361                                         dpm_table->dpm_levels[dpm_table->count-1].value;
1362         vega10_init_dpm_state(&(dpm_table->dpm_state));
1363 
1364         data->dpm_table.eclk_table.count = 0;
1365         dpm_table = &(data->dpm_table.eclk_table);
1366         for (i = 0; i < dep_mm_table->count; i++) {
1367                 if (i == 0 || dpm_table->dpm_levels
1368                                 [dpm_table->count - 1].value <=
1369                                                 dep_mm_table->entries[i].eclk) {
1370                         dpm_table->dpm_levels[dpm_table->count].value =
1371                                         dep_mm_table->entries[i].eclk;
1372                         dpm_table->dpm_levels[dpm_table->count].enabled =
1373                                         (i == 0) ? true : false;
1374                         dpm_table->count++;
1375                 }
1376         }
1377         vega10_init_dpm_state(&(dpm_table->dpm_state));
1378 
1379         data->dpm_table.vclk_table.count = 0;
1380         data->dpm_table.dclk_table.count = 0;
1381         dpm_table = &(data->dpm_table.vclk_table);
1382         for (i = 0; i < dep_mm_table->count; i++) {
1383                 if (i == 0 || dpm_table->dpm_levels
1384                                 [dpm_table->count - 1].value <=
1385                                                 dep_mm_table->entries[i].vclk) {
1386                         dpm_table->dpm_levels[dpm_table->count].value =
1387                                         dep_mm_table->entries[i].vclk;
1388                         dpm_table->dpm_levels[dpm_table->count].enabled =
1389                                         (i == 0) ? true : false;
1390                         dpm_table->count++;
1391                 }
1392         }
1393         vega10_init_dpm_state(&(dpm_table->dpm_state));
1394 
1395         dpm_table = &(data->dpm_table.dclk_table);
1396         for (i = 0; i < dep_mm_table->count; i++) {
1397                 if (i == 0 || dpm_table->dpm_levels
1398                                 [dpm_table->count - 1].value <=
1399                                                 dep_mm_table->entries[i].dclk) {
1400                         dpm_table->dpm_levels[dpm_table->count].value =
1401                                         dep_mm_table->entries[i].dclk;
1402                         dpm_table->dpm_levels[dpm_table->count].enabled =
1403                                         (i == 0) ? true : false;
1404                         dpm_table->count++;
1405                 }
1406         }
1407         vega10_init_dpm_state(&(dpm_table->dpm_state));
1408 
1409         /* Assume there is no headless Vega10 for now */
1410         dpm_table = &(data->dpm_table.dcef_table);
1411         vega10_setup_default_single_dpm_table(hwmgr,
1412                         dpm_table,
1413                         dep_dcef_table);
1414 
1415         vega10_init_dpm_state(&(dpm_table->dpm_state));
1416 
1417         dpm_table = &(data->dpm_table.pixel_table);
1418         vega10_setup_default_single_dpm_table(hwmgr,
1419                         dpm_table,
1420                         dep_pix_table);
1421 
1422         vega10_init_dpm_state(&(dpm_table->dpm_state));
1423 
1424         dpm_table = &(data->dpm_table.display_table);
1425         vega10_setup_default_single_dpm_table(hwmgr,
1426                         dpm_table,
1427                         dep_disp_table);
1428 
1429         vega10_init_dpm_state(&(dpm_table->dpm_state));
1430 
1431         dpm_table = &(data->dpm_table.phy_table);
1432         vega10_setup_default_single_dpm_table(hwmgr,
1433                         dpm_table,
1434                         dep_phy_table);
1435 
1436         vega10_init_dpm_state(&(dpm_table->dpm_state));
1437 
1438         vega10_setup_default_pcie_table(hwmgr);
1439 
1440         /* Zero out the saved copy of the CUSTOM profile
1441          * This will be checked when trying to set the profile
1442          * and will require that new values be passed in
1443          */
1444         data->custom_profile_mode[0] = 0;
1445         data->custom_profile_mode[1] = 0;
1446         data->custom_profile_mode[2] = 0;
1447         data->custom_profile_mode[3] = 0;
1448 
1449         /* save a copy of the default DPM table */
1450         memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1451                         sizeof(struct vega10_dpm_table));
1452 
1453         return 0;
1454 }
1455 
1456 /*
1457  * @fn vega10_populate_ulv_state
1458  * @brief Function to provide parameters for Utral Low Voltage state to SMC.
1459  *
1460  * @param    hwmgr - the address of the hardware manager.
1461  * @return   Always 0.
1462  */
1463 static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
1464 {
1465         struct vega10_hwmgr *data = hwmgr->backend;
1466         struct phm_ppt_v2_information *table_info =
1467                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1468 
1469         data->smc_state_table.pp_table.UlvOffsetVid =
1470                         (uint8_t)table_info->us_ulv_voltage_offset;
1471 
1472         data->smc_state_table.pp_table.UlvSmnclkDid =
1473                         (uint8_t)(table_info->us_ulv_smnclk_did);
1474         data->smc_state_table.pp_table.UlvMp1clkDid =
1475                         (uint8_t)(table_info->us_ulv_mp1clk_did);
1476         data->smc_state_table.pp_table.UlvGfxclkBypass =
1477                         (uint8_t)(table_info->us_ulv_gfxclk_bypass);
1478         data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 =
1479                         (uint8_t)(data->vddc_voltage_table.psi0_enable);
1480         data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 =
1481                         (uint8_t)(data->vddc_voltage_table.psi1_enable);
1482 
1483         return 0;
1484 }
1485 
1486 static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
1487                 uint32_t lclock, uint8_t *curr_lclk_did)
1488 {
1489         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1490 
1491         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1492                         hwmgr,
1493                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1494                         lclock, &dividers),
1495                         "Failed to get LCLK clock settings from VBIOS!",
1496                         return -1);
1497 
1498         *curr_lclk_did = dividers.ulDid;
1499 
1500         return 0;
1501 }
1502 
1503 static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
1504 {
1505         int result = -1;
1506         struct vega10_hwmgr *data = hwmgr->backend;
1507         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1508         struct vega10_pcie_table *pcie_table =
1509                         &(data->dpm_table.pcie_table);
1510         uint32_t i, j;
1511 
1512         for (i = 0; i < pcie_table->count; i++) {
1513                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i];
1514                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i];
1515 
1516                 result = vega10_populate_single_lclk_level(hwmgr,
1517                                 pcie_table->lclk[i], &(pp_table->LclkDid[i]));
1518                 if (result) {
1519                         pr_info("Populate LClock Level %d Failed!\n", i);
1520                         return result;
1521                 }
1522         }
1523 
1524         j = i - 1;
1525         while (i < NUM_LINK_LEVELS) {
1526                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j];
1527                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j];
1528 
1529                 result = vega10_populate_single_lclk_level(hwmgr,
1530                                 pcie_table->lclk[j], &(pp_table->LclkDid[i]));
1531                 if (result) {
1532                         pr_info("Populate LClock Level %d Failed!\n", i);
1533                         return result;
1534                 }
1535                 i++;
1536         }
1537 
1538         return result;
1539 }
1540 
1541 /**
1542 * Populates single SMC GFXSCLK structure using the provided engine clock
1543 *
1544 * @param    hwmgr      the address of the hardware manager
1545 * @param    gfx_clock  the GFX clock to use to populate the structure.
1546 * @param    current_gfxclk_level  location in PPTable for the SMC GFXCLK structure.
1547 */
1548 
1549 static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
1550                 uint32_t gfx_clock, PllSetting_t *current_gfxclk_level,
1551                 uint32_t *acg_freq)
1552 {
1553         struct phm_ppt_v2_information *table_info =
1554                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1555         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk;
1556         struct vega10_hwmgr *data = hwmgr->backend;
1557         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1558         uint32_t gfx_max_clock =
1559                         hwmgr->platform_descriptor.overdriveLimit.engineClock;
1560         uint32_t i = 0;
1561 
1562         if (hwmgr->od_enabled)
1563                 dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1564                                                 &(data->odn_dpm_table.vdd_dep_on_sclk);
1565         else
1566                 dep_on_sclk = table_info->vdd_dep_on_sclk;
1567 
1568         PP_ASSERT_WITH_CODE(dep_on_sclk,
1569                         "Invalid SOC_VDD-GFX_CLK Dependency Table!",
1570                         return -EINVAL);
1571 
1572         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK)
1573                 gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock;
1574         else {
1575                 for (i = 0; i < dep_on_sclk->count; i++) {
1576                         if (dep_on_sclk->entries[i].clk == gfx_clock)
1577                                 break;
1578                 }
1579                 PP_ASSERT_WITH_CODE(dep_on_sclk->count > i,
1580                                 "Cannot find gfx_clk in SOC_VDD-GFX_CLK!",
1581                                 return -EINVAL);
1582         }
1583 
1584         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1585                         COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK,
1586                         gfx_clock, &dividers),
1587                         "Failed to get GFX Clock settings from VBIOS!",
1588                         return -EINVAL);
1589 
1590         /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */
1591         current_gfxclk_level->FbMult =
1592                         cpu_to_le32(dividers.ulPll_fb_mult);
1593         /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
1594         current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
1595         current_gfxclk_level->SsFbMult =
1596                         cpu_to_le32(dividers.ulPll_ss_fbsmult);
1597         current_gfxclk_level->SsSlewFrac =
1598                         cpu_to_le16(dividers.usPll_ss_slew_frac);
1599         current_gfxclk_level->Did = (uint8_t)(dividers.ulDid);
1600 
1601         *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */
1602 
1603         return 0;
1604 }
1605 
1606 /**
1607  * @brief Populates single SMC SOCCLK structure using the provided clock.
1608  *
1609  * @param    hwmgr - the address of the hardware manager.
1610  * @param    soc_clock - the SOC clock to use to populate the structure.
1611  * @param    current_socclk_level - location in PPTable for the SMC SOCCLK structure.
1612  * @return   0 on success..
1613  */
1614 static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
1615                 uint32_t soc_clock, uint8_t *current_soc_did,
1616                 uint8_t *current_vol_index)
1617 {
1618         struct vega10_hwmgr *data = hwmgr->backend;
1619         struct phm_ppt_v2_information *table_info =
1620                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1621         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc;
1622         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1623         uint32_t i;
1624 
1625         if (hwmgr->od_enabled) {
1626                 dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1627                                                 &data->odn_dpm_table.vdd_dep_on_socclk;
1628                 for (i = 0; i < dep_on_soc->count; i++) {
1629                         if (dep_on_soc->entries[i].clk >= soc_clock)
1630                                 break;
1631                 }
1632         } else {
1633                 dep_on_soc = table_info->vdd_dep_on_socclk;
1634                 for (i = 0; i < dep_on_soc->count; i++) {
1635                         if (dep_on_soc->entries[i].clk == soc_clock)
1636                                 break;
1637                 }
1638         }
1639 
1640         PP_ASSERT_WITH_CODE(dep_on_soc->count > i,
1641                         "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table",
1642                         return -EINVAL);
1643 
1644         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1645                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1646                         soc_clock, &dividers),
1647                         "Failed to get SOC Clock settings from VBIOS!",
1648                         return -EINVAL);
1649 
1650         *current_soc_did = (uint8_t)dividers.ulDid;
1651         *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
1652         return 0;
1653 }
1654 
1655 /**
1656 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
1657 *
1658 * @param    hwmgr      the address of the hardware manager
1659 */
1660 static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
1661 {
1662         struct vega10_hwmgr *data = hwmgr->backend;
1663         struct phm_ppt_v2_information *table_info =
1664                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1665         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1666         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
1667         int result = 0;
1668         uint32_t i, j;
1669 
1670         for (i = 0; i < dpm_table->count; i++) {
1671                 result = vega10_populate_single_gfx_level(hwmgr,
1672                                 dpm_table->dpm_levels[i].value,
1673                                 &(pp_table->GfxclkLevel[i]),
1674                                 &(pp_table->AcgFreqTable[i]));
1675                 if (result)
1676                         return result;
1677         }
1678 
1679         j = i - 1;
1680         while (i < NUM_GFXCLK_DPM_LEVELS) {
1681                 result = vega10_populate_single_gfx_level(hwmgr,
1682                                 dpm_table->dpm_levels[j].value,
1683                                 &(pp_table->GfxclkLevel[i]),
1684                                 &(pp_table->AcgFreqTable[i]));
1685                 if (result)
1686                         return result;
1687                 i++;
1688         }
1689 
1690         pp_table->GfxclkSlewRate =
1691                         cpu_to_le16(table_info->us_gfxclk_slew_rate);
1692 
1693         dpm_table = &(data->dpm_table.soc_table);
1694         for (i = 0; i < dpm_table->count; i++) {
1695                 result = vega10_populate_single_soc_level(hwmgr,
1696                                 dpm_table->dpm_levels[i].value,
1697                                 &(pp_table->SocclkDid[i]),
1698                                 &(pp_table->SocDpmVoltageIndex[i]));
1699                 if (result)
1700                         return result;
1701         }
1702 
1703         j = i - 1;
1704         while (i < NUM_SOCCLK_DPM_LEVELS) {
1705                 result = vega10_populate_single_soc_level(hwmgr,
1706                                 dpm_table->dpm_levels[j].value,
1707                                 &(pp_table->SocclkDid[i]),
1708                                 &(pp_table->SocDpmVoltageIndex[i]));
1709                 if (result)
1710                         return result;
1711                 i++;
1712         }
1713 
1714         return result;
1715 }
1716 
1717 static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr)
1718 {
1719         struct vega10_hwmgr *data = hwmgr->backend;
1720         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1721         struct phm_ppt_v2_information *table_info = hwmgr->pptable;
1722         struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
1723 
1724         uint8_t soc_vid = 0;
1725         uint32_t i, max_vddc_level;
1726 
1727         if (hwmgr->od_enabled)
1728                 vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table;
1729         else
1730                 vddc_lookup_table = table_info->vddc_lookup_table;
1731 
1732         max_vddc_level = vddc_lookup_table->count;
1733         for (i = 0; i < max_vddc_level; i++) {
1734                 soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd);
1735                 pp_table->SocVid[i] = soc_vid;
1736         }
1737         while (i < MAX_REGULAR_DPM_NUMBER) {
1738                 pp_table->SocVid[i] = soc_vid;
1739                 i++;
1740         }
1741 }
1742 
1743 /**
1744  * @brief Populates single SMC GFXCLK structure using the provided clock.
1745  *
1746  * @param    hwmgr - the address of the hardware manager.
1747  * @param    mem_clock - the memory clock to use to populate the structure.
1748  * @return   0 on success..
1749  */
1750 static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
1751                 uint32_t mem_clock, uint8_t *current_mem_vid,
1752                 PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind)
1753 {
1754         struct vega10_hwmgr *data = hwmgr->backend;
1755         struct phm_ppt_v2_information *table_info =
1756                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1757         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk;
1758         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1759         uint32_t mem_max_clock =
1760                         hwmgr->platform_descriptor.overdriveLimit.memoryClock;
1761         uint32_t i = 0;
1762 
1763         if (hwmgr->od_enabled)
1764                 dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1765                                         &data->odn_dpm_table.vdd_dep_on_mclk;
1766         else
1767                 dep_on_mclk = table_info->vdd_dep_on_mclk;
1768 
1769         PP_ASSERT_WITH_CODE(dep_on_mclk,
1770                         "Invalid SOC_VDD-UCLK Dependency Table!",
1771                         return -EINVAL);
1772 
1773         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
1774                 mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock;
1775         } else {
1776                 for (i = 0; i < dep_on_mclk->count; i++) {
1777                         if (dep_on_mclk->entries[i].clk == mem_clock)
1778                                 break;
1779                 }
1780                 PP_ASSERT_WITH_CODE(dep_on_mclk->count > i,
1781                                 "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!",
1782                                 return -EINVAL);
1783         }
1784 
1785         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1786                         hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, &dividers),
1787                         "Failed to get UCLK settings from VBIOS!",
1788                         return -1);
1789 
1790         *current_mem_vid =
1791                         (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd));
1792         *current_mem_soc_vind =
1793                         (uint8_t)(dep_on_mclk->entries[i].vddInd);
1794         current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult);
1795         current_memclk_level->Did = (uint8_t)(dividers.ulDid);
1796 
1797         PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1,
1798                         "Invalid Divider ID!",
1799                         return -EINVAL);
1800 
1801         return 0;
1802 }
1803 
1804 /**
1805  * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states.
1806  *
1807  * @param    pHwMgr - the address of the hardware manager.
1808  * @return   PP_Result_OK on success.
1809  */
1810 static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1811 {
1812         struct vega10_hwmgr *data = hwmgr->backend;
1813         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1814         struct vega10_single_dpm_table *dpm_table =
1815                         &(data->dpm_table.mem_table);
1816         int result = 0;
1817         uint32_t i, j;
1818 
1819         for (i = 0; i < dpm_table->count; i++) {
1820                 result = vega10_populate_single_memory_level(hwmgr,
1821                                 dpm_table->dpm_levels[i].value,
1822                                 &(pp_table->MemVid[i]),
1823                                 &(pp_table->UclkLevel[i]),
1824                                 &(pp_table->MemSocVoltageIndex[i]));
1825                 if (result)
1826                         return result;
1827         }
1828 
1829         j = i - 1;
1830         while (i < NUM_UCLK_DPM_LEVELS) {
1831                 result = vega10_populate_single_memory_level(hwmgr,
1832                                 dpm_table->dpm_levels[j].value,
1833                                 &(pp_table->MemVid[i]),
1834                                 &(pp_table->UclkLevel[i]),
1835                                 &(pp_table->MemSocVoltageIndex[i]));
1836                 if (result)
1837                         return result;
1838                 i++;
1839         }
1840 
1841         pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels);
1842         pp_table->MemoryChannelWidth =
1843                         (uint16_t)(HBM_MEMORY_CHANNEL_WIDTH *
1844                                         channel_number[data->mem_channels]);
1845 
1846         pp_table->LowestUclkReservedForUlv =
1847                         (uint8_t)(data->lowest_uclk_reserved_for_ulv);
1848 
1849         return result;
1850 }
1851 
1852 static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr,
1853                 DSPCLK_e disp_clock)
1854 {
1855         struct vega10_hwmgr *data = hwmgr->backend;
1856         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1857         struct phm_ppt_v2_information *table_info =
1858                         (struct phm_ppt_v2_information *)
1859                         (hwmgr->pptable);
1860         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1861         uint32_t i;
1862         uint16_t clk = 0, vddc = 0;
1863         uint8_t vid = 0;
1864 
1865         switch (disp_clock) {
1866         case DSPCLK_DCEFCLK:
1867                 dep_table = table_info->vdd_dep_on_dcefclk;
1868                 break;
1869         case DSPCLK_DISPCLK:
1870                 dep_table = table_info->vdd_dep_on_dispclk;
1871                 break;
1872         case DSPCLK_PIXCLK:
1873                 dep_table = table_info->vdd_dep_on_pixclk;
1874                 break;
1875         case DSPCLK_PHYCLK:
1876                 dep_table = table_info->vdd_dep_on_phyclk;
1877                 break;
1878         default:
1879                 return -1;
1880         }
1881 
1882         PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS,
1883                         "Number Of Entries Exceeded maximum!",
1884                         return -1);
1885 
1886         for (i = 0; i < dep_table->count; i++) {
1887                 clk = (uint16_t)(dep_table->entries[i].clk / 100);
1888                 vddc = table_info->vddc_lookup_table->
1889                                 entries[dep_table->entries[i].vddInd].us_vdd;
1890                 vid = (uint8_t)convert_to_vid(vddc);
1891                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1892                                 cpu_to_le16(clk);
1893                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1894                                 cpu_to_le16(vid);
1895         }
1896 
1897         while (i < NUM_DSPCLK_LEVELS) {
1898                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1899                                 cpu_to_le16(clk);
1900                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1901                                 cpu_to_le16(vid);
1902                 i++;
1903         }
1904 
1905         return 0;
1906 }
1907 
1908 static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr)
1909 {
1910         uint32_t i;
1911 
1912         for (i = 0; i < DSPCLK_COUNT; i++) {
1913                 PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i),
1914                                 "Failed to populate Clock in DisplayClockTable!",
1915                                 return -1);
1916         }
1917 
1918         return 0;
1919 }
1920 
1921 static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr,
1922                 uint32_t eclock, uint8_t *current_eclk_did,
1923                 uint8_t *current_soc_vol)
1924 {
1925         struct phm_ppt_v2_information *table_info =
1926                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1927         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1928                         table_info->mm_dep_table;
1929         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1930         uint32_t i;
1931 
1932         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1933                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1934                         eclock, &dividers),
1935                         "Failed to get ECLK clock settings from VBIOS!",
1936                         return -1);
1937 
1938         *current_eclk_did = (uint8_t)dividers.ulDid;
1939 
1940         for (i = 0; i < dep_table->count; i++) {
1941                 if (dep_table->entries[i].eclk == eclock)
1942                         *current_soc_vol = dep_table->entries[i].vddcInd;
1943         }
1944 
1945         return 0;
1946 }
1947 
1948 static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr)
1949 {
1950         struct vega10_hwmgr *data = hwmgr->backend;
1951         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1952         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table);
1953         int result = -EINVAL;
1954         uint32_t i, j;
1955 
1956         for (i = 0; i < dpm_table->count; i++) {
1957                 result = vega10_populate_single_eclock_level(hwmgr,
1958                                 dpm_table->dpm_levels[i].value,
1959                                 &(pp_table->EclkDid[i]),
1960                                 &(pp_table->VceDpmVoltageIndex[i]));
1961                 if (result)
1962                         return result;
1963         }
1964 
1965         j = i - 1;
1966         while (i < NUM_VCE_DPM_LEVELS) {
1967                 result = vega10_populate_single_eclock_level(hwmgr,
1968                                 dpm_table->dpm_levels[j].value,
1969                                 &(pp_table->EclkDid[i]),
1970                                 &(pp_table->VceDpmVoltageIndex[i]));
1971                 if (result)
1972                         return result;
1973                 i++;
1974         }
1975 
1976         return result;
1977 }
1978 
1979 static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr,
1980                 uint32_t vclock, uint8_t *current_vclk_did)
1981 {
1982         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1983 
1984         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1985                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1986                         vclock, &dividers),
1987                         "Failed to get VCLK clock settings from VBIOS!",
1988                         return -EINVAL);
1989 
1990         *current_vclk_did = (uint8_t)dividers.ulDid;
1991 
1992         return 0;
1993 }
1994 
1995 static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr,
1996                 uint32_t dclock, uint8_t *current_dclk_did)
1997 {
1998         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1999 
2000         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
2001                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
2002                         dclock, &dividers),
2003                         "Failed to get DCLK clock settings from VBIOS!",
2004                         return -EINVAL);
2005 
2006         *current_dclk_did = (uint8_t)dividers.ulDid;
2007 
2008         return 0;
2009 }
2010 
2011 static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr)
2012 {
2013         struct vega10_hwmgr *data = hwmgr->backend;
2014         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2015         struct vega10_single_dpm_table *vclk_dpm_table =
2016                         &(data->dpm_table.vclk_table);
2017         struct vega10_single_dpm_table *dclk_dpm_table =
2018                         &(data->dpm_table.dclk_table);
2019         struct phm_ppt_v2_information *table_info =
2020                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2021         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
2022                         table_info->mm_dep_table;
2023         int result = -EINVAL;
2024         uint32_t i, j;
2025 
2026         for (i = 0; i < vclk_dpm_table->count; i++) {
2027                 result = vega10_populate_single_vclock_level(hwmgr,
2028                                 vclk_dpm_table->dpm_levels[i].value,
2029                                 &(pp_table->VclkDid[i]));
2030                 if (result)
2031                         return result;
2032         }
2033 
2034         j = i - 1;
2035         while (i < NUM_UVD_DPM_LEVELS) {
2036                 result = vega10_populate_single_vclock_level(hwmgr,
2037                                 vclk_dpm_table->dpm_levels[j].value,
2038                                 &(pp_table->VclkDid[i]));
2039                 if (result)
2040                         return result;
2041                 i++;
2042         }
2043 
2044         for (i = 0; i < dclk_dpm_table->count; i++) {
2045                 result = vega10_populate_single_dclock_level(hwmgr,
2046                                 dclk_dpm_table->dpm_levels[i].value,
2047                                 &(pp_table->DclkDid[i]));
2048                 if (result)
2049                         return result;
2050         }
2051 
2052         j = i - 1;
2053         while (i < NUM_UVD_DPM_LEVELS) {
2054                 result = vega10_populate_single_dclock_level(hwmgr,
2055                                 dclk_dpm_table->dpm_levels[j].value,
2056                                 &(pp_table->DclkDid[i]));
2057                 if (result)
2058                         return result;
2059                 i++;
2060         }
2061 
2062         for (i = 0; i < dep_table->count; i++) {
2063                 if (dep_table->entries[i].vclk ==
2064                                 vclk_dpm_table->dpm_levels[i].value &&
2065                         dep_table->entries[i].dclk ==
2066                                 dclk_dpm_table->dpm_levels[i].value)
2067                         pp_table->UvdDpmVoltageIndex[i] =
2068                                         dep_table->entries[i].vddcInd;
2069                 else
2070                         return -1;
2071         }
2072 
2073         j = i - 1;
2074         while (i < NUM_UVD_DPM_LEVELS) {
2075                 pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd;
2076                 i++;
2077         }
2078 
2079         return 0;
2080 }
2081 
2082 static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
2083 {
2084         struct vega10_hwmgr *data = hwmgr->backend;
2085         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2086         struct phm_ppt_v2_information *table_info =
2087                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2088         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2089                         table_info->vdd_dep_on_sclk;
2090         uint32_t i;
2091 
2092         for (i = 0; i < dep_table->count; i++) {
2093                 pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
2094                 pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
2095                                 * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
2096         }
2097 
2098         return 0;
2099 }
2100 
2101 static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
2102 {
2103         struct vega10_hwmgr *data = hwmgr->backend;
2104         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2105         struct phm_ppt_v2_information *table_info =
2106                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2107         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2108                         table_info->vdd_dep_on_sclk;
2109         struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
2110         int result = 0;
2111         uint32_t i;
2112 
2113         pp_table->MinVoltageVid = (uint8_t)0xff;
2114         pp_table->MaxVoltageVid = (uint8_t)0;
2115 
2116         if (data->smu_features[GNLD_AVFS].supported) {
2117                 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
2118                 if (!result) {
2119                         pp_table->MinVoltageVid = (uint8_t)
2120                                         convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
2121                         pp_table->MaxVoltageVid = (uint8_t)
2122                                         convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
2123 
2124                         pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
2125                         pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
2126                         pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
2127                         pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2128                         pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
2129                         pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2130                         pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
2131 
2132                         pp_table->BtcGbVdroopTableCksOff.a0 =
2133                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
2134                         pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
2135                         pp_table->BtcGbVdroopTableCksOff.a1 =
2136                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
2137                         pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
2138                         pp_table->BtcGbVdroopTableCksOff.a2 =
2139                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
2140                         pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
2141 
2142                         pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
2143                         pp_table->BtcGbVdroopTableCksOn.a0 =
2144                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
2145                         pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
2146                         pp_table->BtcGbVdroopTableCksOn.a1 =
2147                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
2148                         pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
2149                         pp_table->BtcGbVdroopTableCksOn.a2 =
2150                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
2151                         pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
2152 
2153                         pp_table->AvfsGbCksOn.m1 =
2154                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
2155                         pp_table->AvfsGbCksOn.m2 =
2156                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM2);
2157                         pp_table->AvfsGbCksOn.b =
2158                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
2159                         pp_table->AvfsGbCksOn.m1_shift = 24;
2160                         pp_table->AvfsGbCksOn.m2_shift = 12;
2161                         pp_table->AvfsGbCksOn.b_shift = 0;
2162 
2163                         pp_table->OverrideAvfsGbCksOn =
2164                                         avfs_params.ucEnableGbFuseTableCkson;
2165                         pp_table->AvfsGbCksOff.m1 =
2166                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
2167                         pp_table->AvfsGbCksOff.m2 =
2168                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2);
2169                         pp_table->AvfsGbCksOff.b =
2170                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
2171                         pp_table->AvfsGbCksOff.m1_shift = 24;
2172                         pp_table->AvfsGbCksOff.m2_shift = 12;
2173                         pp_table->AvfsGbCksOff.b_shift = 0;
2174 
2175                         for (i = 0; i < dep_table->count; i++)
2176                                 pp_table->StaticVoltageOffsetVid[i] =
2177                                                 convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset));
2178 
2179                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2180                                         data->disp_clk_quad_eqn_a) &&
2181                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2182                                         data->disp_clk_quad_eqn_b)) {
2183                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2184                                                 (int32_t)data->disp_clk_quad_eqn_a;
2185                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2186                                                 (int32_t)data->disp_clk_quad_eqn_b;
2187                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2188                                                 (int32_t)data->disp_clk_quad_eqn_c;
2189                         } else {
2190                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2191                                                 (int32_t)avfs_params.ulDispclk2GfxclkM1;
2192                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2193                                                 (int32_t)avfs_params.ulDispclk2GfxclkM2;
2194                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2195                                                 (int32_t)avfs_params.ulDispclk2GfxclkB;
2196                         }
2197 
2198                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
2199                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
2200                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
2201 
2202                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2203                                         data->dcef_clk_quad_eqn_a) &&
2204                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2205                                         data->dcef_clk_quad_eqn_b)) {
2206                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2207                                                 (int32_t)data->dcef_clk_quad_eqn_a;
2208                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2209                                                 (int32_t)data->dcef_clk_quad_eqn_b;
2210                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2211                                                 (int32_t)data->dcef_clk_quad_eqn_c;
2212                         } else {
2213                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2214                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM1;
2215                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2216                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM2;
2217                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2218                                                 (int32_t)avfs_params.ulDcefclk2GfxclkB;
2219                         }
2220 
2221                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
2222                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
2223                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
2224 
2225                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2226                                         data->pixel_clk_quad_eqn_a) &&
2227                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2228                                         data->pixel_clk_quad_eqn_b)) {
2229                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2230                                                 (int32_t)data->pixel_clk_quad_eqn_a;
2231                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2232                                                 (int32_t)data->pixel_clk_quad_eqn_b;
2233                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2234                                                 (int32_t)data->pixel_clk_quad_eqn_c;
2235                         } else {
2236                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2237                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM1;
2238                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2239                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM2;
2240                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2241                                                 (int32_t)avfs_params.ulPixelclk2GfxclkB;
2242                         }
2243 
2244                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
2245                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
2246                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
2247                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2248                                         data->phy_clk_quad_eqn_a) &&
2249                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2250                                         data->phy_clk_quad_eqn_b)) {
2251                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2252                                                 (int32_t)data->phy_clk_quad_eqn_a;
2253                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2254                                                 (int32_t)data->phy_clk_quad_eqn_b;
2255                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2256                                                 (int32_t)data->phy_clk_quad_eqn_c;
2257                         } else {
2258                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2259                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM1;
2260                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2261                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM2;
2262                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2263                                                 (int32_t)avfs_params.ulPhyclk2GfxclkB;
2264                         }
2265 
2266                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
2267                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
2268                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
2269 
2270                         pp_table->AcgBtcGbVdroopTable.a0       = avfs_params.ulAcgGbVdroopTableA0;
2271                         pp_table->AcgBtcGbVdroopTable.a0_shift = 20;
2272                         pp_table->AcgBtcGbVdroopTable.a1       = avfs_params.ulAcgGbVdroopTableA1;
2273                         pp_table->AcgBtcGbVdroopTable.a1_shift = 20;
2274                         pp_table->AcgBtcGbVdroopTable.a2       = avfs_params.ulAcgGbVdroopTableA2;
2275                         pp_table->AcgBtcGbVdroopTable.a2_shift = 20;
2276 
2277                         pp_table->AcgAvfsGb.m1                   = avfs_params.ulAcgGbFuseTableM1;
2278                         pp_table->AcgAvfsGb.m2                   = avfs_params.ulAcgGbFuseTableM2;
2279                         pp_table->AcgAvfsGb.b                    = avfs_params.ulAcgGbFuseTableB;
2280                         pp_table->AcgAvfsGb.m1_shift             = 24;
2281                         pp_table->AcgAvfsGb.m2_shift             = 12;
2282                         pp_table->AcgAvfsGb.b_shift              = 0;
2283 
2284                 } else {
2285                         data->smu_features[GNLD_AVFS].supported = false;
2286                 }
2287         }
2288 
2289         return 0;
2290 }
2291 
2292 static int vega10_acg_enable(struct pp_hwmgr *hwmgr)
2293 {
2294         struct vega10_hwmgr *data = hwmgr->backend;
2295         uint32_t agc_btc_response;
2296 
2297         if (data->smu_features[GNLD_ACG].supported) {
2298                 if (0 == vega10_enable_smc_features(hwmgr, true,
2299                                         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap))
2300                         data->smu_features[GNLD_DPM_PREFETCHER].enabled = true;
2301 
2302                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg);
2303 
2304                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc);
2305                 agc_btc_response = smum_get_argument(hwmgr);
2306 
2307                 if (1 == agc_btc_response) {
2308                         if (1 == data->acg_loop_state)
2309                                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop);
2310                         else if (2 == data->acg_loop_state)
2311                                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop);
2312                         if (0 == vega10_enable_smc_features(hwmgr, true,
2313                                 data->smu_features[GNLD_ACG].smu_feature_bitmap))
2314                                         data->smu_features[GNLD_ACG].enabled = true;
2315                 } else {
2316                         pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n");
2317                         data->smu_features[GNLD_ACG].enabled = false;
2318                 }
2319         }
2320 
2321         return 0;
2322 }
2323 
2324 static int vega10_acg_disable(struct pp_hwmgr *hwmgr)
2325 {
2326         struct vega10_hwmgr *data = hwmgr->backend;
2327 
2328         if (data->smu_features[GNLD_ACG].supported && 
2329             data->smu_features[GNLD_ACG].enabled)
2330                 if (!vega10_enable_smc_features(hwmgr, false,
2331                         data->smu_features[GNLD_ACG].smu_feature_bitmap))
2332                         data->smu_features[GNLD_ACG].enabled = false;
2333 
2334         return 0;
2335 }
2336 
2337 static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr)
2338 {
2339         struct vega10_hwmgr *data = hwmgr->backend;
2340         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2341         struct pp_atomfwctrl_gpio_parameters gpio_params = {0};
2342         int result;
2343 
2344         result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params);
2345         if (!result) {
2346                 if (PP_CAP(PHM_PlatformCaps_RegulatorHot) &&
2347                     data->registry_data.regulator_hot_gpio_support) {
2348                         pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio;
2349                         pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity;
2350                         pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio;
2351                         pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity;
2352                 } else {
2353                         pp_table->VR0HotGpio = 0;
2354                         pp_table->VR0HotPolarity = 0;
2355                         pp_table->VR1HotGpio = 0;
2356                         pp_table->VR1HotPolarity = 0;
2357                 }
2358 
2359                 if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) &&
2360                     data->registry_data.ac_dc_switch_gpio_support) {
2361                         pp_table->AcDcGpio = gpio_params.ucAcDcGpio;
2362                         pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity;
2363                 } else {
2364                         pp_table->AcDcGpio = 0;
2365                         pp_table->AcDcPolarity = 0;
2366                 }
2367         }
2368 
2369         return result;
2370 }
2371 
2372 static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
2373 {
2374         struct vega10_hwmgr *data = hwmgr->backend;
2375 
2376         if (data->smu_features[GNLD_AVFS].supported) {
2377                 /* Already enabled or disabled */
2378                 if (!(enable ^ data->smu_features[GNLD_AVFS].enabled))
2379                         return 0;
2380 
2381                 if (enable) {
2382                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2383                                         true,
2384                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2385                                         "[avfs_control] Attempt to Enable AVFS feature Failed!",
2386                                         return -1);
2387                         data->smu_features[GNLD_AVFS].enabled = true;
2388                 } else {
2389                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2390                                         false,
2391                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2392                                         "[avfs_control] Attempt to Disable AVFS feature Failed!",
2393                                         return -1);
2394                         data->smu_features[GNLD_AVFS].enabled = false;
2395                 }
2396         }
2397 
2398         return 0;
2399 }
2400 
2401 static int vega10_update_avfs(struct pp_hwmgr *hwmgr)
2402 {
2403         struct vega10_hwmgr *data = hwmgr->backend;
2404 
2405         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
2406                 vega10_avfs_enable(hwmgr, false);
2407         } else if (data->need_update_dpm_table) {
2408                 vega10_avfs_enable(hwmgr, false);
2409                 vega10_avfs_enable(hwmgr, true);
2410         } else {
2411                 vega10_avfs_enable(hwmgr, true);
2412         }
2413 
2414         return 0;
2415 }
2416 
2417 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
2418 {
2419         int result = 0;
2420 
2421         uint64_t serial_number = 0;
2422         uint32_t top32, bottom32;
2423         struct phm_fuses_default fuse;
2424 
2425         struct vega10_hwmgr *data = hwmgr->backend;
2426         AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table);
2427 
2428         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32);
2429         top32 = smum_get_argument(hwmgr);
2430 
2431         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32);
2432         bottom32 = smum_get_argument(hwmgr);
2433 
2434         serial_number = ((uint64_t)bottom32 << 32) | top32;
2435 
2436         if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) {
2437                 avfs_fuse_table->VFT0_b  = fuse.VFT0_b;
2438                 avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1;
2439                 avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2;
2440                 avfs_fuse_table->VFT1_b  = fuse.VFT1_b;
2441                 avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1;
2442                 avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2;
2443                 avfs_fuse_table->VFT2_b  = fuse.VFT2_b;
2444                 avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1;
2445                 avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2;
2446                 result = smum_smc_table_manager(hwmgr,  (uint8_t *)avfs_fuse_table,
2447                                                 AVFSFUSETABLE, false);
2448                 PP_ASSERT_WITH_CODE(!result,
2449                         "Failed to upload FuseOVerride!",
2450                         );
2451         }
2452 
2453         return result;
2454 }
2455 
2456 static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
2457 {
2458         struct vega10_hwmgr *data = hwmgr->backend;
2459         struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
2460         struct phm_ppt_v2_information *table_info = hwmgr->pptable;
2461         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
2462         struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
2463         uint32_t i;
2464 
2465         dep_table = table_info->vdd_dep_on_mclk;
2466         odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk);
2467 
2468         for (i = 0; i < dep_table->count; i++) {
2469                 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
2470                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
2471                         return;
2472                 }
2473         }
2474 
2475         dep_table = table_info->vdd_dep_on_sclk;
2476         odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk);
2477         for (i = 0; i < dep_table->count; i++) {
2478                 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
2479                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK;
2480                         return;
2481                 }
2482         }
2483 }
2484 
2485 /**
2486 * Initializes the SMC table and uploads it
2487 *
2488 * @param    hwmgr  the address of the powerplay hardware manager.
2489 * @param    pInput  the pointer to input data (PowerState)
2490 * @return   always 0
2491 */
2492 static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
2493 {
2494         int result;
2495         struct vega10_hwmgr *data = hwmgr->backend;
2496         struct phm_ppt_v2_information *table_info =
2497                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2498         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2499         struct pp_atomfwctrl_voltage_table voltage_table;
2500         struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
2501         struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
2502 
2503         result = vega10_setup_default_dpm_tables(hwmgr);
2504         PP_ASSERT_WITH_CODE(!result,
2505                         "Failed to setup default DPM tables!",
2506                         return result);
2507 
2508         /* initialize ODN table */
2509         if (hwmgr->od_enabled) {
2510                 if (odn_table->max_vddc) {
2511                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
2512                         vega10_check_dpm_table_updated(hwmgr);
2513                 } else {
2514                         vega10_odn_initial_default_setting(hwmgr);
2515                 }
2516         }
2517 
2518         pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
2519                         VOLTAGE_OBJ_SVID2,  &voltage_table);
2520         pp_table->MaxVidStep = voltage_table.max_vid_step;
2521 
2522         pp_table->GfxDpmVoltageMode =
2523                         (uint8_t)(table_info->uc_gfx_dpm_voltage_mode);
2524         pp_table->SocDpmVoltageMode =
2525                         (uint8_t)(table_info->uc_soc_dpm_voltage_mode);
2526         pp_table->UclkDpmVoltageMode =
2527                         (uint8_t)(table_info->uc_uclk_dpm_voltage_mode);
2528         pp_table->UvdDpmVoltageMode =
2529                         (uint8_t)(table_info->uc_uvd_dpm_voltage_mode);
2530         pp_table->VceDpmVoltageMode =
2531                         (uint8_t)(table_info->uc_vce_dpm_voltage_mode);
2532         pp_table->Mp0DpmVoltageMode =
2533                         (uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
2534 
2535         pp_table->DisplayDpmVoltageMode =
2536                         (uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
2537 
2538         data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable;
2539         data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable;
2540 
2541         if (data->registry_data.ulv_support &&
2542                         table_info->us_ulv_voltage_offset) {
2543                 result = vega10_populate_ulv_state(hwmgr);
2544                 PP_ASSERT_WITH_CODE(!result,
2545                                 "Failed to initialize ULV state!",
2546                                 return result);
2547         }
2548 
2549         result = vega10_populate_smc_link_levels(hwmgr);
2550         PP_ASSERT_WITH_CODE(!result,
2551                         "Failed to initialize Link Level!",
2552                         return result);
2553 
2554         result = vega10_populate_all_graphic_levels(hwmgr);
2555         PP_ASSERT_WITH_CODE(!result,
2556                         "Failed to initialize Graphics Level!",
2557                         return result);
2558 
2559         result = vega10_populate_all_memory_levels(hwmgr);
2560         PP_ASSERT_WITH_CODE(!result,
2561                         "Failed to initialize Memory Level!",
2562                         return result);
2563 
2564         vega10_populate_vddc_soc_levels(hwmgr);
2565 
2566         result = vega10_populate_all_display_clock_levels(hwmgr);
2567         PP_ASSERT_WITH_CODE(!result,
2568                         "Failed to initialize Display Level!",
2569                         return result);
2570 
2571         result = vega10_populate_smc_vce_levels(hwmgr);
2572         PP_ASSERT_WITH_CODE(!result,
2573                         "Failed to initialize VCE Level!",
2574                         return result);
2575 
2576         result = vega10_populate_smc_uvd_levels(hwmgr);
2577         PP_ASSERT_WITH_CODE(!result,
2578                         "Failed to initialize UVD Level!",
2579                         return result);
2580 
2581         if (data->registry_data.clock_stretcher_support) {
2582                 result = vega10_populate_clock_stretcher_table(hwmgr);
2583                 PP_ASSERT_WITH_CODE(!result,
2584                                 "Failed to populate Clock Stretcher Table!",
2585                                 return result);
2586         }
2587 
2588         result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
2589         if (!result) {
2590                 data->vbios_boot_state.vddc     = boot_up_values.usVddc;
2591                 data->vbios_boot_state.vddci    = boot_up_values.usVddci;
2592                 data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
2593                 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
2594                 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
2595                 pp_atomfwctrl_get_clk_information_by_clkid(hwmgr,
2596                                 SMU9_SYSPLL0_SOCCLK_ID, 0, &boot_up_values.ulSocClk);
2597 
2598                 pp_atomfwctrl_get_clk_information_by_clkid(hwmgr,
2599                                 SMU9_SYSPLL0_DCEFCLK_ID, 0, &boot_up_values.ulDCEFClk);
2600 
2601                 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
2602                 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
2603                 if (0 != boot_up_values.usVddc) {
2604                         smum_send_msg_to_smc_with_parameter(hwmgr,
2605                                                 PPSMC_MSG_SetFloorSocVoltage,
2606                                                 (boot_up_values.usVddc * 4));
2607                         data->vbios_boot_state.bsoc_vddc_lock = true;
2608                 } else {
2609                         data->vbios_boot_state.bsoc_vddc_lock = false;
2610                 }
2611                 smum_send_msg_to_smc_with_parameter(hwmgr,
2612                                 PPSMC_MSG_SetMinDeepSleepDcefclk,
2613                         (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
2614         }
2615 
2616         result = vega10_populate_avfs_parameters(hwmgr);
2617         PP_ASSERT_WITH_CODE(!result,
2618                         "Failed to initialize AVFS Parameters!",
2619                         return result);
2620 
2621         result = vega10_populate_gpio_parameters(hwmgr);
2622         PP_ASSERT_WITH_CODE(!result,
2623                         "Failed to initialize GPIO Parameters!",
2624                         return result);
2625 
2626         pp_table->GfxclkAverageAlpha = (uint8_t)
2627                         (data->gfxclk_average_alpha);
2628         pp_table->SocclkAverageAlpha = (uint8_t)
2629                         (data->socclk_average_alpha);
2630         pp_table->UclkAverageAlpha = (uint8_t)
2631                         (data->uclk_average_alpha);
2632         pp_table->GfxActivityAverageAlpha = (uint8_t)
2633                         (data->gfx_activity_average_alpha);
2634 
2635         vega10_populate_and_upload_avfs_fuse_override(hwmgr);
2636 
2637         result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false);
2638 
2639         PP_ASSERT_WITH_CODE(!result,
2640                         "Failed to upload PPtable!", return result);
2641 
2642         result = vega10_avfs_enable(hwmgr, true);
2643         PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
2644                                         return result);
2645         vega10_acg_enable(hwmgr);
2646 
2647         return 0;
2648 }
2649 
2650 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
2651 {
2652         struct vega10_hwmgr *data = hwmgr->backend;
2653 
2654         if (data->smu_features[GNLD_THERMAL].supported) {
2655                 if (data->smu_features[GNLD_THERMAL].enabled)
2656                         pr_info("THERMAL Feature Already enabled!");
2657 
2658                 PP_ASSERT_WITH_CODE(
2659                                 !vega10_enable_smc_features(hwmgr,
2660                                 true,
2661                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2662                                 "Enable THERMAL Feature Failed!",
2663                                 return -1);
2664                 data->smu_features[GNLD_THERMAL].enabled = true;
2665         }
2666 
2667         return 0;
2668 }
2669 
2670 static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
2671 {
2672         struct vega10_hwmgr *data = hwmgr->backend;
2673 
2674         if (data->smu_features[GNLD_THERMAL].supported) {
2675                 if (!data->smu_features[GNLD_THERMAL].enabled)
2676                         pr_info("THERMAL Feature Already disabled!");
2677 
2678                 PP_ASSERT_WITH_CODE(
2679                                 !vega10_enable_smc_features(hwmgr,
2680                                 false,
2681                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2682                                 "disable THERMAL Feature Failed!",
2683                                 return -1);
2684                 data->smu_features[GNLD_THERMAL].enabled = false;
2685         }
2686 
2687         return 0;
2688 }
2689 
2690 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
2691 {
2692         struct vega10_hwmgr *data = hwmgr->backend;
2693 
2694         if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) {
2695                 if (data->smu_features[GNLD_VR0HOT].supported) {
2696                         PP_ASSERT_WITH_CODE(
2697                                         !vega10_enable_smc_features(hwmgr,
2698                                         true,
2699                                         data->smu_features[GNLD_VR0HOT].smu_feature_bitmap),
2700                                         "Attempt to Enable VR0 Hot feature Failed!",
2701                                         return -1);
2702                         data->smu_features[GNLD_VR0HOT].enabled = true;
2703                 } else {
2704                         if (data->smu_features[GNLD_VR1HOT].supported) {
2705                                 PP_ASSERT_WITH_CODE(
2706                                                 !vega10_enable_smc_features(hwmgr,
2707                                                 true,
2708                                                 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap),
2709                                                 "Attempt to Enable VR0 Hot feature Failed!",
2710                                                 return -1);
2711                                 data->smu_features[GNLD_VR1HOT].enabled = true;
2712                         }
2713                 }
2714         }
2715         return 0;
2716 }
2717 
2718 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
2719 {
2720         struct vega10_hwmgr *data = hwmgr->backend;
2721 
2722         if (data->registry_data.ulv_support) {
2723                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2724                                 true, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2725                                 "Enable ULV Feature Failed!",
2726                                 return -1);
2727                 data->smu_features[GNLD_ULV].enabled = true;
2728         }
2729 
2730         return 0;
2731 }
2732 
2733 static int vega10_disable_ulv(struct pp_hwmgr *hwmgr)
2734 {
2735         struct vega10_hwmgr *data = hwmgr->backend;
2736 
2737         if (data->registry_data.ulv_support) {
2738                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2739                                 false, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2740                                 "disable ULV Feature Failed!",
2741                                 return -EINVAL);
2742                 data->smu_features[GNLD_ULV].enabled = false;
2743         }
2744 
2745         return 0;
2746 }
2747 
2748 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2749 {
2750         struct vega10_hwmgr *data = hwmgr->backend;
2751 
2752         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2753                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2754                                 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2755                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2756                                 return -EINVAL);
2757                 data->smu_features[GNLD_DS_GFXCLK].enabled = true;
2758         }
2759 
2760         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2761                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2762                                 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2763                                 "Attempt to Enable DS_SOCCLK Feature Failed!",
2764                                 return -EINVAL);
2765                 data->smu_features[GNLD_DS_SOCCLK].enabled = true;
2766         }
2767 
2768         if (data->smu_features[GNLD_DS_LCLK].supported) {
2769                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2770                                 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2771                                 "Attempt to Enable DS_LCLK Feature Failed!",
2772                                 return -EINVAL);
2773                 data->smu_features[GNLD_DS_LCLK].enabled = true;
2774         }
2775 
2776         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2777                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2778                                 true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2779                                 "Attempt to Enable DS_DCEFCLK Feature Failed!",
2780                                 return -EINVAL);
2781                 data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
2782         }
2783 
2784         return 0;
2785 }
2786 
2787 static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2788 {
2789         struct vega10_hwmgr *data = hwmgr->backend;
2790 
2791         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2792                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2793                                 false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2794                                 "Attempt to disable DS_GFXCLK Feature Failed!",
2795                                 return -EINVAL);
2796                 data->smu_features[GNLD_DS_GFXCLK].enabled = false;
2797         }
2798 
2799         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2800                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2801                                 false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2802                                 "Attempt to disable DS_ Feature Failed!",
2803                                 return -EINVAL);
2804                 data->smu_features[GNLD_DS_SOCCLK].enabled = false;
2805         }
2806 
2807         if (data->smu_features[GNLD_DS_LCLK].supported) {
2808                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2809                                 false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2810                                 "Attempt to disable DS_LCLK Feature Failed!",
2811                                 return -EINVAL);
2812                 data->smu_features[GNLD_DS_LCLK].enabled = false;
2813         }
2814 
2815         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2816                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2817                                 false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2818                                 "Attempt to disable DS_DCEFCLK Feature Failed!",
2819                                 return -EINVAL);
2820                 data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
2821         }
2822 
2823         return 0;
2824 }
2825 
2826 static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2827 {
2828         struct vega10_hwmgr *data = hwmgr->backend;
2829         uint32_t i, feature_mask = 0;
2830 
2831 
2832         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2833                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2834                                 false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2835                 "Attempt to disable LED DPM feature failed!", return -EINVAL);
2836                 data->smu_features[GNLD_LED_DISPLAY].enabled = false;
2837         }
2838 
2839         for (i = 0; i < GNLD_DPM_MAX; i++) {
2840                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2841                         if (data->smu_features[i].supported) {
2842                                 if (data->smu_features[i].enabled) {
2843                                         feature_mask |= data->smu_features[i].
2844                                                         smu_feature_bitmap;
2845                                         data->smu_features[i].enabled = false;
2846                                 }
2847                         }
2848                 }
2849         }
2850 
2851         vega10_enable_smc_features(hwmgr, false, feature_mask);
2852 
2853         return 0;
2854 }
2855 
2856 /**
2857  * @brief Tell SMC to enabled the supported DPMs.
2858  *
2859  * @param    hwmgr - the address of the powerplay hardware manager.
2860  * @Param    bitmap - bitmap for the features to enabled.
2861  * @return   0 on at least one DPM is successfully enabled.
2862  */
2863 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2864 {
2865         struct vega10_hwmgr *data = hwmgr->backend;
2866         uint32_t i, feature_mask = 0;
2867 
2868         for (i = 0; i < GNLD_DPM_MAX; i++) {
2869                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2870                         if (data->smu_features[i].supported) {
2871                                 if (!data->smu_features[i].enabled) {
2872                                         feature_mask |= data->smu_features[i].
2873                                                         smu_feature_bitmap;
2874                                         data->smu_features[i].enabled = true;
2875                                 }
2876                         }
2877                 }
2878         }
2879 
2880         if (vega10_enable_smc_features(hwmgr,
2881                         true, feature_mask)) {
2882                 for (i = 0; i < GNLD_DPM_MAX; i++) {
2883                         if (data->smu_features[i].smu_feature_bitmap &
2884                                         feature_mask)
2885                                 data->smu_features[i].enabled = false;
2886                 }
2887         }
2888 
2889         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2890                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2891                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2892                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2893                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2894         }
2895 
2896         if (data->vbios_boot_state.bsoc_vddc_lock) {
2897                 smum_send_msg_to_smc_with_parameter(hwmgr,
2898                                                 PPSMC_MSG_SetFloorSocVoltage, 0);
2899                 data->vbios_boot_state.bsoc_vddc_lock = false;
2900         }
2901 
2902         if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) {
2903                 if (data->smu_features[GNLD_ACDC].supported) {
2904                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2905                                         true, data->smu_features[GNLD_ACDC].smu_feature_bitmap),
2906                                         "Attempt to Enable DS_GFXCLK Feature Failed!",
2907                                         return -1);
2908                         data->smu_features[GNLD_ACDC].enabled = true;
2909                 }
2910         }
2911 
2912         return 0;
2913 }
2914 
2915 static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
2916 {
2917         struct vega10_hwmgr *data = hwmgr->backend;
2918 
2919         if (data->smu_features[GNLD_PCC_LIMIT].supported) {
2920                 if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled)
2921                         pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled");
2922                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2923                                 enable, data->smu_features[GNLD_PCC_LIMIT].smu_feature_bitmap),
2924                                 "Attempt to Enable PCC Limit feature Failed!",
2925                                 return -EINVAL);
2926                 data->smu_features[GNLD_PCC_LIMIT].enabled = enable;
2927         }
2928 
2929         return 0;
2930 }
2931 
2932 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2933 {
2934         struct vega10_hwmgr *data = hwmgr->backend;
2935         int tmp_result, result = 0;
2936 
2937         vega10_enable_disable_PCC_limit_feature(hwmgr, true);
2938 
2939         smum_send_msg_to_smc_with_parameter(hwmgr,
2940                 PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
2941 
2942         tmp_result = vega10_construct_voltage_tables(hwmgr);
2943         PP_ASSERT_WITH_CODE(!tmp_result,
2944                         "Failed to construct voltage tables!",
2945                         result = tmp_result);
2946 
2947         tmp_result = vega10_init_smc_table(hwmgr);
2948         PP_ASSERT_WITH_CODE(!tmp_result,
2949                         "Failed to initialize SMC table!",
2950                         result = tmp_result);
2951 
2952         if (PP_CAP(PHM_PlatformCaps_ThermalController)) {
2953                 tmp_result = vega10_enable_thermal_protection(hwmgr);
2954                 PP_ASSERT_WITH_CODE(!tmp_result,
2955                                 "Failed to enable thermal protection!",
2956                                 result = tmp_result);
2957         }
2958 
2959         tmp_result = vega10_enable_vrhot_feature(hwmgr);
2960         PP_ASSERT_WITH_CODE(!tmp_result,
2961                         "Failed to enable VR hot feature!",
2962                         result = tmp_result);
2963 
2964         tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr);
2965         PP_ASSERT_WITH_CODE(!tmp_result,
2966                         "Failed to enable deep sleep master switch!",
2967                         result = tmp_result);
2968 
2969         tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES);
2970         PP_ASSERT_WITH_CODE(!tmp_result,
2971                         "Failed to start DPM!", result = tmp_result);
2972 
2973         /* enable didt, do not abort if failed didt */
2974         tmp_result = vega10_enable_didt_config(hwmgr);
2975         PP_ASSERT(!tmp_result,
2976                         "Failed to enable didt config!");
2977 
2978         tmp_result = vega10_enable_power_containment(hwmgr);
2979         PP_ASSERT_WITH_CODE(!tmp_result,
2980                         "Failed to enable power containment!",
2981                         result = tmp_result);
2982 
2983         tmp_result = vega10_power_control_set_level(hwmgr);
2984         PP_ASSERT_WITH_CODE(!tmp_result,
2985                         "Failed to power control set level!",
2986                         result = tmp_result);
2987 
2988         tmp_result = vega10_enable_ulv(hwmgr);
2989         PP_ASSERT_WITH_CODE(!tmp_result,
2990                         "Failed to enable ULV!",
2991                         result = tmp_result);
2992 
2993         return result;
2994 }
2995 
2996 static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr)
2997 {
2998         return sizeof(struct vega10_power_state);
2999 }
3000 
3001 static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
3002                 void *state, struct pp_power_state *power_state,
3003                 void *pp_table, uint32_t classification_flag)
3004 {
3005         ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_V2;
3006         struct vega10_power_state *vega10_power_state =
3007                         cast_phw_vega10_power_state(&(power_state->hardware));
3008         struct vega10_performance_level *performance_level;
3009         ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state;
3010         ATOM_Vega10_POWERPLAYTABLE *powerplay_table =
3011                         (ATOM_Vega10_POWERPLAYTABLE *)pp_table;
3012         ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
3013                         (ATOM_Vega10_SOCCLK_Dependency_Table *)
3014                         (((unsigned long)powerplay_table) +
3015                         le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
3016         ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
3017                         (ATOM_Vega10_GFXCLK_Dependency_Table *)
3018                         (((unsigned long)powerplay_table) +
3019                         le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
3020         ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
3021                         (ATOM_Vega10_MCLK_Dependency_Table *)
3022                         (((unsigned long)powerplay_table) +
3023                         le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
3024 
3025 
3026         /* The following fields are not initialized here:
3027          * id orderedList allStatesList
3028          */
3029         power_state->classification.ui_label =
3030                         (le16_to_cpu(state_entry->usClassification) &
3031                         ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
3032                         ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
3033         power_state->classification.flags = classification_flag;
3034         /* NOTE: There is a classification2 flag in BIOS
3035          * that is not being used right now
3036          */
3037         power_state->classification.temporary_state = false;
3038         power_state->classification.to_be_deleted = false;
3039 
3040         power_state->validation.disallowOnDC =
3041                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
3042                                         ATOM_Vega10_DISALLOW_ON_DC) != 0);
3043 
3044         power_state->display.disableFrameModulation = false;
3045         power_state->display.limitRefreshrate = false;
3046         power_state->display.enableVariBright =
3047                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
3048                                         ATOM_Vega10_ENABLE_VARIBRIGHT) != 0);
3049 
3050         power_state->validation.supportedPowerLevels = 0;
3051         power_state->uvd_clocks.VCLK = 0;
3052         power_state->uvd_clocks.DCLK = 0;
3053         power_state->temperatures.min = 0;
3054         power_state->temperatures.max = 0;
3055 
3056         performance_level = &(vega10_power_state->performance_levels
3057                         [vega10_power_state->performance_level_count++]);
3058 
3059         PP_ASSERT_WITH_CODE(
3060                         (vega10_power_state->performance_level_count <
3061                                         NUM_GFXCLK_DPM_LEVELS),
3062                         "Performance levels exceeds SMC limit!",
3063                         return -1);
3064 
3065         PP_ASSERT_WITH_CODE(
3066                         (vega10_power_state->performance_level_count <=
3067                                         hwmgr->platform_descriptor.
3068                                         hardwareActivityPerformanceLevels),
3069                         "Performance levels exceeds Driver limit!",
3070                         return -1);
3071 
3072         /* Performance levels are arranged from low to high. */
3073         performance_level->soc_clock = socclk_dep_table->entries
3074                         [state_entry->ucSocClockIndexLow].ulClk;
3075         performance_level->gfx_clock = gfxclk_dep_table->entries
3076                         [state_entry->ucGfxClockIndexLow].ulClk;
3077         performance_level->mem_clock = mclk_dep_table->entries
3078                         [state_entry->ucMemClockIndexLow].ulMemClk;
3079 
3080         performance_level = &(vega10_power_state->performance_levels
3081                                 [vega10_power_state->performance_level_count++]);
3082         performance_level->soc_clock = socclk_dep_table->entries
3083                                 [state_entry->ucSocClockIndexHigh].ulClk;
3084         if (gfxclk_dep_table->ucRevId == 0) {
3085                 performance_level->gfx_clock = gfxclk_dep_table->entries
3086                         [state_entry->ucGfxClockIndexHigh].ulClk;
3087         } else if (gfxclk_dep_table->ucRevId == 1) {
3088                 patom_record_V2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
3089                 performance_level->gfx_clock = patom_record_V2[state_entry->ucGfxClockIndexHigh].ulClk;
3090         }
3091 
3092         performance_level->mem_clock = mclk_dep_table->entries
3093                         [state_entry->ucMemClockIndexHigh].ulMemClk;
3094         return 0;
3095 }
3096 
3097 static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
3098                 unsigned long entry_index, struct pp_power_state *state)
3099 {
3100         int result;
3101         struct vega10_power_state *ps;
3102 
3103         state->hardware.magic = PhwVega10_Magic;
3104 
3105         ps = cast_phw_vega10_power_state(&state->hardware);
3106 
3107         result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state,
3108                         vega10_get_pp_table_entry_callback_func);
3109 
3110         /*
3111          * This is the earliest time we have all the dependency table
3112          * and the VBIOS boot state
3113          */
3114         /* set DC compatible flag if this state supports DC */
3115         if (!state->validation.disallowOnDC)
3116                 ps->dc_compatible = true;
3117 
3118         ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3119         ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3120 
3121         return 0;
3122 }
3123 
3124 static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr,
3125              struct pp_hw_power_state *hw_ps)
3126 {
3127         return 0;
3128 }
3129 
3130 static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
3131                                 struct pp_power_state  *request_ps,
3132                         const struct pp_power_state *current_ps)
3133 {
3134         struct amdgpu_device *adev = hwmgr->adev;
3135         struct vega10_power_state *vega10_ps =
3136                                 cast_phw_vega10_power_state(&request_ps->hardware);
3137         uint32_t sclk;
3138         uint32_t mclk;
3139         struct PP_Clocks minimum_clocks = {0};
3140         bool disable_mclk_switching;
3141         bool disable_mclk_switching_for_frame_lock;
3142         bool disable_mclk_switching_for_vr;
3143         bool force_mclk_high;
3144         const struct phm_clock_and_voltage_limits *max_limits;
3145         uint32_t i;
3146         struct vega10_hwmgr *data = hwmgr->backend;
3147         struct phm_ppt_v2_information *table_info =
3148                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
3149         int32_t count;
3150         uint32_t stable_pstate_sclk_dpm_percentage;
3151         uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
3152         uint32_t latency;
3153 
3154         data->battery_state = (PP_StateUILabel_Battery ==
3155                         request_ps->classification.ui_label);
3156 
3157         if (vega10_ps->performance_level_count != 2)
3158                 pr_info("VI should always have 2 performance levels");
3159 
3160         max_limits = adev->pm.ac_power ?
3161                         &(hwmgr->dyn_state.max_clock_voltage_on_ac) :
3162                         &(hwmgr->dyn_state.max_clock_voltage_on_dc);
3163 
3164         /* Cap clock DPM tables at DC MAX if it is in DC. */
3165         if (!adev->pm.ac_power) {
3166                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
3167                         if (vega10_ps->performance_levels[i].mem_clock >
3168                                 max_limits->mclk)
3169                                 vega10_ps->performance_levels[i].mem_clock =
3170                                                 max_limits->mclk;
3171                         if (vega10_ps->performance_levels[i].gfx_clock >
3172                                 max_limits->sclk)
3173                                 vega10_ps->performance_levels[i].gfx_clock =
3174                                                 max_limits->sclk;
3175                 }
3176         }
3177 
3178         /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
3179         minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock;
3180         minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
3181 
3182         if (PP_CAP(PHM_PlatformCaps_StablePState)) {
3183                 stable_pstate_sclk_dpm_percentage =
3184                         data->registry_data.stable_pstate_sclk_dpm_percentage;
3185                 PP_ASSERT_WITH_CODE(
3186                         data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 &&
3187                         data->registry_data.stable_pstate_sclk_dpm_percentage <= 100,
3188                         "percent sclk value must range from 1% to 100%, setting default value",
3189                         stable_pstate_sclk_dpm_percentage = 75);
3190 
3191                 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
3192                 stable_pstate_sclk = (max_limits->sclk *
3193                                 stable_pstate_sclk_dpm_percentage) / 100;
3194 
3195                 for (count = table_info->vdd_dep_on_sclk->count - 1;
3196                                 count >= 0; count--) {
3197                         if (stable_pstate_sclk >=
3198                                         table_info->vdd_dep_on_sclk->entries[count].clk) {
3199                                 stable_pstate_sclk =
3200                                                 table_info->vdd_dep_on_sclk->entries[count].clk;
3201                                 break;
3202                         }
3203                 }
3204 
3205                 if (count < 0)
3206                         stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
3207 
3208                 stable_pstate_mclk = max_limits->mclk;
3209 
3210                 minimum_clocks.engineClock = stable_pstate_sclk;
3211                 minimum_clocks.memoryClock = stable_pstate_mclk;
3212         }
3213 
3214         disable_mclk_switching_for_frame_lock =
3215                 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
3216         disable_mclk_switching_for_vr =
3217                 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);
3218         force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh);
3219 
3220         if (hwmgr->display_config->num_display == 0)
3221                 disable_mclk_switching = false;
3222         else
3223                 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
3224                                           !hwmgr->display_config->multi_monitor_in_sync) ||
3225                         disable_mclk_switching_for_frame_lock ||
3226                         disable_mclk_switching_for_vr ||
3227                         force_mclk_high;
3228 
3229         sclk = vega10_ps->performance_levels[0].gfx_clock;
3230         mclk = vega10_ps->performance_levels[0].mem_clock;
3231 
3232         if (sclk < minimum_clocks.engineClock)
3233                 sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
3234                                 max_limits->sclk : minimum_clocks.engineClock;
3235 
3236         if (mclk < minimum_clocks.memoryClock)
3237                 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
3238                                 max_limits->mclk : minimum_clocks.memoryClock;
3239 
3240         vega10_ps->performance_levels[0].gfx_clock = sclk;
3241         vega10_ps->performance_levels[0].mem_clock = mclk;
3242 
3243         if (vega10_ps->performance_levels[1].gfx_clock <
3244                         vega10_ps->performance_levels[0].gfx_clock)
3245                 vega10_ps->performance_levels[0].gfx_clock =
3246                                 vega10_ps->performance_levels[1].gfx_clock;
3247 
3248         if (disable_mclk_switching) {
3249                 /* Set Mclk the max of level 0 and level 1 */
3250                 if (mclk < vega10_ps->performance_levels[1].mem_clock)
3251                         mclk = vega10_ps->performance_levels[1].mem_clock;
3252 
3253                 /* Find the lowest MCLK frequency that is within
3254                  * the tolerable latency defined in DAL
3255                  */
3256                 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3257                 for (i = 0; i < data->mclk_latency_table.count; i++) {
3258                         if ((data->mclk_latency_table.entries[i].latency <= latency) &&
3259                                 (data->mclk_latency_table.entries[i].frequency >=
3260                                                 vega10_ps->performance_levels[0].mem_clock) &&
3261                                 (data->mclk_latency_table.entries[i].frequency <=
3262                                                 vega10_ps->performance_levels[1].mem_clock))
3263                                 mclk = data->mclk_latency_table.entries[i].frequency;
3264                 }
3265                 vega10_ps->performance_levels[0].mem_clock = mclk;
3266         } else {
3267                 if (vega10_ps->performance_levels[1].mem_clock <
3268                                 vega10_ps->performance_levels[0].mem_clock)
3269                         vega10_ps->performance_levels[0].mem_clock =
3270                                         vega10_ps->performance_levels[1].mem_clock;
3271         }
3272 
3273         if (PP_CAP(PHM_PlatformCaps_StablePState)) {
3274                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
3275                         vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk;
3276                         vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk;
3277                 }
3278         }
3279 
3280         return 0;
3281 }
3282 
3283 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
3284 {
3285         struct vega10_hwmgr *data = hwmgr->backend;
3286         const struct phm_set_power_state_input *states =
3287                         (const struct phm_set_power_state_input *)input;
3288         const struct vega10_power_state *vega10_ps =
3289                         cast_const_phw_vega10_power_state(states->pnew_state);
3290         struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
3291         uint32_t sclk = vega10_ps->performance_levels
3292                         [vega10_ps->performance_level_count - 1].gfx_clock;
3293         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
3294         uint32_t mclk = vega10_ps->performance_levels
3295                         [vega10_ps->performance_level_count - 1].mem_clock;
3296         uint32_t i;
3297 
3298         for (i = 0; i < sclk_table->count; i++) {
3299                 if (sclk == sclk_table->dpm_levels[i].value)
3300                         break;
3301         }
3302 
3303         if (i >= sclk_table->count) {
3304                 if (sclk > sclk_table->dpm_levels[i-1].value) {
3305                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
3306                         sclk_table->dpm_levels[i-1].value = sclk;
3307                 }
3308         }
3309 
3310         for (i = 0; i < mclk_table->count; i++) {
3311                 if (mclk == mclk_table->dpm_levels[i].value)
3312                         break;
3313         }
3314 
3315         if (i >= mclk_table->count) {
3316                 if (mclk > mclk_table->dpm_levels[i-1].value) {
3317                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
3318                         mclk_table->dpm_levels[i-1].value = mclk;
3319                 }
3320         }
3321 
3322         if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
3323                 data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
3324 
3325         return 0;
3326 }
3327 
3328 static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
3329                 struct pp_hwmgr *hwmgr, const void *input)
3330 {
3331         int result = 0;
3332         struct vega10_hwmgr *data = hwmgr->backend;
3333         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3334         struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table;
3335         struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk;
3336         int count;
3337 
3338         if (!data->need_update_dpm_table)
3339                 return 0;
3340 
3341         if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
3342                 for (count = 0; count < dpm_table->gfx_table.count; count++)
3343                         dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk;
3344         }
3345 
3346         odn_clk_table = &odn_table->vdd_dep_on_mclk;
3347         if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
3348                 for (count = 0; count < dpm_table->mem_table.count; count++)
3349                         dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk;
3350         }
3351 
3352         if (data->need_update_dpm_table &
3353                         (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK + DPMTABLE_UPDATE_SOCCLK)) {
3354                 result = vega10_populate_all_graphic_levels(hwmgr);
3355                 PP_ASSERT_WITH_CODE((0 == result),
3356                                 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
3357                                 return result);
3358         }
3359 
3360         if (data->need_update_dpm_table &
3361                         (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
3362                 result = vega10_populate_all_memory_levels(hwmgr);
3363                 PP_ASSERT_WITH_CODE((0 == result),
3364                                 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
3365                                 return result);
3366         }
3367 
3368         vega10_populate_vddc_soc_levels(hwmgr);
3369 
3370         return result;
3371 }
3372 
3373 static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
3374                 struct vega10_single_dpm_table *dpm_table,
3375                 uint32_t low_limit, uint32_t high_limit)
3376 {
3377         uint32_t i;
3378 
3379         for (i = 0; i < dpm_table->count; i++) {
3380                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3381                     (dpm_table->dpm_levels[i].value > high_limit))
3382                         dpm_table->dpm_levels[i].enabled = false;
3383                 else
3384                         dpm_table->dpm_levels[i].enabled = true;
3385         }
3386         return 0;
3387 }
3388 
3389 static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr,
3390                 struct vega10_single_dpm_table *dpm_table,
3391                 uint32_t low_limit, uint32_t high_limit,
3392                 uint32_t disable_dpm_mask)
3393 {
3394         uint32_t i;
3395 
3396         for (i = 0; i < dpm_table->count; i++) {
3397                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3398                     (dpm_table->dpm_levels[i].value > high_limit))
3399                         dpm_table->dpm_levels[i].enabled = false;
3400                 else if (!((1 << i) & disable_dpm_mask))
3401                         dpm_table->dpm_levels[i].enabled = false;
3402                 else
3403                         dpm_table->dpm_levels[i].enabled = true;
3404         }
3405         return 0;
3406 }
3407 
3408 static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr,
3409                 const struct vega10_power_state *vega10_ps)
3410 {
3411         struct vega10_hwmgr *data = hwmgr->backend;
3412         uint32_t high_limit_count;
3413 
3414         PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1),
3415                         "power state did not have any performance level",
3416                         return -1);
3417 
3418         high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1;
3419 
3420         vega10_trim_single_dpm_states(hwmgr,
3421                         &(data->dpm_table.soc_table),
3422                         vega10_ps->performance_levels[0].soc_clock,
3423                         vega10_ps->performance_levels[high_limit_count].soc_clock);
3424 
3425         vega10_trim_single_dpm_states_with_mask(hwmgr,
3426                         &(data->dpm_table.gfx_table),
3427                         vega10_ps->performance_levels[0].gfx_clock,
3428                         vega10_ps->performance_levels[high_limit_count].gfx_clock,
3429                         data->disable_dpm_mask);
3430 
3431         vega10_trim_single_dpm_states(hwmgr,
3432                         &(data->dpm_table.mem_table),
3433                         vega10_ps->performance_levels[0].mem_clock,
3434                         vega10_ps->performance_levels[high_limit_count].mem_clock);
3435 
3436         return 0;
3437 }
3438 
3439 static uint32_t vega10_find_lowest_dpm_level(
3440                 struct vega10_single_dpm_table *table)
3441 {
3442         uint32_t i;
3443 
3444         for (i = 0; i < table->count; i++) {
3445                 if (table->dpm_levels[i].enabled)
3446                         break;
3447         }
3448 
3449         return i;
3450 }
3451 
3452 static uint32_t vega10_find_highest_dpm_level(
3453                 struct vega10_single_dpm_table *table)
3454 {
3455         uint32_t i = 0;
3456 
3457         if (table->count <= MAX_REGULAR_DPM_NUMBER) {
3458                 for (i = table->count; i > 0; i--) {
3459                         if (table->dpm_levels[i - 1].enabled)
3460                                 return i - 1;
3461                 }
3462         } else {
3463                 pr_info("DPM Table Has Too Many Entries!");
3464                 return MAX_REGULAR_DPM_NUMBER - 1;
3465         }
3466 
3467         return i;
3468 }
3469 
3470 static void vega10_apply_dal_minimum_voltage_request(
3471                 struct pp_hwmgr *hwmgr)
3472 {
3473         return;
3474 }
3475 
3476 static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr)
3477 {
3478         struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk;
3479         struct phm_ppt_v2_information *table_info =
3480                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
3481 
3482         vdd_dep_table_on_mclk  = table_info->vdd_dep_on_mclk;
3483 
3484         return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1;
3485 }
3486 
3487 static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
3488 {
3489         struct vega10_hwmgr *data = hwmgr->backend;
3490         uint32_t socclk_idx;
3491 
3492         vega10_apply_dal_minimum_voltage_request(hwmgr);
3493 
3494         if (!data->registry_data.sclk_dpm_key_disabled) {
3495                 if (data->smc_state_table.gfx_boot_level !=
3496                                 data->dpm_table.gfx_table.dpm_state.soft_min_level) {
3497                         smum_send_msg_to_smc_with_parameter(hwmgr,
3498                                 PPSMC_MSG_SetSoftMinGfxclkByIndex,
3499                                 data->smc_state_table.gfx_boot_level);
3500                         data->dpm_table.gfx_table.dpm_state.soft_min_level =
3501                                         data->smc_state_table.gfx_boot_level;
3502                 }
3503         }
3504 
3505         if (!data->registry_data.mclk_dpm_key_disabled) {
3506                 if (data->smc_state_table.mem_boot_level !=
3507                                 data->dpm_table.mem_table.dpm_state.soft_min_level) {
3508                         if (data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) {
3509                                 socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr);
3510                                 smum_send_msg_to_smc_with_parameter(hwmgr,
3511                                                 PPSMC_MSG_SetSoftMinSocclkByIndex,
3512                                                 socclk_idx);
3513                         } else {
3514                                 smum_send_msg_to_smc_with_parameter(hwmgr,
3515                                                 PPSMC_MSG_SetSoftMinUclkByIndex,
3516                                                 data->smc_state_table.mem_boot_level);
3517                         }
3518                         data->dpm_table.mem_table.dpm_state.soft_min_level =
3519                                         data->smc_state_table.mem_boot_level;
3520                 }
3521         }
3522 
3523         if (!data->registry_data.socclk_dpm_key_disabled) {
3524                 if (data->smc_state_table.soc_boot_level !=
3525                                 data->dpm_table.soc_table.dpm_state.soft_min_level) {
3526                         smum_send_msg_to_smc_with_parameter(hwmgr,
3527                                 PPSMC_MSG_SetSoftMinSocclkByIndex,
3528                                 data->smc_state_table.soc_boot_level);
3529                         data->dpm_table.soc_table.dpm_state.soft_min_level =
3530                                         data->smc_state_table.soc_boot_level;
3531                 }
3532         }
3533 
3534         return 0;
3535 }
3536 
3537 static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
3538 {
3539         struct vega10_hwmgr *data = hwmgr->backend;
3540 
3541         vega10_apply_dal_minimum_voltage_request(hwmgr);
3542 
3543         if (!data->registry_data.sclk_dpm_key_disabled) {
3544                 if (data->smc_state_table.gfx_max_level !=
3545                         data->dpm_table.gfx_table.dpm_state.soft_max_level) {
3546                         smum_send_msg_to_smc_with_parameter(hwmgr,
3547                                 PPSMC_MSG_SetSoftMaxGfxclkByIndex,
3548                                 data->smc_state_table.gfx_max_level);
3549                         data->dpm_table.gfx_table.dpm_state.soft_max_level =
3550                                         data->smc_state_table.gfx_max_level;
3551                 }
3552         }
3553 
3554         if (!data->registry_data.mclk_dpm_key_disabled) {
3555                 if (data->smc_state_table.mem_max_level !=
3556                         data->dpm_table.mem_table.dpm_state.soft_max_level) {
3557                         smum_send_msg_to_smc_with_parameter(hwmgr,
3558                                         PPSMC_MSG_SetSoftMaxUclkByIndex,
3559                                         data->smc_state_table.mem_max_level);
3560                         data->dpm_table.mem_table.dpm_state.soft_max_level =
3561                                         data->smc_state_table.mem_max_level;
3562                 }
3563         }
3564 
3565         if (!data->registry_data.socclk_dpm_key_disabled) {
3566                 if (data->smc_state_table.soc_max_level !=
3567                         data->dpm_table.soc_table.dpm_state.soft_max_level) {
3568                         smum_send_msg_to_smc_with_parameter(hwmgr,
3569                                 PPSMC_MSG_SetSoftMaxSocclkByIndex,
3570                                 data->smc_state_table.soc_max_level);
3571                         data->dpm_table.soc_table.dpm_state.soft_max_level =
3572                                         data->smc_state_table.soc_max_level;
3573                 }
3574         }
3575 
3576         return 0;
3577 }
3578 
3579 static int vega10_generate_dpm_level_enable_mask(
3580                 struct pp_hwmgr *hwmgr, const void *input)
3581 {
3582         struct vega10_hwmgr *data = hwmgr->backend;
3583         const struct phm_set_power_state_input *states =
3584                         (const struct phm_set_power_state_input *)input;
3585         const struct vega10_power_state *vega10_ps =
3586                         cast_const_phw_vega10_power_state(states->pnew_state);
3587         int i;
3588 
3589         PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
3590                         "Attempt to Trim DPM States Failed!",
3591                         return -1);
3592 
3593         data->smc_state_table.gfx_boot_level =
3594                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3595         data->smc_state_table.gfx_max_level =
3596                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3597         data->smc_state_table.mem_boot_level =
3598                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3599         data->smc_state_table.mem_max_level =
3600                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3601         data->smc_state_table.soc_boot_level =
3602                         vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table));
3603         data->smc_state_table.soc_max_level =
3604                         vega10_find_highest_dpm_level(&(data->dpm_table.soc_table));
3605 
3606         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3607                         "Attempt to upload DPM Bootup Levels Failed!",
3608                         return -1);
3609         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3610                         "Attempt to upload DPM Max Levels Failed!",
3611                         return -1);
3612         for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++)
3613                 data->dpm_table.gfx_table.dpm_levels[i].enabled = true;
3614 
3615 
3616         for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++)
3617                 data->dpm_table.mem_table.dpm_levels[i].enabled = true;
3618 
3619         for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++)
3620                 data->dpm_table.soc_table.dpm_levels[i].enabled = true;
3621 
3622         return 0;
3623 }
3624 
3625 int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
3626 {
3627         struct vega10_hwmgr *data = hwmgr->backend;
3628 
3629         if (data->smu_features[GNLD_DPM_VCE].supported) {
3630                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
3631                                 enable,
3632                                 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap),
3633                                 "Attempt to Enable/Disable DPM VCE Failed!",
3634                                 return -1);
3635                 data->smu_features[GNLD_DPM_VCE].enabled = enable;
3636         }
3637 
3638         return 0;
3639 }
3640 
3641 static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
3642 {
3643         struct vega10_hwmgr *data = hwmgr->backend;
3644         uint32_t low_sclk_interrupt_threshold = 0;
3645 
3646         if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) &&
3647                 (data->low_sclk_interrupt_threshold != 0)) {
3648                 low_sclk_interrupt_threshold =
3649                                 data->low_sclk_interrupt_threshold;
3650 
3651                 data->smc_state_table.pp_table.LowGfxclkInterruptThreshold =
3652                                 cpu_to_le32(low_sclk_interrupt_threshold);
3653 
3654                 /* This message will also enable SmcToHost Interrupt */
3655                 smum_send_msg_to_smc_with_parameter(hwmgr,
3656                                 PPSMC_MSG_SetLowGfxclkInterruptThreshold,
3657                                 (uint32_t)low_sclk_interrupt_threshold);
3658         }
3659 
3660         return 0;
3661 }
3662 
3663 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
3664                 const void *input)
3665 {
3666         int tmp_result, result = 0;
3667         struct vega10_hwmgr *data = hwmgr->backend;
3668         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
3669 
3670         tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
3671         PP_ASSERT_WITH_CODE(!tmp_result,
3672                         "Failed to find DPM states clocks in DPM table!",
3673                         result = tmp_result);
3674 
3675         tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
3676         PP_ASSERT_WITH_CODE(!tmp_result,
3677                         "Failed to populate and upload SCLK MCLK DPM levels!",
3678                         result = tmp_result);
3679 
3680         tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input);
3681         PP_ASSERT_WITH_CODE(!tmp_result,
3682                         "Failed to generate DPM level enabled mask!",
3683                         result = tmp_result);
3684 
3685         tmp_result = vega10_update_sclk_threshold(hwmgr);
3686         PP_ASSERT_WITH_CODE(!tmp_result,
3687                         "Failed to update SCLK threshold!",
3688                         result = tmp_result);
3689 
3690         result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false);
3691         PP_ASSERT_WITH_CODE(!result,
3692                         "Failed to upload PPtable!", return result);
3693 
3694         vega10_update_avfs(hwmgr);
3695 
3696         /*
3697          * Clear all OD flags except DPMTABLE_OD_UPDATE_VDDC.
3698          * That will help to keep AVFS disabled.
3699          */
3700         data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC;
3701 
3702         return 0;
3703 }
3704 
3705 static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
3706 {
3707         struct pp_power_state *ps;
3708         struct vega10_power_state *vega10_ps;
3709 
3710         if (hwmgr == NULL)
3711                 return -EINVAL;
3712 
3713         ps = hwmgr->request_ps;
3714 
3715         if (ps == NULL)
3716                 return -EINVAL;
3717 
3718         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3719 
3720         if (low)
3721                 return vega10_ps->performance_levels[0].gfx_clock;
3722         else
3723                 return vega10_ps->performance_levels
3724                                 [vega10_ps->performance_level_count - 1].gfx_clock;
3725 }
3726 
3727 static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
3728 {
3729         struct pp_power_state *ps;
3730         struct vega10_power_state *vega10_ps;
3731 
3732         if (hwmgr == NULL)
3733                 return -EINVAL;
3734 
3735         ps = hwmgr->request_ps;
3736 
3737         if (ps == NULL)
3738                 return -EINVAL;
3739 
3740         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3741 
3742         if (low)
3743                 return vega10_ps->performance_levels[0].mem_clock;
3744         else
3745                 return vega10_ps->performance_levels
3746                                 [vega10_ps->performance_level_count-1].mem_clock;
3747 }
3748 
3749 static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr,
3750                 uint32_t *query)
3751 {
3752         uint32_t value;
3753 
3754         if (!query)
3755                 return -EINVAL;
3756 
3757         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr);
3758         value = smum_get_argument(hwmgr);
3759 
3760         /* SMC returning actual watts, keep consistent with legacy asics, low 8 bit as 8 fractional bits */
3761         *query = value << 8;
3762 
3763         return 0;
3764 }
3765 
3766 static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
3767                               void *value, int *size)
3768 {
3769         struct amdgpu_device *adev = hwmgr->adev;
3770         uint32_t sclk_mhz, mclk_idx, activity_percent = 0;
3771         struct vega10_hwmgr *data = hwmgr->backend;
3772         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3773         int ret = 0;
3774         uint32_t val_vid;
3775 
3776         switch (idx) {
3777         case AMDGPU_PP_SENSOR_GFX_SCLK:
3778                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency);
3779                 sclk_mhz = smum_get_argument(hwmgr);
3780                 *((uint32_t *)value) = sclk_mhz * 100;
3781                 break;
3782         case AMDGPU_PP_SENSOR_GFX_MCLK:
3783                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex);
3784                 mclk_idx = smum_get_argument(hwmgr);
3785                 if (mclk_idx < dpm_table->mem_table.count) {
3786                         *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value;
3787                         *size = 4;
3788                 } else {
3789                         ret = -EINVAL;
3790                 }
3791                 break;
3792         case AMDGPU_PP_SENSOR_GPU_LOAD:
3793                 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0);
3794                 activity_percent = smum_get_argument(hwmgr);
3795                 *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
3796                 *size = 4;
3797                 break;
3798         case AMDGPU_PP_SENSOR_GPU_TEMP:
3799                 *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr);
3800                 *size = 4;
3801                 break;
3802         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
3803                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot);
3804                 *((uint32_t *)value) = smum_get_argument(hwmgr) *
3805                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
3806                 *size = 4;
3807                 break;
3808         case AMDGPU_PP_SENSOR_MEM_TEMP:
3809                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM);
3810                 *((uint32_t *)value) = smum_get_argument(hwmgr) *
3811                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
3812                 *size = 4;
3813                 break;
3814         case AMDGPU_PP_SENSOR_UVD_POWER:
3815                 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
3816                 *size = 4;
3817                 break;
3818         case AMDGPU_PP_SENSOR_VCE_POWER:
3819                 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
3820                 *size = 4;
3821                 break;
3822         case AMDGPU_PP_SENSOR_GPU_POWER:
3823                 ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value);
3824                 break;
3825         case AMDGPU_PP_SENSOR_VDDGFX:
3826                 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) &
3827                         SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >>
3828                         SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT;
3829                 *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid);
3830                 return 0;
3831         case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
3832                 ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value);
3833                 if (!ret)
3834                         *size = 8;
3835                 break;
3836         default:
3837                 ret = -EINVAL;
3838                 break;
3839         }
3840 
3841         return ret;
3842 }
3843 
3844 static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
3845                 bool has_disp)
3846 {
3847         smum_send_msg_to_smc_with_parameter(hwmgr,
3848                         PPSMC_MSG_SetUclkFastSwitch,
3849                         has_disp ? 1 : 0);
3850 }
3851 
3852 int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
3853                 struct pp_display_clock_request *clock_req)
3854 {
3855         int result = 0;
3856         enum amd_pp_clock_type clk_type = clock_req->clock_type;
3857         uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
3858         DSPCLK_e clk_select = 0;
3859         uint32_t clk_request = 0;
3860 
3861         switch (clk_type) {
3862         case amd_pp_dcef_clock:
3863                 clk_select = DSPCLK_DCEFCLK;
3864                 break;
3865         case amd_pp_disp_clock:
3866                 clk_select = DSPCLK_DISPCLK;
3867                 break;
3868         case amd_pp_pixel_clock:
3869                 clk_select = DSPCLK_PIXCLK;
3870                 break;
3871         case amd_pp_phy_clock:
3872                 clk_select = DSPCLK_PHYCLK;
3873                 break;
3874         default:
3875                 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
3876                 result = -1;
3877                 break;
3878         }
3879 
3880         if (!result) {
3881                 clk_request = (clk_freq << 16) | clk_select;
3882                 smum_send_msg_to_smc_with_parameter(hwmgr,
3883                                 PPSMC_MSG_RequestDisplayClockByFreq,
3884                                 clk_request);
3885         }
3886 
3887         return result;
3888 }
3889 
3890 static uint8_t vega10_get_uclk_index(struct pp_hwmgr *hwmgr,
3891                         struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table,
3892                                                 uint32_t frequency)
3893 {
3894         uint8_t count;
3895         uint8_t i;
3896 
3897         if (mclk_table == NULL || mclk_table->count == 0)
3898                 return 0;
3899 
3900         count = (uint8_t)(mclk_table->count);
3901 
3902         for(i = 0; i < count; i++) {
3903                 if(mclk_table->entries[i].clk >= frequency)
3904                         return i;
3905         }
3906 
3907         return i-1;
3908 }
3909 
3910 static int vega10_notify_smc_display_config_after_ps_adjustment(
3911                 struct pp_hwmgr *hwmgr)
3912 {
3913         struct vega10_hwmgr *data = hwmgr->backend;
3914         struct vega10_single_dpm_table *dpm_table =
3915                         &data->dpm_table.dcef_table;
3916         struct phm_ppt_v2_information *table_info =
3917                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3918         struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk;
3919         uint32_t idx;
3920         struct PP_Clocks min_clocks = {0};
3921         uint32_t i;
3922         struct pp_display_clock_request clock_req;
3923 
3924         if ((hwmgr->display_config->num_display > 1) &&
3925              !hwmgr->display_config->multi_monitor_in_sync &&
3926              !hwmgr->display_config->nb_pstate_switch_disable)
3927                 vega10_notify_smc_display_change(hwmgr, false);
3928         else
3929                 vega10_notify_smc_display_change(hwmgr, true);
3930 
3931         min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
3932         min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
3933         min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
3934 
3935         for (i = 0; i < dpm_table->count; i++) {
3936                 if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock)
3937                         break;
3938         }
3939 
3940         if (i < dpm_table->count) {
3941                 clock_req.clock_type = amd_pp_dcef_clock;
3942                 clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10;
3943                 if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) {
3944                         smum_send_msg_to_smc_with_parameter(
3945                                         hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
3946                                         min_clocks.dcefClockInSR / 100);
3947                 } else {
3948                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
3949                 }
3950         } else {
3951                 pr_debug("Cannot find requested DCEFCLK!");
3952         }
3953 
3954         if (min_clocks.memoryClock != 0) {
3955                 idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock);
3956                 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx);
3957                 data->dpm_table.mem_table.dpm_state.soft_min_level= idx;
3958         }
3959 
3960         return 0;
3961 }
3962 
3963 static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr)
3964 {
3965         struct vega10_hwmgr *data = hwmgr->backend;
3966 
3967         data->smc_state_table.gfx_boot_level =
3968         data->smc_state_table.gfx_max_level =
3969                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3970         data->smc_state_table.mem_boot_level =
3971         data->smc_state_table.mem_max_level =
3972                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3973 
3974         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3975                         "Failed to upload boot level to highest!",
3976                         return -1);
3977 
3978         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3979                         "Failed to upload dpm max level to highest!",
3980                         return -1);
3981 
3982         return 0;
3983 }
3984 
3985 static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3986 {
3987         struct vega10_hwmgr *data = hwmgr->backend;
3988 
3989         data->smc_state_table.gfx_boot_level =
3990         data->smc_state_table.gfx_max_level =
3991                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3992         data->smc_state_table.mem_boot_level =
3993         data->smc_state_table.mem_max_level =
3994                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3995 
3996         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3997                         "Failed to upload boot level to highest!",
3998                         return -1);
3999 
4000         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4001                         "Failed to upload dpm max level to highest!",
4002                         return -1);
4003 
4004         return 0;
4005 
4006 }
4007 
4008 static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
4009 {
4010         struct vega10_hwmgr *data = hwmgr->backend;
4011 
4012         data->smc_state_table.gfx_boot_level =
4013                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
4014         data->smc_state_table.gfx_max_level =
4015                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
4016         data->smc_state_table.mem_boot_level =
4017                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
4018         data->smc_state_table.mem_max_level =
4019                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
4020 
4021         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4022                         "Failed to upload DPM Bootup Levels!",
4023                         return -1);
4024 
4025         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4026                         "Failed to upload DPM Max Levels!",
4027                         return -1);
4028         return 0;
4029 }
4030 
4031 static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
4032                                 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
4033 {
4034         struct phm_ppt_v2_information *table_info =
4035                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
4036 
4037         if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL &&
4038                 table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL &&
4039                 table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) {
4040                 *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL;
4041                 *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL;
4042                 *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL;
4043                 hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk;
4044                 hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk;
4045         }
4046 
4047         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
4048                 *sclk_mask = 0;
4049         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
4050                 *mclk_mask = 0;
4051         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
4052                 *sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
4053                 *soc_mask = table_info->vdd_dep_on_socclk->count - 1;
4054                 *mclk_mask = table_info->vdd_dep_on_mclk->count - 1;
4055         }
4056         return 0;
4057 }
4058 
4059 static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
4060 {
4061         switch (mode) {
4062         case AMD_FAN_CTRL_NONE:
4063                 vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
4064                 break;
4065         case AMD_FAN_CTRL_MANUAL:
4066                 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
4067                         vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
4068                 break;
4069         case AMD_FAN_CTRL_AUTO:
4070                 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
4071                         vega10_fan_ctrl_start_smc_fan_control(hwmgr);
4072                 break;
4073         default:
4074                 break;
4075         }
4076 }
4077 
4078 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
4079                 enum pp_clock_type type, uint32_t mask)
4080 {
4081         struct vega10_hwmgr *data = hwmgr->backend;
4082 
4083         switch (type) {
4084         case PP_SCLK:
4085                 data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0;
4086                 data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0;
4087 
4088                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4089                         "Failed to upload boot level to lowest!",
4090                         return -EINVAL);
4091 
4092                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4093                         "Failed to upload dpm max level to highest!",
4094                         return -EINVAL);
4095                 break;
4096 
4097         case PP_MCLK:
4098                 data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0;
4099                 data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0;
4100 
4101                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4102                         "Failed to upload boot level to lowest!",
4103                         return -EINVAL);
4104 
4105                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4106                         "Failed to upload dpm max level to highest!",
4107                         return -EINVAL);
4108 
4109                 break;
4110 
4111         case PP_SOCCLK:
4112                 data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0;
4113                 data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0;
4114 
4115                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4116                         "Failed to upload boot level to lowest!",
4117                         return -EINVAL);
4118 
4119                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4120                         "Failed to upload dpm max level to highest!",
4121                         return -EINVAL);
4122 
4123                 break;
4124 
4125         case PP_DCEFCLK:
4126                 pr_info("Setting DCEFCLK min/max dpm level is not supported!\n");
4127                 break;
4128 
4129         case PP_PCIE:
4130         default:
4131                 break;
4132         }
4133 
4134         return 0;
4135 }
4136 
4137 static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
4138                                 enum amd_dpm_forced_level level)
4139 {
4140         int ret = 0;
4141         uint32_t sclk_mask = 0;
4142         uint32_t mclk_mask = 0;
4143         uint32_t soc_mask = 0;
4144 
4145         if (hwmgr->pstate_sclk == 0)
4146                 vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
4147 
4148         switch (level) {
4149         case AMD_DPM_FORCED_LEVEL_HIGH:
4150                 ret = vega10_force_dpm_highest(hwmgr);
4151                 break;
4152         case AMD_DPM_FORCED_LEVEL_LOW:
4153                 ret = vega10_force_dpm_lowest(hwmgr);
4154                 break;
4155         case AMD_DPM_FORCED_LEVEL_AUTO:
4156                 ret = vega10_unforce_dpm_levels(hwmgr);
4157                 break;
4158         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
4159         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
4160         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
4161         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
4162                 ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
4163                 if (ret)
4164                         return ret;
4165                 vega10_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
4166                 vega10_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
4167                 break;
4168         case AMD_DPM_FORCED_LEVEL_MANUAL:
4169         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
4170         default:
4171                 break;
4172         }
4173 
4174         if (!ret) {
4175                 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
4176                         vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE);
4177                 else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
4178                         vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO);
4179         }
4180 
4181         return ret;
4182 }
4183 
4184 static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
4185 {
4186         struct vega10_hwmgr *data = hwmgr->backend;
4187 
4188         if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
4189                 return AMD_FAN_CTRL_MANUAL;
4190         else
4191                 return AMD_FAN_CTRL_AUTO;
4192 }
4193 
4194 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr,
4195                 struct amd_pp_simple_clock_info *info)
4196 {
4197         struct phm_ppt_v2_information *table_info =
4198                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4199         struct phm_clock_and_voltage_limits *max_limits =
4200                         &table_info->max_clock_voltage_on_ac;
4201 
4202         info->engine_max_clock = max_limits->sclk;
4203         info->memory_max_clock = max_limits->mclk;
4204 
4205         return 0;
4206 }
4207 
4208 static void vega10_get_sclks(struct pp_hwmgr *hwmgr,
4209                 struct pp_clock_levels_with_latency *clocks)
4210 {
4211         struct phm_ppt_v2_information *table_info =
4212                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4213         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4214                         table_info->vdd_dep_on_sclk;
4215         uint32_t i;
4216 
4217         clocks->num_levels = 0;
4218         for (i = 0; i < dep_table->count; i++) {
4219                 if (dep_table->entries[i].clk) {
4220                         clocks->data[clocks->num_levels].clocks_in_khz =
4221                                         dep_table->entries[i].clk * 10;
4222                         clocks->num_levels++;
4223                 }
4224         }
4225 
4226 }
4227 
4228 static void vega10_get_memclocks(struct pp_hwmgr *hwmgr,
4229                 struct pp_clock_levels_with_latency *clocks)
4230 {
4231         struct phm_ppt_v2_information *table_info =
4232                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4233         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4234                         table_info->vdd_dep_on_mclk;
4235         struct vega10_hwmgr *data = hwmgr->backend;
4236         uint32_t j = 0;
4237         uint32_t i;
4238 
4239         for (i = 0; i < dep_table->count; i++) {
4240                 if (dep_table->entries[i].clk) {
4241 
4242                         clocks->data[j].clocks_in_khz =
4243                                                 dep_table->entries[i].clk * 10;
4244                         data->mclk_latency_table.entries[j].frequency =
4245                                                         dep_table->entries[i].clk;
4246                         clocks->data[j].latency_in_us =
4247                                 data->mclk_latency_table.entries[j].latency = 25;
4248                         j++;
4249                 }
4250         }
4251         clocks->num_levels = data->mclk_latency_table.count = j;
4252 }
4253 
4254 static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr,
4255                 struct pp_clock_levels_with_latency *clocks)
4256 {
4257         struct phm_ppt_v2_information *table_info =
4258                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4259         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4260                         table_info->vdd_dep_on_dcefclk;
4261         uint32_t i;
4262 
4263         for (i = 0; i < dep_table->count; i++) {
4264                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10;
4265                 clocks->data[i].latency_in_us = 0;
4266                 clocks->num_levels++;
4267         }
4268 }
4269 
4270 static void vega10_get_socclocks(struct pp_hwmgr *hwmgr,
4271                 struct pp_clock_levels_with_latency *clocks)
4272 {
4273         struct phm_ppt_v2_information *table_info =
4274                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4275         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4276                         table_info->vdd_dep_on_socclk;
4277         uint32_t i;
4278 
4279         for (i = 0; i < dep_table->count; i++) {
4280                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10;
4281                 clocks->data[i].latency_in_us = 0;
4282                 clocks->num_levels++;
4283         }
4284 }
4285 
4286 static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
4287                 enum amd_pp_clock_type type,
4288                 struct pp_clock_levels_with_latency *clocks)
4289 {
4290         switch (type) {
4291         case amd_pp_sys_clock:
4292                 vega10_get_sclks(hwmgr, clocks);
4293                 break;
4294         case amd_pp_mem_clock:
4295                 vega10_get_memclocks(hwmgr, clocks);
4296                 break;
4297         case amd_pp_dcef_clock:
4298                 vega10_get_dcefclocks(hwmgr, clocks);
4299                 break;
4300         case amd_pp_soc_clock:
4301                 vega10_get_socclocks(hwmgr, clocks);
4302                 break;
4303         default:
4304                 return -1;
4305         }
4306 
4307         return 0;
4308 }
4309 
4310 static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
4311                 enum amd_pp_clock_type type,
4312                 struct pp_clock_levels_with_voltage *clocks)
4313 {
4314         struct phm_ppt_v2_information *table_info =
4315                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4316         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
4317         uint32_t i;
4318 
4319         switch (type) {
4320         case amd_pp_mem_clock:
4321                 dep_table = table_info->vdd_dep_on_mclk;
4322                 break;
4323         case amd_pp_dcef_clock:
4324                 dep_table = table_info->vdd_dep_on_dcefclk;
4325                 break;
4326         case amd_pp_disp_clock:
4327                 dep_table = table_info->vdd_dep_on_dispclk;
4328                 break;
4329         case amd_pp_pixel_clock:
4330                 dep_table = table_info->vdd_dep_on_pixclk;
4331                 break;
4332         case amd_pp_phy_clock:
4333                 dep_table = table_info->vdd_dep_on_phyclk;
4334                 break;
4335         default:
4336                 return -1;
4337         }
4338 
4339         for (i = 0; i < dep_table->count; i++) {
4340                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk  * 10;
4341                 clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table->
4342                                 entries[dep_table->entries[i].vddInd].us_vdd);
4343                 clocks->num_levels++;
4344         }
4345 
4346         if (i < dep_table->count)
4347                 return -1;
4348 
4349         return 0;
4350 }
4351 
4352 static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
4353                                                         void *clock_range)
4354 {
4355         struct vega10_hwmgr *data = hwmgr->backend;
4356         struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range;
4357         Watermarks_t *table = &(data->smc_state_table.water_marks_table);
4358         int result = 0;
4359 
4360         if (!data->registry_data.disable_water_mark) {
4361                 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
4362                 data->water_marks_bitmap = WaterMarksExist;
4363         }
4364 
4365         return result;
4366 }
4367 
4368 static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
4369 {
4370         static const char *ppfeature_name[] = {
4371                                 "DPM_PREFETCHER",
4372                                 "GFXCLK_DPM",
4373                                 "UCLK_DPM",
4374                                 "SOCCLK_DPM",
4375                                 "UVD_DPM",
4376                                 "VCE_DPM",
4377                                 "ULV",
4378                                 "MP0CLK_DPM",
4379                                 "LINK_DPM",
4380                                 "DCEFCLK_DPM",
4381                                 "AVFS",
4382                                 "GFXCLK_DS",
4383                                 "SOCCLK_DS",
4384                                 "LCLK_DS",
4385                                 "PPT",
4386                                 "TDC",
4387                                 "THERMAL",
4388                                 "GFX_PER_CU_CG",
4389                                 "RM",
4390                                 "DCEFCLK_DS",
4391                                 "ACDC",
4392                                 "VR0HOT",
4393                                 "VR1HOT",
4394                                 "FW_CTF",
4395                                 "LED_DISPLAY",
4396                                 "FAN_CONTROL",
4397                                 "FAST_PPT",
4398                                 "DIDT",
4399                                 "ACG",
4400                                 "PCC_LIMIT"};
4401         static const char *output_title[] = {
4402                                 "FEATURES",
4403                                 "BITMASK",
4404                                 "ENABLEMENT"};
4405         uint64_t features_enabled;
4406         int i;
4407         int ret = 0;
4408         int size = 0;
4409 
4410         ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
4411         PP_ASSERT_WITH_CODE(!ret,
4412                         "[EnableAllSmuFeatures] Failed to get enabled smc features!",
4413                         return ret);
4414 
4415         size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
4416         size += sprintf(buf + size, "%-19s %-22s %s\n",
4417                                 output_title[0],
4418                                 output_title[1],
4419                                 output_title[2]);
4420         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
4421                 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
4422                                         ppfeature_name[i],
4423                                         1ULL << i,
4424                                         (features_enabled & (1ULL << i)) ? "Y" : "N");
4425         }
4426 
4427         return size;
4428 }
4429 
4430 static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
4431 {
4432         uint64_t features_enabled;
4433         uint64_t features_to_enable;
4434         uint64_t features_to_disable;
4435         int ret = 0;
4436 
4437         if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
4438                 return -EINVAL;
4439 
4440         ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
4441         if (ret)
4442                 return ret;
4443 
4444         features_to_disable =
4445                 features_enabled & ~new_ppfeature_masks;
4446         features_to_enable =
4447                 ~features_enabled & new_ppfeature_masks;
4448 
4449         pr_debug("features_to_disable 0x%llx\n", features_to_disable);
4450         pr_debug("features_to_enable 0x%llx\n", features_to_enable);
4451 
4452         if (features_to_disable) {
4453                 ret = vega10_enable_smc_features(hwmgr, false, features_to_disable);
4454                 if (ret)
4455                         return ret;
4456         }
4457 
4458         if (features_to_enable) {
4459                 ret = vega10_enable_smc_features(hwmgr, true, features_to_enable);
4460                 if (ret)
4461                         return ret;
4462         }
4463 
4464         return 0;
4465 }
4466 
4467 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
4468                 enum pp_clock_type type, char *buf)
4469 {
4470         struct vega10_hwmgr *data = hwmgr->backend;
4471         struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
4472         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
4473         struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
4474         struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
4475         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
4476         struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL;
4477 
4478         int i, now, size = 0;
4479 
4480         switch (type) {
4481         case PP_SCLK:
4482                 if (data->registry_data.sclk_dpm_key_disabled)
4483                         break;
4484 
4485                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex);
4486                 now = smum_get_argument(hwmgr);
4487 
4488                 for (i = 0; i < sclk_table->count; i++)
4489                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4490                                         i, sclk_table->dpm_levels[i].value / 100,
4491                                         (i == now) ? "*" : "");
4492                 break;
4493         case PP_MCLK:
4494                 if (data->registry_data.mclk_dpm_key_disabled)
4495                         break;
4496 
4497                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex);
4498                 now = smum_get_argument(hwmgr);
4499 
4500                 for (i = 0; i < mclk_table->count; i++)
4501                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4502                                         i, mclk_table->dpm_levels[i].value / 100,
4503                                         (i == now) ? "*" : "");
4504                 break;
4505         case PP_SOCCLK:
4506                 if (data->registry_data.socclk_dpm_key_disabled)
4507                         break;
4508 
4509                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex);
4510                 now = smum_get_argument(hwmgr);
4511 
4512                 for (i = 0; i < soc_table->count; i++)
4513                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4514                                         i, soc_table->dpm_levels[i].value / 100,
4515                                         (i == now) ? "*" : "");
4516                 break;
4517         case PP_DCEFCLK:
4518                 if (data->registry_data.dcefclk_dpm_key_disabled)
4519                         break;
4520 
4521                 smum_send_msg_to_smc_with_parameter(hwmgr,
4522                                 PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK);
4523                 now = smum_get_argument(hwmgr);
4524 
4525                 for (i = 0; i < dcef_table->count; i++)
4526                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4527                                         i, dcef_table->dpm_levels[i].value / 100,
4528                                         (dcef_table->dpm_levels[i].value / 100 == now) ?
4529                                         "*" : "");
4530                 break;
4531         case PP_PCIE:
4532                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex);
4533                 now = smum_get_argument(hwmgr);
4534 
4535                 for (i = 0; i < pcie_table->count; i++)
4536                         size += sprintf(buf + size, "%d: %s %s\n", i,
4537                                         (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" :
4538                                         (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" :
4539                                         (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "",
4540                                         (i == now) ? "*" : "");
4541                 break;
4542         case OD_SCLK:
4543                 if (hwmgr->od_enabled) {
4544                         size = sprintf(buf, "%s:\n", "OD_SCLK");
4545                         podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
4546                         for (i = 0; i < podn_vdd_dep->count; i++)
4547                                 size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
4548                                         i, podn_vdd_dep->entries[i].clk / 100,
4549                                                 podn_vdd_dep->entries[i].vddc);
4550                 }
4551                 break;
4552         case OD_MCLK:
4553                 if (hwmgr->od_enabled) {
4554                         size = sprintf(buf, "%s:\n", "OD_MCLK");
4555                         podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
4556                         for (i = 0; i < podn_vdd_dep->count; i++)
4557                                 size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
4558                                         i, podn_vdd_dep->entries[i].clk/100,
4559                                                 podn_vdd_dep->entries[i].vddc);
4560                 }
4561                 break;
4562         case OD_RANGE:
4563                 if (hwmgr->od_enabled) {
4564                         size = sprintf(buf, "%s:\n", "OD_RANGE");
4565                         size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
4566                                 data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
4567                                 hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
4568                         size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
4569                                 data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
4570                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
4571                         size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
4572                                 data->odn_dpm_table.min_vddc,
4573                                 data->odn_dpm_table.max_vddc);
4574                 }
4575                 break;
4576         default:
4577                 break;
4578         }
4579         return size;
4580 }
4581 
4582 static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4583 {
4584         struct vega10_hwmgr *data = hwmgr->backend;
4585         Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
4586         int result = 0;
4587 
4588         if ((data->water_marks_bitmap & WaterMarksExist) &&
4589                         !(data->water_marks_bitmap & WaterMarksLoaded)) {
4590                 result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false);
4591                 PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL);
4592                 data->water_marks_bitmap |= WaterMarksLoaded;
4593         }
4594 
4595         if (data->water_marks_bitmap & WaterMarksLoaded) {
4596                 smum_send_msg_to_smc_with_parameter(hwmgr,
4597                         PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display);
4598         }
4599 
4600         return result;
4601 }
4602 
4603 int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
4604 {
4605         struct vega10_hwmgr *data = hwmgr->backend;
4606 
4607         if (data->smu_features[GNLD_DPM_UVD].supported) {
4608                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
4609                                 enable,
4610                                 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap),
4611                                 "Attempt to Enable/Disable DPM UVD Failed!",
4612                                 return -1);
4613                 data->smu_features[GNLD_DPM_UVD].enabled = enable;
4614         }
4615         return 0;
4616 }
4617 
4618 static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
4619 {
4620         struct vega10_hwmgr *data = hwmgr->backend;
4621 
4622         data->vce_power_gated = bgate;
4623         vega10_enable_disable_vce_dpm(hwmgr, !bgate);
4624 }
4625 
4626 static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
4627 {
4628         struct vega10_hwmgr *data = hwmgr->backend;
4629 
4630         data->uvd_power_gated = bgate;
4631         vega10_enable_disable_uvd_dpm(hwmgr, !bgate);
4632 }
4633 
4634 static inline bool vega10_are_power_levels_equal(
4635                                 const struct vega10_performance_level *pl1,
4636                                 const struct vega10_performance_level *pl2)
4637 {
4638         return ((pl1->soc_clock == pl2->soc_clock) &&
4639                         (pl1->gfx_clock == pl2->gfx_clock) &&
4640                         (pl1->mem_clock == pl2->mem_clock));
4641 }
4642 
4643 static int vega10_check_states_equal(struct pp_hwmgr *hwmgr,
4644                                 const struct pp_hw_power_state *pstate1,
4645                         const struct pp_hw_power_state *pstate2, bool *equal)
4646 {
4647         const struct vega10_power_state *psa;
4648         const struct vega10_power_state *psb;
4649         int i;
4650 
4651         if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
4652                 return -EINVAL;
4653 
4654         psa = cast_const_phw_vega10_power_state(pstate1);
4655         psb = cast_const_phw_vega10_power_state(pstate2);
4656         /* If the two states don't even have the same number of performance levels they cannot be the same state. */
4657         if (psa->performance_level_count != psb->performance_level_count) {
4658                 *equal = false;
4659                 return 0;
4660         }
4661 
4662         for (i = 0; i < psa->performance_level_count; i++) {
4663                 if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4664                         /* If we have found even one performance level pair that is different the states are different. */
4665                         *equal = false;
4666                         return 0;
4667                 }
4668         }
4669 
4670         /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4671         *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4672         *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4673         *equal &= (psa->sclk_threshold == psb->sclk_threshold);
4674 
4675         return 0;
4676 }
4677 
4678 static bool
4679 vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4680 {
4681         struct vega10_hwmgr *data = hwmgr->backend;
4682         bool is_update_required = false;
4683 
4684         if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4685                 is_update_required = true;
4686 
4687         if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) {
4688                 if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr)
4689                         is_update_required = true;
4690         }
4691 
4692         return is_update_required;
4693 }
4694 
4695 static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
4696 {
4697         int tmp_result, result = 0;
4698 
4699         if (PP_CAP(PHM_PlatformCaps_ThermalController))
4700                 vega10_disable_thermal_protection(hwmgr);
4701 
4702         tmp_result = vega10_disable_power_containment(hwmgr);
4703         PP_ASSERT_WITH_CODE((tmp_result == 0),
4704                         "Failed to disable power containment!", result = tmp_result);
4705 
4706         tmp_result = vega10_disable_didt_config(hwmgr);
4707         PP_ASSERT_WITH_CODE((tmp_result == 0),
4708                         "Failed to disable didt config!", result = tmp_result);
4709 
4710         tmp_result = vega10_avfs_enable(hwmgr, false);
4711         PP_ASSERT_WITH_CODE((tmp_result == 0),
4712                         "Failed to disable AVFS!", result = tmp_result);
4713 
4714         tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES);
4715         PP_ASSERT_WITH_CODE((tmp_result == 0),
4716                         "Failed to stop DPM!", result = tmp_result);
4717 
4718         tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr);
4719         PP_ASSERT_WITH_CODE((tmp_result == 0),
4720                         "Failed to disable deep sleep!", result = tmp_result);
4721 
4722         tmp_result = vega10_disable_ulv(hwmgr);
4723         PP_ASSERT_WITH_CODE((tmp_result == 0),
4724                         "Failed to disable ulv!", result = tmp_result);
4725 
4726         tmp_result =  vega10_acg_disable(hwmgr);
4727         PP_ASSERT_WITH_CODE((tmp_result == 0),
4728                         "Failed to disable acg!", result = tmp_result);
4729 
4730         vega10_enable_disable_PCC_limit_feature(hwmgr, false);
4731         return result;
4732 }
4733 
4734 static int vega10_power_off_asic(struct pp_hwmgr *hwmgr)
4735 {
4736         struct vega10_hwmgr *data = hwmgr->backend;
4737         int result;
4738 
4739         result = vega10_disable_dpm_tasks(hwmgr);
4740         PP_ASSERT_WITH_CODE((0 == result),
4741                         "[disable_dpm_tasks] Failed to disable DPM!",
4742                         );
4743         data->water_marks_bitmap &= ~(WaterMarksLoaded);
4744 
4745         return result;
4746 }
4747 
4748 static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
4749 {
4750         struct vega10_hwmgr *data = hwmgr->backend;
4751         struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
4752         struct vega10_single_dpm_table *golden_sclk_table =
4753                         &(data->golden_dpm_table.gfx_table);
4754         int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
4755         int golden_value = golden_sclk_table->dpm_levels
4756                         [golden_sclk_table->count - 1].value;
4757 
4758         value -= golden_value;
4759         value = DIV_ROUND_UP(value * 100, golden_value);
4760 
4761         return value;
4762 }
4763 
4764 static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
4765 {
4766         struct vega10_hwmgr *data = hwmgr->backend;
4767         struct vega10_single_dpm_table *golden_sclk_table =
4768                         &(data->golden_dpm_table.gfx_table);
4769         struct pp_power_state *ps;
4770         struct vega10_power_state *vega10_ps;
4771 
4772         ps = hwmgr->request_ps;
4773 
4774         if (ps == NULL)
4775                 return -EINVAL;
4776 
4777         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
4778 
4779         vega10_ps->performance_levels
4780         [vega10_ps->performance_level_count - 1].gfx_clock =
4781                         golden_sclk_table->dpm_levels
4782                         [golden_sclk_table->count - 1].value *
4783                         value / 100 +
4784                         golden_sclk_table->dpm_levels
4785                         [golden_sclk_table->count - 1].value;
4786 
4787         if (vega10_ps->performance_levels
4788                         [vega10_ps->performance_level_count - 1].gfx_clock >
4789                         hwmgr->platform_descriptor.overdriveLimit.engineClock) {
4790                 vega10_ps->performance_levels
4791                 [vega10_ps->performance_level_count - 1].gfx_clock =
4792                                 hwmgr->platform_descriptor.overdriveLimit.engineClock;
4793                 pr_warn("max sclk supported by vbios is %d\n",
4794                                 hwmgr->platform_descriptor.overdriveLimit.engineClock);
4795         }
4796         return 0;
4797 }
4798 
4799 static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)
4800 {
4801         struct vega10_hwmgr *data = hwmgr->backend;
4802         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
4803         struct vega10_single_dpm_table *golden_mclk_table =
4804                         &(data->golden_dpm_table.mem_table);
4805         int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
4806         int golden_value = golden_mclk_table->dpm_levels
4807                         [golden_mclk_table->count - 1].value;
4808 
4809         value -= golden_value;
4810         value = DIV_ROUND_UP(value * 100, golden_value);
4811 
4812         return value;
4813 }
4814 
4815 static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
4816 {
4817         struct vega10_hwmgr *data = hwmgr->backend;
4818         struct vega10_single_dpm_table *golden_mclk_table =
4819                         &(data->golden_dpm_table.mem_table);
4820         struct pp_power_state  *ps;
4821         struct vega10_power_state  *vega10_ps;
4822 
4823         ps = hwmgr->request_ps;
4824 
4825         if (ps == NULL)
4826                 return -EINVAL;
4827 
4828         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
4829 
4830         vega10_ps->performance_levels
4831         [vega10_ps->performance_level_count - 1].mem_clock =
4832                         golden_mclk_table->dpm_levels
4833                         [golden_mclk_table->count - 1].value *
4834                         value / 100 +
4835                         golden_mclk_table->dpm_levels
4836                         [golden_mclk_table->count - 1].value;
4837 
4838         if (vega10_ps->performance_levels
4839                         [vega10_ps->performance_level_count - 1].mem_clock >
4840                         hwmgr->platform_descriptor.overdriveLimit.memoryClock) {
4841                 vega10_ps->performance_levels
4842                 [vega10_ps->performance_level_count - 1].mem_clock =
4843                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock;
4844                 pr_warn("max mclk supported by vbios is %d\n",
4845                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock);
4846         }
4847 
4848         return 0;
4849 }
4850 
4851 static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
4852                                         uint32_t virtual_addr_low,
4853                                         uint32_t virtual_addr_hi,
4854                                         uint32_t mc_addr_low,
4855                                         uint32_t mc_addr_hi,
4856                                         uint32_t size)
4857 {
4858         smum_send_msg_to_smc_with_parameter(hwmgr,
4859                                         PPSMC_MSG_SetSystemVirtualDramAddrHigh,
4860                                         virtual_addr_hi);
4861         smum_send_msg_to_smc_with_parameter(hwmgr,
4862                                         PPSMC_MSG_SetSystemVirtualDramAddrLow,
4863                                         virtual_addr_low);
4864         smum_send_msg_to_smc_with_parameter(hwmgr,
4865                                         PPSMC_MSG_DramLogSetDramAddrHigh,
4866                                         mc_addr_hi);
4867 
4868         smum_send_msg_to_smc_with_parameter(hwmgr,
4869                                         PPSMC_MSG_DramLogSetDramAddrLow,
4870                                         mc_addr_low);
4871 
4872         smum_send_msg_to_smc_with_parameter(hwmgr,
4873                                         PPSMC_MSG_DramLogSetDramSize,
4874                                         size);
4875         return 0;
4876 }
4877 
4878 static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
4879                 struct PP_TemperatureRange *thermal_data)
4880 {
4881         struct vega10_hwmgr *data = hwmgr->backend;
4882         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
4883 
4884         memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
4885 
4886         thermal_data->max = pp_table->TedgeLimit *
4887                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4888         thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
4889                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4890         thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
4891                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4892         thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
4893                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4894         thermal_data->mem_crit_max = pp_table->ThbmLimit *
4895                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4896         thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
4897                 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4898 
4899         return 0;
4900 }
4901 
4902 static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
4903 {
4904         struct vega10_hwmgr *data = hwmgr->backend;
4905         uint32_t i, size = 0;
4906         static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,},
4907                                                 {70, 60, 1, 3,},
4908                                                 {90, 60, 0, 0,},
4909                                                 {70, 60, 0, 0,},
4910                                                 {70, 90, 0, 0,},
4911                                                 {30, 60, 0, 6,},
4912                                                 };
4913         static const char *profile_name[7] = {"BOOTUP_DEFAULT",
4914                                         "3D_FULL_SCREEN",
4915                                         "POWER_SAVING",
4916                                         "VIDEO",
4917                                         "VR",
4918                                         "COMPUTE",
4919                                         "CUSTOM"};
4920         static const char *title[6] = {"NUM",
4921                         "MODE_NAME",
4922                         "BUSY_SET_POINT",
4923                         "FPS",
4924                         "USE_RLC_BUSY",
4925                         "MIN_ACTIVE_LEVEL"};
4926 
4927         if (!buf)
4928                 return -EINVAL;
4929 
4930         size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
4931                         title[1], title[2], title[3], title[4], title[5]);
4932 
4933         for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++)
4934                 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
4935                         i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
4936                         profile_mode_setting[i][0], profile_mode_setting[i][1],
4937                         profile_mode_setting[i][2], profile_mode_setting[i][3]);
4938         size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i,
4939                         profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
4940                         data->custom_profile_mode[0], data->custom_profile_mode[1],
4941                         data->custom_profile_mode[2], data->custom_profile_mode[3]);
4942         return size;
4943 }
4944 
4945 static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
4946 {
4947         struct vega10_hwmgr *data = hwmgr->backend;
4948         uint8_t busy_set_point;
4949         uint8_t FPS;
4950         uint8_t use_rlc_busy;
4951         uint8_t min_active_level;
4952         uint32_t power_profile_mode = input[size];
4953 
4954         if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
4955                 if (size != 0 && size != 4)
4956                         return -EINVAL;
4957 
4958                 /* If size = 0 and the CUSTOM profile has been set already
4959                  * then just apply the profile. The copy stored in the hwmgr
4960                  * is zeroed out on init
4961                  */
4962                 if (size == 0) {
4963                         if (data->custom_profile_mode[0] != 0)
4964                                 goto out;
4965                         else
4966                                 return -EINVAL;
4967                 }
4968 
4969                 data->custom_profile_mode[0] = busy_set_point = input[0];
4970                 data->custom_profile_mode[1] = FPS = input[1];
4971                 data->custom_profile_mode[2] = use_rlc_busy = input[2];
4972                 data->custom_profile_mode[3] = min_active_level = input[3];
4973                 smum_send_msg_to_smc_with_parameter(hwmgr,
4974                                         PPSMC_MSG_SetCustomGfxDpmParameters,
4975                                         busy_set_point | FPS<<8 |
4976                                         use_rlc_busy << 16 | min_active_level<<24);
4977         }
4978 
4979 out:
4980         smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
4981                                                 1 << power_profile_mode);
4982         hwmgr->power_profile_mode = power_profile_mode;
4983 
4984         return 0;
4985 }
4986 
4987 
4988 static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
4989                                         enum PP_OD_DPM_TABLE_COMMAND type,
4990                                         uint32_t clk,
4991                                         uint32_t voltage)
4992 {
4993         struct vega10_hwmgr *data = hwmgr->backend;
4994         struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4995         struct vega10_single_dpm_table *golden_table;
4996 
4997         if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) {
4998                 pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc);
4999                 return false;
5000         }
5001 
5002         if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
5003                 golden_table = &(data->golden_dpm_table.gfx_table);
5004                 if (golden_table->dpm_levels[0].value > clk ||
5005                         hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
5006                         pr_info("OD engine clock is out of range [%d - %d] MHz\n",
5007                                 golden_table->dpm_levels[0].value/100,
5008                                 hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
5009                         return false;
5010                 }
5011         } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
5012                 golden_table = &(data->golden_dpm_table.mem_table);
5013                 if (golden_table->dpm_levels[0].value > clk ||
5014                         hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
5015                         pr_info("OD memory clock is out of range [%d - %d] MHz\n",
5016                                 golden_table->dpm_levels[0].value/100,
5017                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
5018                         return false;
5019                 }
5020         } else {
5021                 return false;
5022         }
5023 
5024         return true;
5025 }
5026 
5027 static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
5028 {
5029         struct vega10_hwmgr *data = hwmgr->backend;
5030         struct pp_power_state *ps = hwmgr->request_ps;
5031         struct vega10_power_state *vega10_ps;
5032         struct vega10_single_dpm_table *gfx_dpm_table =
5033                 &data->dpm_table.gfx_table;
5034         struct vega10_single_dpm_table *soc_dpm_table =
5035                 &data->dpm_table.soc_table;
5036         struct vega10_single_dpm_table *mem_dpm_table =
5037                 &data->dpm_table.mem_table;
5038         int max_level;
5039 
5040         if (!ps)
5041                 return;
5042 
5043         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
5044         max_level = vega10_ps->performance_level_count - 1;
5045 
5046         if (vega10_ps->performance_levels[max_level].gfx_clock !=
5047             gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value)
5048                 vega10_ps->performance_levels[max_level].gfx_clock =
5049                         gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value;
5050 
5051         if (vega10_ps->performance_levels[max_level].soc_clock !=
5052             soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value)
5053                 vega10_ps->performance_levels[max_level].soc_clock =
5054                         soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value;
5055 
5056         if (vega10_ps->performance_levels[max_level].mem_clock !=
5057             mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value)
5058                 vega10_ps->performance_levels[max_level].mem_clock =
5059                         mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value;
5060 
5061         if (!hwmgr->ps)
5062                 return;
5063 
5064         ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1));
5065         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
5066         max_level = vega10_ps->performance_level_count - 1;
5067 
5068         if (vega10_ps->performance_levels[max_level].gfx_clock !=
5069             gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value)
5070                 vega10_ps->performance_levels[max_level].gfx_clock =
5071                         gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value;
5072 
5073         if (vega10_ps->performance_levels[max_level].soc_clock !=
5074             soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value)
5075                 vega10_ps->performance_levels[max_level].soc_clock =
5076                         soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value;
5077 
5078         if (vega10_ps->performance_levels[max_level].mem_clock !=
5079             mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value)
5080                 vega10_ps->performance_levels[max_level].mem_clock =
5081                         mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value;
5082 }
5083 
5084 static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr,
5085                                                 enum PP_OD_DPM_TABLE_COMMAND type)
5086 {
5087         struct vega10_hwmgr *data = hwmgr->backend;
5088         struct phm_ppt_v2_information *table_info = hwmgr->pptable;
5089         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk;
5090         struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table;
5091 
5092         struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk =
5093                                                         &data->odn_dpm_table.vdd_dep_on_socclk;
5094         struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table;
5095 
5096         struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep;
5097         uint8_t i, j;
5098 
5099         if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
5100                 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
5101                 for (i = 0; i < podn_vdd_dep->count; i++)
5102                         od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
5103         } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
5104                 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
5105                 for (i = 0; i < dpm_table->count; i++) {
5106                         for (j = 0; j < od_vddc_lookup_table->count; j++) {
5107                                 if (od_vddc_lookup_table->entries[j].us_vdd >
5108                                         podn_vdd_dep->entries[i].vddc)
5109                                         break;
5110                         }
5111                         if (j == od_vddc_lookup_table->count) {
5112                                 j = od_vddc_lookup_table->count - 1;
5113                                 od_vddc_lookup_table->entries[j].us_vdd =
5114                                         podn_vdd_dep->entries[i].vddc;
5115                                 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
5116                         }
5117                         podn_vdd_dep->entries[i].vddInd = j;
5118                 }
5119                 dpm_table = &data->dpm_table.soc_table;
5120                 for (i = 0; i < dep_table->count; i++) {
5121                         if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd &&
5122                                         dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) {
5123                                 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
5124                                 for (; (i < dep_table->count) &&
5125                                        (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) {
5126                                         podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk;
5127                                         dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk;
5128                                 }
5129                                 break;
5130                         } else {
5131                                 dpm_table->dpm_levels[i].value = dep_table->entries[i].clk;
5132                                 podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc;
5133                                 podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd;
5134                                 podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk;
5135                         }
5136                 }
5137                 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk <
5138                                         podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) {
5139                         data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
5140                         podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk =
5141                                 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk;
5142                         dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value =
5143                                 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk;
5144                 }
5145                 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd <
5146                                         podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) {
5147                         data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
5148                         podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd =
5149                                 podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd;
5150                 }
5151         }
5152         vega10_odn_update_power_state(hwmgr);
5153 }
5154 
5155 static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
5156                                         enum PP_OD_DPM_TABLE_COMMAND type,
5157                                         long *input, uint32_t size)
5158 {
5159         struct vega10_hwmgr *data = hwmgr->backend;
5160         struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table;
5161         struct vega10_single_dpm_table *dpm_table;
5162 
5163         uint32_t input_clk;
5164         uint32_t input_vol;
5165         uint32_t input_level;
5166         uint32_t i;
5167 
5168         PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
5169                                 return -EINVAL);
5170 
5171         if (!hwmgr->od_enabled) {
5172                 pr_info("OverDrive feature not enabled\n");
5173                 return -EINVAL;
5174         }
5175 
5176         if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
5177                 dpm_table = &data->dpm_table.gfx_table;
5178                 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk;
5179                 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
5180         } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
5181                 dpm_table = &data->dpm_table.mem_table;
5182                 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk;
5183                 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
5184         } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
5185                 memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table));
5186                 vega10_odn_initial_default_setting(hwmgr);
5187                 vega10_odn_update_power_state(hwmgr);
5188                 /* force to update all clock tables */
5189                 data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK |
5190                                               DPMTABLE_UPDATE_MCLK |
5191                                               DPMTABLE_UPDATE_SOCCLK;
5192                 return 0;
5193         } else if (PP_OD_COMMIT_DPM_TABLE == type) {
5194                 vega10_check_dpm_table_updated(hwmgr);
5195                 return 0;
5196         } else {
5197                 return -EINVAL;
5198         }
5199 
5200         for (i = 0; i < size; i += 3) {
5201                 if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) {
5202                         pr_info("invalid clock voltage input\n");
5203                         return 0;
5204                 }
5205                 input_level = input[i];
5206                 input_clk = input[i+1] * 100;
5207                 input_vol = input[i+2];
5208 
5209                 if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
5210                         dpm_table->dpm_levels[input_level].value = input_clk;
5211                         podn_vdd_dep_table->entries[input_level].clk = input_clk;
5212                         podn_vdd_dep_table->entries[input_level].vddc = input_vol;
5213                 } else {
5214                         return -EINVAL;
5215                 }
5216         }
5217         vega10_odn_update_soc_table(hwmgr, type);
5218         return 0;
5219 }
5220 
5221 static int vega10_set_mp1_state(struct pp_hwmgr *hwmgr,
5222                                 enum pp_mp1_state mp1_state)
5223 {
5224         uint16_t msg;
5225         int ret;
5226 
5227         switch (mp1_state) {
5228         case PP_MP1_STATE_UNLOAD:
5229                 msg = PPSMC_MSG_PrepareMp1ForUnload;
5230                 break;
5231         case PP_MP1_STATE_SHUTDOWN:
5232         case PP_MP1_STATE_RESET:
5233         case PP_MP1_STATE_NONE:
5234         default:
5235                 return 0;
5236         }
5237 
5238         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg)) == 0,
5239                             "[PrepareMp1] Failed!",
5240                             return ret);
5241 
5242         return 0;
5243 }
5244 
5245 static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
5246                                 PHM_PerformanceLevelDesignation designation, uint32_t index,
5247                                 PHM_PerformanceLevel *level)
5248 {
5249         const struct vega10_power_state *ps;
5250         struct vega10_hwmgr *data;
5251         uint32_t i;
5252 
5253         if (level == NULL || hwmgr == NULL || state == NULL)
5254                 return -EINVAL;
5255 
5256         data = hwmgr->backend;
5257         ps = cast_const_phw_vega10_power_state(state);
5258 
5259         i = index > ps->performance_level_count - 1 ?
5260                         ps->performance_level_count - 1 : index;
5261 
5262         level->coreClock = ps->performance_levels[i].gfx_clock;
5263         level->memory_clock = ps->performance_levels[i].mem_clock;
5264 
5265         return 0;
5266 }
5267 
5268 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
5269         .backend_init = vega10_hwmgr_backend_init,
5270         .backend_fini = vega10_hwmgr_backend_fini,
5271         .asic_setup = vega10_setup_asic_task,
5272         .dynamic_state_management_enable = vega10_enable_dpm_tasks,
5273         .dynamic_state_management_disable = vega10_disable_dpm_tasks,
5274         .get_num_of_pp_table_entries =
5275                         vega10_get_number_of_powerplay_table_entries,
5276         .get_power_state_size = vega10_get_power_state_size,
5277         .get_pp_table_entry = vega10_get_pp_table_entry,
5278         .patch_boot_state = vega10_patch_boot_state,
5279         .apply_state_adjust_rules = vega10_apply_state_adjust_rules,
5280         .power_state_set = vega10_set_power_state_tasks,
5281         .get_sclk = vega10_dpm_get_sclk,
5282         .get_mclk = vega10_dpm_get_mclk,
5283         .notify_smc_display_config_after_ps_adjustment =
5284                         vega10_notify_smc_display_config_after_ps_adjustment,
5285         .force_dpm_level = vega10_dpm_force_dpm_level,
5286         .stop_thermal_controller = vega10_thermal_stop_thermal_controller,
5287         .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info,
5288         .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent,
5289         .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent,
5290         .reset_fan_speed_to_default =
5291                         vega10_fan_ctrl_reset_fan_speed_to_default,
5292         .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm,
5293         .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm,
5294         .uninitialize_thermal_controller =
5295                         vega10_thermal_ctrl_uninitialize_thermal_controller,
5296         .set_fan_control_mode = vega10_set_fan_control_mode,
5297         .get_fan_control_mode = vega10_get_fan_control_mode,
5298         .read_sensor = vega10_read_sensor,
5299         .get_dal_power_level = vega10_get_dal_power_level,
5300         .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency,
5301         .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage,
5302         .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges,
5303         .display_clock_voltage_request = vega10_display_clock_voltage_request,
5304         .force_clock_level = vega10_force_clock_level,
5305         .print_clock_levels = vega10_print_clock_levels,
5306         .display_config_changed = vega10_display_configuration_changed_task,
5307         .powergate_uvd = vega10_power_gate_uvd,
5308         .powergate_vce = vega10_power_gate_vce,
5309         .check_states_equal = vega10_check_states_equal,
5310         .check_smc_update_required_for_display_configuration =
5311                         vega10_check_smc_update_required_for_display_configuration,
5312         .power_off_asic = vega10_power_off_asic,
5313         .disable_smc_firmware_ctf = vega10_thermal_disable_alert,
5314         .get_sclk_od = vega10_get_sclk_od,
5315         .set_sclk_od = vega10_set_sclk_od,
5316         .get_mclk_od = vega10_get_mclk_od,
5317         .set_mclk_od = vega10_set_mclk_od,
5318         .avfs_control = vega10_avfs_enable,
5319         .notify_cac_buffer_info = vega10_notify_cac_buffer_info,
5320         .get_thermal_temperature_range = vega10_get_thermal_temperature_range,
5321         .register_irq_handlers = smu9_register_irq_handlers,
5322         .start_thermal_controller = vega10_start_thermal_controller,
5323         .get_power_profile_mode = vega10_get_power_profile_mode,
5324         .set_power_profile_mode = vega10_set_power_profile_mode,
5325         .set_power_limit = vega10_set_power_limit,
5326         .odn_edit_dpm_table = vega10_odn_edit_dpm_table,
5327         .get_performance_level = vega10_get_performance_level,
5328         .get_asic_baco_capability = smu9_baco_get_capability,
5329         .get_asic_baco_state = smu9_baco_get_state,
5330         .set_asic_baco_state = vega10_baco_set_state,
5331         .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost,
5332         .get_ppfeature_status = vega10_get_ppfeature_status,
5333         .set_ppfeature_status = vega10_set_ppfeature_status,
5334         .set_mp1_state = vega10_set_mp1_state,
5335 };
5336 
5337 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
5338 {
5339         struct amdgpu_device *adev = hwmgr->adev;
5340 
5341         hwmgr->hwmgr_func = &vega10_hwmgr_funcs;
5342         hwmgr->pptable_func = &vega10_pptable_funcs;
5343         if (amdgpu_passthrough(adev))
5344                 return vega10_baco_set_cap(hwmgr);
5345 
5346         return 0;
5347 }

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