linux/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
<<
>>
Prefs
   1/*
   2 * Copyright 2017 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23
  24#include <linux/delay.h>
  25#include <linux/fb.h>
  26#include <linux/module.h>
  27#include <linux/slab.h>
  28
  29#include "hwmgr.h"
  30#include "amd_powerplay.h"
  31#include "vega12_smumgr.h"
  32#include "hardwaremanager.h"
  33#include "ppatomfwctrl.h"
  34#include "atomfirmware.h"
  35#include "cgs_common.h"
  36#include "vega12_inc.h"
  37#include "pp_soc15.h"
  38#include "pppcielanes.h"
  39#include "vega12_hwmgr.h"
  40#include "vega12_processpptables.h"
  41#include "vega12_pptable.h"
  42#include "vega12_thermal.h"
  43#include "vega12_ppsmc.h"
  44#include "pp_debug.h"
  45#include "amd_pcie_helpers.h"
  46#include "ppinterrupt.h"
  47#include "pp_overdriver.h"
  48#include "pp_thermal.h"
  49
  50
  51static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
  52                enum pp_clock_type type, uint32_t mask);
  53static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr,
  54                uint32_t *clock,
  55                PPCLK_e clock_select,
  56                bool max);
  57
  58static void vega12_set_default_registry_data(struct pp_hwmgr *hwmgr)
  59{
  60        struct vega12_hwmgr *data =
  61                        (struct vega12_hwmgr *)(hwmgr->backend);
  62
  63        data->gfxclk_average_alpha = PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT;
  64        data->socclk_average_alpha = PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT;
  65        data->uclk_average_alpha = PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT;
  66        data->gfx_activity_average_alpha = PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT;
  67        data->lowest_uclk_reserved_for_ulv = PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT;
  68
  69        data->display_voltage_mode = PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT;
  70        data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  71        data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  72        data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  73        data->disp_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  74        data->disp_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  75        data->disp_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  76        data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  77        data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  78        data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  79        data->phy_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  80        data->phy_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  81        data->phy_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  82
  83        data->registry_data.disallowed_features = 0x0;
  84        data->registry_data.od_state_in_dc_support = 0;
  85        data->registry_data.skip_baco_hardware = 0;
  86
  87        data->registry_data.log_avfs_param = 0;
  88        data->registry_data.sclk_throttle_low_notification = 1;
  89        data->registry_data.force_dpm_high = 0;
  90        data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
  91
  92        data->registry_data.didt_support = 0;
  93        if (data->registry_data.didt_support) {
  94                data->registry_data.didt_mode = 6;
  95                data->registry_data.sq_ramping_support = 1;
  96                data->registry_data.db_ramping_support = 0;
  97                data->registry_data.td_ramping_support = 0;
  98                data->registry_data.tcp_ramping_support = 0;
  99                data->registry_data.dbr_ramping_support = 0;
 100                data->registry_data.edc_didt_support = 1;
 101                data->registry_data.gc_didt_support = 0;
 102                data->registry_data.psm_didt_support = 0;
 103        }
 104
 105        data->registry_data.pcie_lane_override = 0xff;
 106        data->registry_data.pcie_speed_override = 0xff;
 107        data->registry_data.pcie_clock_override = 0xffffffff;
 108        data->registry_data.regulator_hot_gpio_support = 1;
 109        data->registry_data.ac_dc_switch_gpio_support = 0;
 110        data->registry_data.quick_transition_support = 0;
 111        data->registry_data.zrpm_start_temp = 0xffff;
 112        data->registry_data.zrpm_stop_temp = 0xffff;
 113        data->registry_data.odn_feature_enable = 1;
 114        data->registry_data.disable_water_mark = 0;
 115        data->registry_data.disable_pp_tuning = 0;
 116        data->registry_data.disable_xlpp_tuning = 0;
 117        data->registry_data.disable_workload_policy = 0;
 118        data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
 119        data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
 120        data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
 121        data->registry_data.force_workload_policy_mask = 0;
 122        data->registry_data.disable_3d_fs_detection = 0;
 123        data->registry_data.fps_support = 1;
 124        data->registry_data.disable_auto_wattman = 1;
 125        data->registry_data.auto_wattman_debug = 0;
 126        data->registry_data.auto_wattman_sample_period = 100;
 127        data->registry_data.auto_wattman_threshold = 50;
 128}
 129
 130static int vega12_set_features_platform_caps(struct pp_hwmgr *hwmgr)
 131{
 132        struct vega12_hwmgr *data =
 133                        (struct vega12_hwmgr *)(hwmgr->backend);
 134        struct amdgpu_device *adev = hwmgr->adev;
 135
 136        if (data->vddci_control == VEGA12_VOLTAGE_CONTROL_NONE)
 137                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 138                                PHM_PlatformCaps_ControlVDDCI);
 139
 140        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 141                        PHM_PlatformCaps_TablelessHardwareInterface);
 142
 143        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 144                        PHM_PlatformCaps_EnableSMU7ThermalManagement);
 145
 146        if (adev->pg_flags & AMD_PG_SUPPORT_UVD) {
 147                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 148                                PHM_PlatformCaps_UVDPowerGating);
 149                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 150                                PHM_PlatformCaps_UVDDynamicPowerGating);
 151        }
 152
 153        if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
 154                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 155                                PHM_PlatformCaps_VCEPowerGating);
 156
 157        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 158                        PHM_PlatformCaps_UnTabledHardwareInterface);
 159
 160        if (data->registry_data.odn_feature_enable)
 161                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 162                                PHM_PlatformCaps_ODNinACSupport);
 163        else {
 164                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 165                                PHM_PlatformCaps_OD6inACSupport);
 166                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 167                                PHM_PlatformCaps_OD6PlusinACSupport);
 168        }
 169
 170        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 171                        PHM_PlatformCaps_ActivityReporting);
 172        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 173                        PHM_PlatformCaps_FanSpeedInTableIsRPM);
 174
 175        if (data->registry_data.od_state_in_dc_support) {
 176                if (data->registry_data.odn_feature_enable)
 177                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 178                                        PHM_PlatformCaps_ODNinDCSupport);
 179                else {
 180                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 181                                        PHM_PlatformCaps_OD6inDCSupport);
 182                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 183                                        PHM_PlatformCaps_OD6PlusinDCSupport);
 184                }
 185        }
 186
 187        if (data->registry_data.thermal_support
 188                        && data->registry_data.fuzzy_fan_control_support
 189                        && hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
 190                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 191                                PHM_PlatformCaps_ODFuzzyFanControlSupport);
 192
 193        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 194                                PHM_PlatformCaps_DynamicPowerManagement);
 195        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 196                        PHM_PlatformCaps_SMC);
 197        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 198                        PHM_PlatformCaps_ThermalPolicyDelay);
 199
 200        if (data->registry_data.force_dpm_high)
 201                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 202                                PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
 203
 204        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 205                        PHM_PlatformCaps_DynamicUVDState);
 206
 207        if (data->registry_data.sclk_throttle_low_notification)
 208                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 209                                PHM_PlatformCaps_SclkThrottleLowNotification);
 210
 211        /* power tune caps */
 212        /* assume disabled */
 213        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 214                        PHM_PlatformCaps_PowerContainment);
 215        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 216                        PHM_PlatformCaps_DiDtSupport);
 217        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 218                        PHM_PlatformCaps_SQRamping);
 219        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 220                        PHM_PlatformCaps_DBRamping);
 221        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 222                        PHM_PlatformCaps_TDRamping);
 223        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 224                        PHM_PlatformCaps_TCPRamping);
 225        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 226                        PHM_PlatformCaps_DBRRamping);
 227        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 228                        PHM_PlatformCaps_DiDtEDCEnable);
 229        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 230                        PHM_PlatformCaps_GCEDC);
 231        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 232                        PHM_PlatformCaps_PSM);
 233
 234        if (data->registry_data.didt_support) {
 235                phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport);
 236                if (data->registry_data.sq_ramping_support)
 237                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping);
 238                if (data->registry_data.db_ramping_support)
 239                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping);
 240                if (data->registry_data.td_ramping_support)
 241                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping);
 242                if (data->registry_data.tcp_ramping_support)
 243                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping);
 244                if (data->registry_data.dbr_ramping_support)
 245                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping);
 246                if (data->registry_data.edc_didt_support)
 247                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable);
 248                if (data->registry_data.gc_didt_support)
 249                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC);
 250                if (data->registry_data.psm_didt_support)
 251                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM);
 252        }
 253
 254        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 255                        PHM_PlatformCaps_RegulatorHot);
 256
 257        if (data->registry_data.ac_dc_switch_gpio_support) {
 258                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 259                                PHM_PlatformCaps_AutomaticDCTransition);
 260                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 261                                PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 262        }
 263
 264        if (data->registry_data.quick_transition_support) {
 265                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 266                                PHM_PlatformCaps_AutomaticDCTransition);
 267                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 268                                PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 269                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 270                                PHM_PlatformCaps_Falcon_QuickTransition);
 271        }
 272
 273        if (data->lowest_uclk_reserved_for_ulv != PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT) {
 274                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 275                                PHM_PlatformCaps_LowestUclkReservedForUlv);
 276                if (data->lowest_uclk_reserved_for_ulv == 1)
 277                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 278                                        PHM_PlatformCaps_LowestUclkReservedForUlv);
 279        }
 280
 281        if (data->registry_data.custom_fan_support)
 282                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 283                                PHM_PlatformCaps_CustomFanControlSupport);
 284
 285        return 0;
 286}
 287
 288static void vega12_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 289{
 290        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
 291        int i;
 292
 293        data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
 294                        FEATURE_DPM_PREFETCHER_BIT;
 295        data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
 296                        FEATURE_DPM_GFXCLK_BIT;
 297        data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
 298                        FEATURE_DPM_UCLK_BIT;
 299        data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
 300                        FEATURE_DPM_SOCCLK_BIT;
 301        data->smu_features[GNLD_DPM_UVD].smu_feature_id =
 302                        FEATURE_DPM_UVD_BIT;
 303        data->smu_features[GNLD_DPM_VCE].smu_feature_id =
 304                        FEATURE_DPM_VCE_BIT;
 305        data->smu_features[GNLD_ULV].smu_feature_id =
 306                        FEATURE_ULV_BIT;
 307        data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
 308                        FEATURE_DPM_MP0CLK_BIT;
 309        data->smu_features[GNLD_DPM_LINK].smu_feature_id =
 310                        FEATURE_DPM_LINK_BIT;
 311        data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
 312                        FEATURE_DPM_DCEFCLK_BIT;
 313        data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
 314                        FEATURE_DS_GFXCLK_BIT;
 315        data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
 316                        FEATURE_DS_SOCCLK_BIT;
 317        data->smu_features[GNLD_DS_LCLK].smu_feature_id =
 318                        FEATURE_DS_LCLK_BIT;
 319        data->smu_features[GNLD_PPT].smu_feature_id =
 320                        FEATURE_PPT_BIT;
 321        data->smu_features[GNLD_TDC].smu_feature_id =
 322                        FEATURE_TDC_BIT;
 323        data->smu_features[GNLD_THERMAL].smu_feature_id =
 324                        FEATURE_THERMAL_BIT;
 325        data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
 326                        FEATURE_GFX_PER_CU_CG_BIT;
 327        data->smu_features[GNLD_RM].smu_feature_id =
 328                        FEATURE_RM_BIT;
 329        data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
 330                        FEATURE_DS_DCEFCLK_BIT;
 331        data->smu_features[GNLD_ACDC].smu_feature_id =
 332                        FEATURE_ACDC_BIT;
 333        data->smu_features[GNLD_VR0HOT].smu_feature_id =
 334                        FEATURE_VR0HOT_BIT;
 335        data->smu_features[GNLD_VR1HOT].smu_feature_id =
 336                        FEATURE_VR1HOT_BIT;
 337        data->smu_features[GNLD_FW_CTF].smu_feature_id =
 338                        FEATURE_FW_CTF_BIT;
 339        data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
 340                        FEATURE_LED_DISPLAY_BIT;
 341        data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
 342                        FEATURE_FAN_CONTROL_BIT;
 343        data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
 344        data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
 345        data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
 346        data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
 347
 348        for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 349                data->smu_features[i].smu_feature_bitmap =
 350                        (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
 351                data->smu_features[i].allowed =
 352                        ((data->registry_data.disallowed_features >> i) & 1) ?
 353                        false : true;
 354        }
 355}
 356
 357static int vega12_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
 358{
 359        return 0;
 360}
 361
 362static int vega12_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 363{
 364        kfree(hwmgr->backend);
 365        hwmgr->backend = NULL;
 366
 367        return 0;
 368}
 369
 370static int vega12_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 371{
 372        int result = 0;
 373        struct vega12_hwmgr *data;
 374        struct amdgpu_device *adev = hwmgr->adev;
 375
 376        data = kzalloc(sizeof(struct vega12_hwmgr), GFP_KERNEL);
 377        if (data == NULL)
 378                return -ENOMEM;
 379
 380        hwmgr->backend = data;
 381
 382        vega12_set_default_registry_data(hwmgr);
 383
 384        data->disable_dpm_mask = 0xff;
 385        data->workload_mask = 0xff;
 386
 387        /* need to set voltage control types before EVV patching */
 388        data->vddc_control = VEGA12_VOLTAGE_CONTROL_NONE;
 389        data->mvdd_control = VEGA12_VOLTAGE_CONTROL_NONE;
 390        data->vddci_control = VEGA12_VOLTAGE_CONTROL_NONE;
 391
 392        data->water_marks_bitmap = 0;
 393        data->avfs_exist = false;
 394
 395        vega12_set_features_platform_caps(hwmgr);
 396
 397        vega12_init_dpm_defaults(hwmgr);
 398
 399        /* Parse pptable data read from VBIOS */
 400        vega12_set_private_data_based_on_pptable(hwmgr);
 401
 402        data->is_tlu_enabled = false;
 403
 404        hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
 405                        VEGA12_MAX_HARDWARE_POWERLEVELS;
 406        hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
 407        hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
 408
 409        hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
 410        /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
 411        hwmgr->platform_descriptor.clockStep.engineClock = 500;
 412        hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 413
 414        data->total_active_cus = adev->gfx.cu_info.number;
 415        /* Setup default Overdrive Fan control settings */
 416        data->odn_fan_table.target_fan_speed =
 417                        hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
 418        data->odn_fan_table.target_temperature =
 419                        hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature;
 420        data->odn_fan_table.min_performance_clock =
 421                        hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit;
 422        data->odn_fan_table.min_fan_limit =
 423                        hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit *
 424                        hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
 425
 426        return result;
 427}
 428
 429static int vega12_init_sclk_threshold(struct pp_hwmgr *hwmgr)
 430{
 431        struct vega12_hwmgr *data =
 432                        (struct vega12_hwmgr *)(hwmgr->backend);
 433
 434        data->low_sclk_interrupt_threshold = 0;
 435
 436        return 0;
 437}
 438
 439static int vega12_setup_asic_task(struct pp_hwmgr *hwmgr)
 440{
 441        PP_ASSERT_WITH_CODE(!vega12_init_sclk_threshold(hwmgr),
 442                        "Failed to init sclk threshold!",
 443                        return -EINVAL);
 444
 445        return 0;
 446}
 447
 448/*
 449 * @fn vega12_init_dpm_state
 450 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
 451 *
 452 * @param    dpm_state - the address of the DPM Table to initiailize.
 453 * @return   None.
 454 */
 455static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state)
 456{
 457        dpm_state->soft_min_level = 0xff;
 458        dpm_state->soft_max_level = 0xff;
 459        dpm_state->hard_min_level = 0xff;
 460        dpm_state->hard_max_level = 0xff;
 461}
 462
 463static int vega12_get_number_dpm_level(struct pp_hwmgr *hwmgr,
 464                PPCLK_e clkID, uint32_t *num_dpm_level)
 465{
 466        int result;
 467        /*
 468         * SMU expects the Clock ID to be in the top 16 bits.
 469         * Lower 16 bits specify the level however 0xFF is a
 470         * special argument the returns the total number of levels
 471         */
 472        PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 473                PPSMC_MSG_GetDpmFreqByIndex, (clkID << 16 | 0xFF)) == 0,
 474                "[GetNumberDpmLevel] Failed to get DPM levels from SMU for CLKID!",
 475                return -EINVAL);
 476
 477        result = vega12_read_arg_from_smc(hwmgr, num_dpm_level);
 478
 479        PP_ASSERT_WITH_CODE(*num_dpm_level < MAX_REGULAR_DPM_NUMBER,
 480                "[GetNumberDPMLevel] Number of DPM levels is greater than limit",
 481                return -EINVAL);
 482
 483        PP_ASSERT_WITH_CODE(*num_dpm_level != 0,
 484                "[GetNumberDPMLevel] Number of CLK Levels is zero!",
 485                return -EINVAL);
 486
 487        return result;
 488}
 489
 490static int vega12_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
 491                PPCLK_e clkID, uint32_t index, uint32_t *clock)
 492{
 493        int result;
 494
 495        /*
 496         *SMU expects the Clock ID to be in the top 16 bits.
 497         *Lower 16 bits specify the level
 498         */
 499        PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 500                PPSMC_MSG_GetDpmFreqByIndex, (clkID << 16 | index)) == 0,
 501                "[GetDpmFrequencyByIndex] Failed to get dpm frequency from SMU!",
 502                return -EINVAL);
 503
 504        result = vega12_read_arg_from_smc(hwmgr, clock);
 505
 506        PP_ASSERT_WITH_CODE(*clock != 0,
 507                "[GetDPMFrequencyByIndex] Failed to get dpm frequency by index.!",
 508                return -EINVAL);
 509
 510        return result;
 511}
 512
 513/*
 514 * This function is to initialize all DPM state tables
 515 * for SMU based on the dependency table.
 516 * Dynamic state patching function will then trim these
 517 * state tables to the allowed range based
 518 * on the power policy or external client requests,
 519 * such as UVD request, etc.
 520 */
 521static int vega12_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 522{
 523        uint32_t num_levels, i, clock;
 524
 525        struct vega12_hwmgr *data =
 526                        (struct vega12_hwmgr *)(hwmgr->backend);
 527
 528        struct vega12_single_dpm_table *dpm_table;
 529
 530        memset(&data->dpm_table, 0, sizeof(data->dpm_table));
 531
 532        /* Initialize Sclk DPM and SOC DPM table based on allow Sclk values */
 533        dpm_table = &(data->dpm_table.soc_table);
 534
 535        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_SOCCLK,
 536                &num_levels) == 0,
 537                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for SOCCLK!",
 538                return -EINVAL);
 539
 540        dpm_table->count = num_levels;
 541
 542        for (i = 0; i < num_levels; i++) {
 543                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 544                        PPCLK_SOCCLK, i, &clock) == 0,
 545                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for SOCCLK!",
 546                        return -EINVAL);
 547
 548                dpm_table->dpm_levels[i].value = clock;
 549        }
 550
 551        vega12_init_dpm_state(&(dpm_table->dpm_state));
 552
 553        dpm_table = &(data->dpm_table.gfx_table);
 554
 555        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_GFXCLK,
 556                &num_levels) == 0,
 557                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for GFXCLK!",
 558                return -EINVAL);
 559
 560        dpm_table->count = num_levels;
 561        for (i = 0; i < num_levels; i++) {
 562                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 563                        PPCLK_GFXCLK, i, &clock) == 0,
 564                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for GFXCLK!",
 565                        return -EINVAL);
 566
 567                dpm_table->dpm_levels[i].value = clock;
 568        }
 569
 570        vega12_init_dpm_state(&(dpm_table->dpm_state));
 571        /* Initialize Mclk DPM table based on allow Mclk values */
 572        dpm_table = &(data->dpm_table.mem_table);
 573
 574        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_UCLK,
 575                &num_levels) == 0,
 576                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for UCLK!",
 577                return -EINVAL);
 578
 579        dpm_table->count = num_levels;
 580
 581        for (i = 0; i < num_levels; i++) {
 582                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 583                        PPCLK_UCLK, i, &clock) == 0,
 584                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for UCLK!",
 585                        return -EINVAL);
 586
 587                dpm_table->dpm_levels[i].value = clock;
 588        }
 589
 590        vega12_init_dpm_state(&(dpm_table->dpm_state));
 591
 592        dpm_table = &(data->dpm_table.eclk_table);
 593
 594        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_ECLK,
 595                &num_levels) == 0,
 596                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for ECLK!",
 597                return -EINVAL);
 598
 599        dpm_table->count = num_levels;
 600
 601        for (i = 0; i < num_levels; i++) {
 602                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 603                PPCLK_ECLK, i, &clock) == 0,
 604                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for ECLK!",
 605                return -EINVAL);
 606
 607                dpm_table->dpm_levels[i].value = clock;
 608        }
 609
 610        vega12_init_dpm_state(&(dpm_table->dpm_state));
 611
 612        dpm_table = &(data->dpm_table.vclk_table);
 613
 614        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_VCLK,
 615                &num_levels) == 0,
 616                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for VCLK!",
 617                return -EINVAL);
 618
 619        dpm_table->count = num_levels;
 620
 621        for (i = 0; i < num_levels; i++) {
 622                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 623                        PPCLK_VCLK, i, &clock) == 0,
 624                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for VCLK!",
 625                        return -EINVAL);
 626
 627                dpm_table->dpm_levels[i].value = clock;
 628        }
 629
 630        vega12_init_dpm_state(&(dpm_table->dpm_state));
 631
 632        dpm_table = &(data->dpm_table.dclk_table);
 633
 634        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr, PPCLK_DCLK,
 635                &num_levels) == 0,
 636                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DCLK!",
 637                return -EINVAL);
 638
 639        dpm_table->count = num_levels;
 640
 641        for (i = 0; i < num_levels; i++) {
 642                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 643                        PPCLK_DCLK, i, &clock) == 0,
 644                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DCLK!",
 645                return -EINVAL);
 646
 647                dpm_table->dpm_levels[i].value = clock;
 648        }
 649
 650        vega12_init_dpm_state(&(dpm_table->dpm_state));
 651
 652        /* Assume there is no headless Vega12 for now */
 653        dpm_table = &(data->dpm_table.dcef_table);
 654
 655        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr,
 656                PPCLK_DCEFCLK, &num_levels) == 0,
 657                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DCEFCLK!",
 658                return -EINVAL);
 659
 660        dpm_table->count = num_levels;
 661
 662        for (i = 0; i < num_levels; i++) {
 663                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 664                        PPCLK_DCEFCLK, i, &clock) == 0,
 665                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DCEFCLK!",
 666                        return -EINVAL);
 667
 668                dpm_table->dpm_levels[i].value = clock;
 669        }
 670
 671        vega12_init_dpm_state(&(dpm_table->dpm_state));
 672
 673        dpm_table = &(data->dpm_table.pixel_table);
 674
 675        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr,
 676                PPCLK_PIXCLK, &num_levels) == 0,
 677                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for PIXCLK!",
 678                return -EINVAL);
 679
 680        dpm_table->count = num_levels;
 681
 682        for (i = 0; i < num_levels; i++) {
 683                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 684                        PPCLK_PIXCLK, i, &clock) == 0,
 685                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for PIXCLK!",
 686                        return -EINVAL);
 687
 688                dpm_table->dpm_levels[i].value = clock;
 689        }
 690
 691        vega12_init_dpm_state(&(dpm_table->dpm_state));
 692
 693        dpm_table = &(data->dpm_table.display_table);
 694
 695        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr,
 696                PPCLK_DISPCLK, &num_levels) == 0,
 697                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DISPCLK!",
 698                return -EINVAL);
 699
 700        dpm_table->count = num_levels;
 701
 702        for (i = 0; i < num_levels; i++) {
 703                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 704                        PPCLK_DISPCLK, i, &clock) == 0,
 705                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for DISPCLK!",
 706                        return -EINVAL);
 707
 708                dpm_table->dpm_levels[i].value = clock;
 709        }
 710
 711        vega12_init_dpm_state(&(dpm_table->dpm_state));
 712
 713        dpm_table = &(data->dpm_table.phy_table);
 714
 715        PP_ASSERT_WITH_CODE(vega12_get_number_dpm_level(hwmgr,
 716                PPCLK_PHYCLK, &num_levels) == 0,
 717                "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for PHYCLK!",
 718                return -EINVAL);
 719
 720        dpm_table->count = num_levels;
 721
 722        for (i = 0; i < num_levels; i++) {
 723                PP_ASSERT_WITH_CODE(vega12_get_dpm_frequency_by_index(hwmgr,
 724                        PPCLK_PHYCLK, i, &clock) == 0,
 725                        "[SetupDefaultDPMTables] Failed to get DPM levels from SMU for PHYCLK!",
 726                        return -EINVAL);
 727
 728                dpm_table->dpm_levels[i].value = clock;
 729        }
 730
 731        vega12_init_dpm_state(&(dpm_table->dpm_state));
 732
 733        /* save a copy of the default DPM table */
 734        memcpy(&(data->golden_dpm_table), &(data->dpm_table),
 735                        sizeof(struct vega12_dpm_table));
 736
 737        return 0;
 738}
 739
 740#if 0
 741static int vega12_save_default_power_profile(struct pp_hwmgr *hwmgr)
 742{
 743        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
 744        struct vega12_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
 745        uint32_t min_level;
 746
 747        hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
 748        hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
 749
 750        /* Optimize compute power profile: Use only highest
 751         * 2 power levels (if more than 2 are available)
 752         */
 753        if (dpm_table->count > 2)
 754                min_level = dpm_table->count - 2;
 755        else if (dpm_table->count == 2)
 756                min_level = 1;
 757        else
 758                min_level = 0;
 759
 760        hwmgr->default_compute_power_profile.min_sclk =
 761                        dpm_table->dpm_levels[min_level].value;
 762
 763        hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
 764        hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
 765
 766        return 0;
 767}
 768#endif
 769
 770/**
 771* Initializes the SMC table and uploads it
 772*
 773* @param    hwmgr  the address of the powerplay hardware manager.
 774* @param    pInput  the pointer to input data (PowerState)
 775* @return   always 0
 776*/
 777static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
 778{
 779        int result;
 780        struct vega12_hwmgr *data =
 781                        (struct vega12_hwmgr *)(hwmgr->backend);
 782        PPTable_t *pp_table = &(data->smc_state_table.pp_table);
 783        struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
 784        struct phm_ppt_v3_information *pptable_information =
 785                (struct phm_ppt_v3_information *)hwmgr->pptable;
 786
 787        result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
 788        if (!result) {
 789                data->vbios_boot_state.vddc     = boot_up_values.usVddc;
 790                data->vbios_boot_state.vddci    = boot_up_values.usVddci;
 791                data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
 792                data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
 793                data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
 794                data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
 795                data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
 796                data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
 797                smum_send_msg_to_smc_with_parameter(hwmgr,
 798                                PPSMC_MSG_SetMinDeepSleepDcefclk,
 799                        (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
 800        }
 801
 802        memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
 803
 804        result = vega12_copy_table_to_smc(hwmgr,
 805                        (uint8_t *)pp_table, TABLE_PPTABLE);
 806        PP_ASSERT_WITH_CODE(!result,
 807                        "Failed to upload PPtable!", return result);
 808
 809        return 0;
 810}
 811
 812static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 813{
 814        struct vega12_hwmgr *data =
 815                        (struct vega12_hwmgr *)(hwmgr->backend);
 816        int i;
 817        uint32_t allowed_features_low = 0, allowed_features_high = 0;
 818
 819        for (i = 0; i < GNLD_FEATURES_MAX; i++)
 820                if (data->smu_features[i].allowed)
 821                        data->smu_features[i].smu_feature_id > 31 ?
 822                                (allowed_features_high |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) & 0xFFFFFFFF)) :
 823                                (allowed_features_low |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) & 0xFFFFFFFF));
 824
 825        PP_ASSERT_WITH_CODE(
 826                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high) == 0,
 827                "[SetAllowedFeaturesMask] Attempt to set allowed features mask (high) failed!",
 828                return -1);
 829
 830        PP_ASSERT_WITH_CODE(
 831                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low) == 0,
 832                "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
 833                return -1);
 834
 835        return 0;
 836}
 837
 838static int vega12_enable_all_smu_features(struct pp_hwmgr *hwmgr)
 839{
 840        struct vega12_hwmgr *data =
 841                        (struct vega12_hwmgr *)(hwmgr->backend);
 842        uint64_t features_enabled;
 843        int i;
 844        bool enabled;
 845
 846        PP_ASSERT_WITH_CODE(
 847                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAllSmuFeatures) == 0,
 848                "[EnableAllSMUFeatures] Failed to enable all smu features!",
 849                return -1);
 850
 851        if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) {
 852                for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 853                        enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false;
 854                        data->smu_features[i].enabled = enabled;
 855                        data->smu_features[i].supported = enabled;
 856                        PP_ASSERT(
 857                                !data->smu_features[i].allowed || enabled,
 858                                "[EnableAllSMUFeatures] Enabled feature is different from allowed, expected disabled!");
 859                }
 860        }
 861
 862        return 0;
 863}
 864
 865static int vega12_disable_all_smu_features(struct pp_hwmgr *hwmgr)
 866{
 867        struct vega12_hwmgr *data =
 868                        (struct vega12_hwmgr *)(hwmgr->backend);
 869        uint64_t features_enabled;
 870        int i;
 871        bool enabled;
 872
 873        PP_ASSERT_WITH_CODE(
 874                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures) == 0,
 875                "[DisableAllSMUFeatures] Failed to disable all smu features!",
 876                return -1);
 877
 878        if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) {
 879                for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 880                        enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false;
 881                        data->smu_features[i].enabled = enabled;
 882                        data->smu_features[i].supported = enabled;
 883                }
 884        }
 885
 886        return 0;
 887}
 888
 889static int vega12_odn_initialize_default_settings(
 890                struct pp_hwmgr *hwmgr)
 891{
 892        return 0;
 893}
 894
 895static int vega12_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr,
 896                uint32_t adjust_percent)
 897{
 898        return smum_send_msg_to_smc_with_parameter(hwmgr,
 899                        PPSMC_MSG_OverDriveSetPercentage, adjust_percent);
 900}
 901
 902static int vega12_power_control_set_level(struct pp_hwmgr *hwmgr)
 903{
 904        int adjust_percent, result = 0;
 905
 906        if (PP_CAP(PHM_PlatformCaps_PowerContainment)) {
 907                adjust_percent =
 908                                hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
 909                                hwmgr->platform_descriptor.TDPAdjustment :
 910                                (-1 * hwmgr->platform_descriptor.TDPAdjustment);
 911                result = vega12_set_overdrive_target_percentage(hwmgr,
 912                                (uint32_t)adjust_percent);
 913        }
 914        return result;
 915}
 916
 917static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
 918{
 919        int tmp_result, result = 0;
 920
 921        smum_send_msg_to_smc_with_parameter(hwmgr,
 922                        PPSMC_MSG_NumOfDisplays, 0);
 923
 924        result = vega12_set_allowed_featuresmask(hwmgr);
 925        PP_ASSERT_WITH_CODE(result == 0,
 926                        "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
 927                        return result);
 928
 929        tmp_result = vega12_init_smc_table(hwmgr);
 930        PP_ASSERT_WITH_CODE(!tmp_result,
 931                        "Failed to initialize SMC table!",
 932                        result = tmp_result);
 933
 934        result = vega12_enable_all_smu_features(hwmgr);
 935        PP_ASSERT_WITH_CODE(!result,
 936                        "Failed to enable all smu features!",
 937                        return result);
 938
 939        tmp_result = vega12_power_control_set_level(hwmgr);
 940        PP_ASSERT_WITH_CODE(!tmp_result,
 941                        "Failed to power control set level!",
 942                        result = tmp_result);
 943
 944        result = vega12_odn_initialize_default_settings(hwmgr);
 945        PP_ASSERT_WITH_CODE(!result,
 946                        "Failed to power control set level!",
 947                        return result);
 948
 949        result = vega12_setup_default_dpm_tables(hwmgr);
 950        PP_ASSERT_WITH_CODE(!result,
 951                        "Failed to setup default DPM tables!",
 952                        return result);
 953        return result;
 954}
 955
 956static int vega12_patch_boot_state(struct pp_hwmgr *hwmgr,
 957             struct pp_hw_power_state *hw_ps)
 958{
 959        return 0;
 960}
 961
 962static uint32_t vega12_find_lowest_dpm_level(
 963                struct vega12_single_dpm_table *table)
 964{
 965        uint32_t i;
 966
 967        for (i = 0; i < table->count; i++) {
 968                if (table->dpm_levels[i].enabled)
 969                        break;
 970        }
 971
 972        return i;
 973}
 974
 975static uint32_t vega12_find_highest_dpm_level(
 976                struct vega12_single_dpm_table *table)
 977{
 978        uint32_t i = 0;
 979
 980        if (table->count <= MAX_REGULAR_DPM_NUMBER) {
 981                for (i = table->count; i > 0; i--) {
 982                        if (table->dpm_levels[i - 1].enabled)
 983                                return i - 1;
 984                }
 985        } else {
 986                pr_info("DPM Table Has Too Many Entries!");
 987                return MAX_REGULAR_DPM_NUMBER - 1;
 988        }
 989
 990        return i;
 991}
 992
 993static int vega12_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
 994{
 995        return 0;
 996}
 997
 998static int vega12_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
 999{
1000        return 0;
1001}
1002
1003
1004int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
1005{
1006        struct vega12_hwmgr *data =
1007                        (struct vega12_hwmgr *)(hwmgr->backend);
1008
1009        if (data->smu_features[GNLD_DPM_VCE].supported) {
1010                PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr,
1011                                enable,
1012                                data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap),
1013                                "Attempt to Enable/Disable DPM VCE Failed!",
1014                                return -1);
1015                data->smu_features[GNLD_DPM_VCE].enabled = enable;
1016        }
1017
1018        return 0;
1019}
1020
1021static uint32_t vega12_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
1022{
1023        struct vega12_hwmgr *data =
1024                        (struct vega12_hwmgr *)(hwmgr->backend);
1025        uint32_t gfx_clk;
1026
1027        if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
1028                return -1;
1029
1030        if (low)
1031                PP_ASSERT_WITH_CODE(
1032                        vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false) == 0,
1033                        "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
1034                        return -1);
1035        else
1036                PP_ASSERT_WITH_CODE(
1037                        vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true) == 0,
1038                        "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
1039                        return -1);
1040
1041        return (gfx_clk * 100);
1042}
1043
1044static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
1045{
1046        struct vega12_hwmgr *data =
1047                        (struct vega12_hwmgr *)(hwmgr->backend);
1048        uint32_t mem_clk;
1049
1050        if (!data->smu_features[GNLD_DPM_UCLK].enabled)
1051                return -1;
1052
1053        if (low)
1054                PP_ASSERT_WITH_CODE(
1055                        vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false) == 0,
1056                        "[GetMclks]: fail to get min PPCLK_UCLK\n",
1057                        return -1);
1058        else
1059                PP_ASSERT_WITH_CODE(
1060                        vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true) == 0,
1061                        "[GetMclks]: fail to get max PPCLK_UCLK\n",
1062                        return -1);
1063
1064        return (mem_clk * 100);
1065}
1066
1067static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr,
1068                struct pp_gpu_power *query)
1069{
1070#if 0
1071        uint32_t value;
1072
1073        PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
1074                        PPSMC_MSG_GetCurrPkgPwr),
1075                        "Failed to get current package power!",
1076                        return -EINVAL);
1077
1078        vega12_read_arg_from_smc(hwmgr, &value);
1079        /* power value is an integer */
1080        query->average_gpu_power = value << 8;
1081#endif
1082        return 0;
1083}
1084
1085static int vega12_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq)
1086{
1087        uint32_t gfx_clk = 0;
1088
1089        *gfx_freq = 0;
1090
1091        PP_ASSERT_WITH_CODE(
1092                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16)) == 0,
1093                        "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!",
1094                        return -1);
1095        PP_ASSERT_WITH_CODE(
1096                        vega12_read_arg_from_smc(hwmgr, &gfx_clk) == 0,
1097                        "[GetCurrentGfxClkFreq] Attempt to read arg from SMC Failed",
1098                        return -1);
1099
1100        *gfx_freq = gfx_clk * 100;
1101
1102        return 0;
1103}
1104
1105static int vega12_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq)
1106{
1107        uint32_t mem_clk = 0;
1108
1109        *mclk_freq = 0;
1110
1111        PP_ASSERT_WITH_CODE(
1112                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16)) == 0,
1113                        "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!",
1114                        return -1);
1115        PP_ASSERT_WITH_CODE(
1116                        vega12_read_arg_from_smc(hwmgr, &mem_clk) == 0,
1117                        "[GetCurrentMClkFreq] Attempt to read arg from SMC Failed",
1118                        return -1);
1119
1120        *mclk_freq = mem_clk * 100;
1121
1122        return 0;
1123}
1124
1125static int vega12_get_current_activity_percent(
1126                struct pp_hwmgr *hwmgr,
1127                uint32_t *activity_percent)
1128{
1129        int ret = 0;
1130        uint32_t current_activity = 50;
1131
1132#if 0
1133        ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0);
1134        if (!ret) {
1135                ret = vega12_read_arg_from_smc(hwmgr, &current_activity);
1136                if (!ret) {
1137                        if (current_activity > 100) {
1138                                PP_ASSERT(false,
1139                                        "[GetCurrentActivityPercent] Activity Percentage Exceeds 100!");
1140                                current_activity = 100;
1141                        }
1142                } else
1143                        PP_ASSERT(false,
1144                                "[GetCurrentActivityPercent] Attempt To Read Average Graphics Activity from SMU Failed!");
1145        } else
1146                PP_ASSERT(false,
1147                        "[GetCurrentActivityPercent] Attempt To Send Get Average Graphics Activity to SMU Failed!");
1148#endif
1149        *activity_percent = current_activity;
1150
1151        return ret;
1152}
1153
1154static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1155                              void *value, int *size)
1156{
1157        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1158        int ret = 0;
1159
1160        switch (idx) {
1161        case AMDGPU_PP_SENSOR_GFX_SCLK:
1162                ret = vega12_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value);
1163                if (!ret)
1164                        *size = 4;
1165                break;
1166        case AMDGPU_PP_SENSOR_GFX_MCLK:
1167                ret = vega12_get_current_mclk_freq(hwmgr, (uint32_t *)value);
1168                if (!ret)
1169                        *size = 4;
1170                break;
1171        case AMDGPU_PP_SENSOR_GPU_LOAD:
1172                ret = vega12_get_current_activity_percent(hwmgr, (uint32_t *)value);
1173                if (!ret)
1174                        *size = 4;
1175                break;
1176        case AMDGPU_PP_SENSOR_GPU_TEMP:
1177                *((uint32_t *)value) = vega12_thermal_get_temperature(hwmgr);
1178                *size = 4;
1179                break;
1180        case AMDGPU_PP_SENSOR_UVD_POWER:
1181                *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
1182                *size = 4;
1183                break;
1184        case AMDGPU_PP_SENSOR_VCE_POWER:
1185                *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
1186                *size = 4;
1187                break;
1188        case AMDGPU_PP_SENSOR_GPU_POWER:
1189                if (*size < sizeof(struct pp_gpu_power))
1190                        ret = -EINVAL;
1191                else {
1192                        *size = sizeof(struct pp_gpu_power);
1193                        ret = vega12_get_gpu_power(hwmgr, (struct pp_gpu_power *)value);
1194                }
1195                break;
1196        default:
1197                ret = -EINVAL;
1198                break;
1199        }
1200        return ret;
1201}
1202
1203static int vega12_notify_smc_display_change(struct pp_hwmgr *hwmgr,
1204                bool has_disp)
1205{
1206        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1207
1208        if (data->smu_features[GNLD_DPM_UCLK].enabled)
1209                return smum_send_msg_to_smc_with_parameter(hwmgr,
1210                        PPSMC_MSG_SetUclkFastSwitch,
1211                        has_disp ? 0 : 1);
1212
1213        return 0;
1214}
1215
1216int vega12_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
1217                struct pp_display_clock_request *clock_req)
1218{
1219        int result = 0;
1220        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1221        enum amd_pp_clock_type clk_type = clock_req->clock_type;
1222        uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
1223        PPCLK_e clk_select = 0;
1224        uint32_t clk_request = 0;
1225
1226        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1227                switch (clk_type) {
1228                case amd_pp_dcef_clock:
1229                        clk_freq = clock_req->clock_freq_in_khz / 100;
1230                        clk_select = PPCLK_DCEFCLK;
1231                        break;
1232                case amd_pp_disp_clock:
1233                        clk_select = PPCLK_DISPCLK;
1234                        break;
1235                case amd_pp_pixel_clock:
1236                        clk_select = PPCLK_PIXCLK;
1237                        break;
1238                case amd_pp_phy_clock:
1239                        clk_select = PPCLK_PHYCLK;
1240                        break;
1241                default:
1242                        pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
1243                        result = -1;
1244                        break;
1245                }
1246
1247                if (!result) {
1248                        clk_request = (clk_select << 16) | clk_freq;
1249                        result = smum_send_msg_to_smc_with_parameter(hwmgr,
1250                                        PPSMC_MSG_SetHardMinByFreq,
1251                                        clk_request);
1252                }
1253        }
1254
1255        return result;
1256}
1257
1258static int vega12_notify_smc_display_config_after_ps_adjustment(
1259                struct pp_hwmgr *hwmgr)
1260{
1261        struct vega12_hwmgr *data =
1262                        (struct vega12_hwmgr *)(hwmgr->backend);
1263        uint32_t num_active_disps = 0;
1264        struct cgs_display_info info = {0};
1265        struct PP_Clocks min_clocks = {0};
1266        struct pp_display_clock_request clock_req;
1267        uint32_t clk_request;
1268
1269        info.mode_info = NULL;
1270        cgs_get_active_displays_info(hwmgr->device, &info);
1271        num_active_disps = info.display_count;
1272        if (num_active_disps > 1)
1273                vega12_notify_smc_display_change(hwmgr, false);
1274        else
1275                vega12_notify_smc_display_change(hwmgr, true);
1276
1277        min_clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk;
1278        min_clocks.dcefClockInSR = hwmgr->display_config.min_dcef_deep_sleep_set_clk;
1279        min_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock;
1280
1281        if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
1282                clock_req.clock_type = amd_pp_dcef_clock;
1283                clock_req.clock_freq_in_khz = min_clocks.dcefClock;
1284                if (!vega12_display_clock_voltage_request(hwmgr, &clock_req)) {
1285                        if (data->smu_features[GNLD_DS_DCEFCLK].supported)
1286                                PP_ASSERT_WITH_CODE(
1287                                        !smum_send_msg_to_smc_with_parameter(
1288                                        hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
1289                                        min_clocks.dcefClockInSR /100),
1290                                        "Attempt to set divider for DCEFCLK Failed!",
1291                                        return -1);
1292                } else {
1293                        pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1294                }
1295        }
1296
1297        if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1298                clk_request = (PPCLK_UCLK << 16) | (min_clocks.memoryClock) / 100;
1299                PP_ASSERT_WITH_CODE(
1300                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinByFreq, clk_request) == 0,
1301                        "[PhwVega12_NotifySMCDisplayConfigAfterPowerStateAdjustment] Attempt to set UCLK HardMin Failed!",
1302                        return -1);
1303                data->dpm_table.mem_table.dpm_state.hard_min_level = min_clocks.memoryClock;
1304        }
1305
1306        return 0;
1307}
1308
1309static int vega12_force_dpm_highest(struct pp_hwmgr *hwmgr)
1310{
1311        struct vega12_hwmgr *data =
1312                        (struct vega12_hwmgr *)(hwmgr->backend);
1313
1314        data->smc_state_table.gfx_boot_level =
1315        data->smc_state_table.gfx_max_level =
1316                        vega12_find_highest_dpm_level(&(data->dpm_table.gfx_table));
1317        data->smc_state_table.mem_boot_level =
1318        data->smc_state_table.mem_max_level =
1319                        vega12_find_highest_dpm_level(&(data->dpm_table.mem_table));
1320
1321        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1322                        "Failed to upload boot level to highest!",
1323                        return -1);
1324
1325        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1326                        "Failed to upload dpm max level to highest!",
1327                        return -1);
1328
1329        return 0;
1330}
1331
1332static int vega12_force_dpm_lowest(struct pp_hwmgr *hwmgr)
1333{
1334        struct vega12_hwmgr *data =
1335                        (struct vega12_hwmgr *)(hwmgr->backend);
1336
1337        data->smc_state_table.gfx_boot_level =
1338        data->smc_state_table.gfx_max_level =
1339                        vega12_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
1340        data->smc_state_table.mem_boot_level =
1341        data->smc_state_table.mem_max_level =
1342                        vega12_find_lowest_dpm_level(&(data->dpm_table.mem_table));
1343
1344        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1345                        "Failed to upload boot level to highest!",
1346                        return -1);
1347
1348        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1349                        "Failed to upload dpm max level to highest!",
1350                        return -1);
1351
1352        return 0;
1353
1354}
1355
1356static int vega12_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
1357{
1358        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1359
1360        data->smc_state_table.gfx_boot_level =
1361                        vega12_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
1362        data->smc_state_table.gfx_max_level =
1363                        vega12_find_highest_dpm_level(&(data->dpm_table.gfx_table));
1364        data->smc_state_table.mem_boot_level =
1365                        vega12_find_lowest_dpm_level(&(data->dpm_table.mem_table));
1366        data->smc_state_table.mem_max_level =
1367                        vega12_find_highest_dpm_level(&(data->dpm_table.mem_table));
1368
1369        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1370                        "Failed to upload DPM Bootup Levels!",
1371                        return -1);
1372
1373        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1374                        "Failed to upload DPM Max Levels!",
1375                        return -1);
1376        return 0;
1377}
1378
1379#if 0
1380static int vega12_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
1381                                uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
1382{
1383        struct phm_ppt_v2_information *table_info =
1384                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
1385
1386        if (table_info->vdd_dep_on_sclk->count > VEGA12_UMD_PSTATE_GFXCLK_LEVEL &&
1387                table_info->vdd_dep_on_socclk->count > VEGA12_UMD_PSTATE_SOCCLK_LEVEL &&
1388                table_info->vdd_dep_on_mclk->count > VEGA12_UMD_PSTATE_MCLK_LEVEL) {
1389                *sclk_mask = VEGA12_UMD_PSTATE_GFXCLK_LEVEL;
1390                *soc_mask = VEGA12_UMD_PSTATE_SOCCLK_LEVEL;
1391                *mclk_mask = VEGA12_UMD_PSTATE_MCLK_LEVEL;
1392        }
1393
1394        if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1395                *sclk_mask = 0;
1396        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1397                *mclk_mask = 0;
1398        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1399                *sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
1400                *soc_mask = table_info->vdd_dep_on_socclk->count - 1;
1401                *mclk_mask = table_info->vdd_dep_on_mclk->count - 1;
1402        }
1403        return 0;
1404}
1405#endif
1406
1407static void vega12_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
1408{
1409        switch (mode) {
1410        case AMD_FAN_CTRL_NONE:
1411                break;
1412        case AMD_FAN_CTRL_MANUAL:
1413                if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
1414                        vega12_fan_ctrl_stop_smc_fan_control(hwmgr);
1415                break;
1416        case AMD_FAN_CTRL_AUTO:
1417                if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
1418                        vega12_fan_ctrl_start_smc_fan_control(hwmgr);
1419                break;
1420        default:
1421                break;
1422        }
1423}
1424
1425static int vega12_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
1426                                enum amd_dpm_forced_level level)
1427{
1428        int ret = 0;
1429#if 0
1430        uint32_t sclk_mask = 0;
1431        uint32_t mclk_mask = 0;
1432        uint32_t soc_mask = 0;
1433#endif
1434
1435        switch (level) {
1436        case AMD_DPM_FORCED_LEVEL_HIGH:
1437                ret = vega12_force_dpm_highest(hwmgr);
1438                break;
1439        case AMD_DPM_FORCED_LEVEL_LOW:
1440                ret = vega12_force_dpm_lowest(hwmgr);
1441                break;
1442        case AMD_DPM_FORCED_LEVEL_AUTO:
1443                ret = vega12_unforce_dpm_levels(hwmgr);
1444                break;
1445        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1446        case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1447        case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1448        case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1449#if 0
1450                ret = vega12_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
1451                if (ret)
1452                        return ret;
1453                vega12_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
1454                vega12_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
1455#endif
1456                break;
1457        case AMD_DPM_FORCED_LEVEL_MANUAL:
1458        case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1459        default:
1460                break;
1461        }
1462#if 0
1463        if (!ret) {
1464                if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1465                        vega12_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE);
1466                else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1467                        vega12_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO);
1468        }
1469#endif
1470        return ret;
1471}
1472
1473static uint32_t vega12_get_fan_control_mode(struct pp_hwmgr *hwmgr)
1474{
1475        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1476
1477        if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
1478                return AMD_FAN_CTRL_MANUAL;
1479        else
1480                return AMD_FAN_CTRL_AUTO;
1481}
1482
1483static int vega12_get_dal_power_level(struct pp_hwmgr *hwmgr,
1484                struct amd_pp_simple_clock_info *info)
1485{
1486#if 0
1487        struct phm_ppt_v2_information *table_info =
1488                        (struct phm_ppt_v2_information *)hwmgr->pptable;
1489        struct phm_clock_and_voltage_limits *max_limits =
1490                        &table_info->max_clock_voltage_on_ac;
1491
1492        info->engine_max_clock = max_limits->sclk;
1493        info->memory_max_clock = max_limits->mclk;
1494#endif
1495        return 0;
1496}
1497
1498static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr,
1499                uint32_t *clock,
1500                PPCLK_e clock_select,
1501                bool max)
1502{
1503        int result;
1504        *clock = 0;
1505
1506        if (max) {
1507                 PP_ASSERT_WITH_CODE(
1508                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16)) == 0,
1509                        "[GetClockRanges] Failed to get max clock from SMC!",
1510                        return -1);
1511                result = vega12_read_arg_from_smc(hwmgr, clock);
1512        } else {
1513                PP_ASSERT_WITH_CODE(
1514                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMinDpmFreq, (clock_select << 16)) == 0,
1515                        "[GetClockRanges] Failed to get min clock from SMC!",
1516                        return -1);
1517                result = vega12_read_arg_from_smc(hwmgr, clock);
1518        }
1519
1520        return result;
1521}
1522
1523static int vega12_get_sclks(struct pp_hwmgr *hwmgr,
1524                struct pp_clock_levels_with_latency *clocks)
1525{
1526        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1527        uint32_t ucount;
1528        int i;
1529        struct vega12_single_dpm_table *dpm_table;
1530
1531        if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
1532                return -1;
1533
1534        dpm_table = &(data->dpm_table.gfx_table);
1535        ucount = (dpm_table->count > VG12_PSUEDO_NUM_GFXCLK_DPM_LEVELS) ?
1536                VG12_PSUEDO_NUM_GFXCLK_DPM_LEVELS : dpm_table->count;
1537
1538        for (i = 0; i < ucount; i++) {
1539                clocks->data[i].clocks_in_khz =
1540                        dpm_table->dpm_levels[i].value * 100;
1541
1542                clocks->data[i].latency_in_us = 0;
1543        }
1544
1545        clocks->num_levels = ucount;
1546
1547        return 0;
1548}
1549
1550static uint32_t vega12_get_mem_latency(struct pp_hwmgr *hwmgr,
1551                uint32_t clock)
1552{
1553        return 25;
1554}
1555
1556static int vega12_get_memclocks(struct pp_hwmgr *hwmgr,
1557                struct pp_clock_levels_with_latency *clocks)
1558{
1559        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1560        uint32_t ucount;
1561        int i;
1562        struct vega12_single_dpm_table *dpm_table;
1563        if (!data->smu_features[GNLD_DPM_UCLK].enabled)
1564                return -1;
1565
1566        dpm_table = &(data->dpm_table.mem_table);
1567        ucount = (dpm_table->count > VG12_PSUEDO_NUM_UCLK_DPM_LEVELS) ?
1568                VG12_PSUEDO_NUM_UCLK_DPM_LEVELS : dpm_table->count;
1569
1570        for (i = 0; i < ucount; i++) {
1571                clocks->data[i].clocks_in_khz =
1572                        dpm_table->dpm_levels[i].value * 100;
1573
1574                clocks->data[i].latency_in_us =
1575                        data->mclk_latency_table.entries[i].latency =
1576                        vega12_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
1577        }
1578
1579        clocks->num_levels = data->mclk_latency_table.count = ucount;
1580
1581        return 0;
1582}
1583
1584static int vega12_get_dcefclocks(struct pp_hwmgr *hwmgr,
1585                struct pp_clock_levels_with_latency *clocks)
1586{
1587        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1588        uint32_t ucount;
1589        int i;
1590        struct vega12_single_dpm_table *dpm_table;
1591
1592        if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled)
1593                return -1;
1594
1595
1596        dpm_table = &(data->dpm_table.dcef_table);
1597        ucount = (dpm_table->count > VG12_PSUEDO_NUM_DCEFCLK_DPM_LEVELS) ?
1598                VG12_PSUEDO_NUM_DCEFCLK_DPM_LEVELS : dpm_table->count;
1599
1600        for (i = 0; i < ucount; i++) {
1601                clocks->data[i].clocks_in_khz =
1602                        dpm_table->dpm_levels[i].value * 100;
1603
1604                clocks->data[i].latency_in_us = 0;
1605        }
1606
1607        clocks->num_levels = ucount;
1608
1609        return 0;
1610}
1611
1612static int vega12_get_socclocks(struct pp_hwmgr *hwmgr,
1613                struct pp_clock_levels_with_latency *clocks)
1614{
1615        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1616        uint32_t ucount;
1617        int i;
1618        struct vega12_single_dpm_table *dpm_table;
1619
1620        if (!data->smu_features[GNLD_DPM_SOCCLK].enabled)
1621                return -1;
1622
1623
1624        dpm_table = &(data->dpm_table.soc_table);
1625        ucount = (dpm_table->count > VG12_PSUEDO_NUM_SOCCLK_DPM_LEVELS) ?
1626                VG12_PSUEDO_NUM_SOCCLK_DPM_LEVELS : dpm_table->count;
1627
1628        for (i = 0; i < ucount; i++) {
1629                clocks->data[i].clocks_in_khz =
1630                        dpm_table->dpm_levels[i].value * 100;
1631
1632                clocks->data[i].latency_in_us = 0;
1633        }
1634
1635        clocks->num_levels = ucount;
1636
1637        return 0;
1638
1639}
1640
1641static int vega12_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
1642                enum amd_pp_clock_type type,
1643                struct pp_clock_levels_with_latency *clocks)
1644{
1645        int ret;
1646
1647        switch (type) {
1648        case amd_pp_sys_clock:
1649                ret = vega12_get_sclks(hwmgr, clocks);
1650                break;
1651        case amd_pp_mem_clock:
1652                ret = vega12_get_memclocks(hwmgr, clocks);
1653                break;
1654        case amd_pp_dcef_clock:
1655                ret = vega12_get_dcefclocks(hwmgr, clocks);
1656                break;
1657        case amd_pp_soc_clock:
1658                ret = vega12_get_socclocks(hwmgr, clocks);
1659                break;
1660        default:
1661                return -EINVAL;
1662        }
1663
1664        return ret;
1665}
1666
1667static int vega12_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
1668                enum amd_pp_clock_type type,
1669                struct pp_clock_levels_with_voltage *clocks)
1670{
1671        clocks->num_levels = 0;
1672
1673        return 0;
1674}
1675
1676static int vega12_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
1677                struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1678{
1679        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1680        Watermarks_t *table = &(data->smc_state_table.water_marks_table);
1681        int result = 0;
1682        uint32_t i;
1683
1684        if (!data->registry_data.disable_water_mark &&
1685                        data->smu_features[GNLD_DPM_DCEFCLK].supported &&
1686                        data->smu_features[GNLD_DPM_SOCCLK].supported) {
1687                for (i = 0; i < wm_with_clock_ranges->num_wm_sets_dmif; i++) {
1688                        table->WatermarkRow[WM_DCEFCLK][i].MinClock =
1689                                cpu_to_le16((uint16_t)
1690                                (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_dcefclk_in_khz) /
1691                                100);
1692                        table->WatermarkRow[WM_DCEFCLK][i].MaxClock =
1693                                cpu_to_le16((uint16_t)
1694                                (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_dcefclk_in_khz) /
1695                                100);
1696                        table->WatermarkRow[WM_DCEFCLK][i].MinUclk =
1697                                cpu_to_le16((uint16_t)
1698                                (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_memclk_in_khz) /
1699                                100);
1700                        table->WatermarkRow[WM_DCEFCLK][i].MaxUclk =
1701                                cpu_to_le16((uint16_t)
1702                                (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_memclk_in_khz) /
1703                                100);
1704                        table->WatermarkRow[WM_DCEFCLK][i].WmSetting = (uint8_t)
1705                                        wm_with_clock_ranges->wm_sets_dmif[i].wm_set_id;
1706                }
1707
1708                for (i = 0; i < wm_with_clock_ranges->num_wm_sets_mcif; i++) {
1709                        table->WatermarkRow[WM_SOCCLK][i].MinClock =
1710                                cpu_to_le16((uint16_t)
1711                                (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_socclk_in_khz) /
1712                                100);
1713                        table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1714                                cpu_to_le16((uint16_t)
1715                                (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_socclk_in_khz) /
1716                                100);
1717                        table->WatermarkRow[WM_SOCCLK][i].MinUclk =
1718                                cpu_to_le16((uint16_t)
1719                                (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_memclk_in_khz) /
1720                                100);
1721                        table->WatermarkRow[WM_SOCCLK][i].MaxUclk =
1722                                cpu_to_le16((uint16_t)
1723                                (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_memclk_in_khz) /
1724                                100);
1725                        table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t)
1726                                        wm_with_clock_ranges->wm_sets_mcif[i].wm_set_id;
1727                }
1728                data->water_marks_bitmap |= WaterMarksExist;
1729                data->water_marks_bitmap &= ~WaterMarksLoaded;
1730        }
1731
1732        return result;
1733}
1734
1735static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
1736                enum pp_clock_type type, uint32_t mask)
1737{
1738        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1739
1740        if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO |
1741                                AMD_DPM_FORCED_LEVEL_LOW |
1742                                AMD_DPM_FORCED_LEVEL_HIGH))
1743                return -EINVAL;
1744
1745        switch (type) {
1746        case PP_SCLK:
1747                data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0;
1748                data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0;
1749
1750                PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1751                        "Failed to upload boot level to lowest!",
1752                        return -EINVAL);
1753
1754                PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1755                        "Failed to upload dpm max level to highest!",
1756                        return -EINVAL);
1757                break;
1758
1759        case PP_MCLK:
1760                data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0;
1761                data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0;
1762
1763                PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1764                        "Failed to upload boot level to lowest!",
1765                        return -EINVAL);
1766
1767                PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1768                        "Failed to upload dpm max level to highest!",
1769                        return -EINVAL);
1770
1771                break;
1772
1773        case PP_PCIE:
1774                break;
1775
1776        default:
1777                break;
1778        }
1779
1780        return 0;
1781}
1782
1783static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
1784                enum pp_clock_type type, char *buf)
1785{
1786        int i, now, size = 0;
1787        struct pp_clock_levels_with_latency clocks;
1788
1789        switch (type) {
1790        case PP_SCLK:
1791                PP_ASSERT_WITH_CODE(
1792                                vega12_get_current_gfx_clk_freq(hwmgr, &now) == 0,
1793                                "Attempt to get current gfx clk Failed!",
1794                                return -1);
1795
1796                PP_ASSERT_WITH_CODE(
1797                                vega12_get_sclks(hwmgr, &clocks) == 0,
1798                                "Attempt to get gfx clk levels Failed!",
1799                                return -1);
1800                for (i = 0; i < clocks.num_levels; i++)
1801                        size += sprintf(buf + size, "%d: %uMhz %s\n",
1802                                i, clocks.data[i].clocks_in_khz / 100,
1803                                (clocks.data[i].clocks_in_khz == now) ? "*" : "");
1804                break;
1805
1806        case PP_MCLK:
1807                PP_ASSERT_WITH_CODE(
1808                                vega12_get_current_mclk_freq(hwmgr, &now) == 0,
1809                                "Attempt to get current mclk freq Failed!",
1810                                return -1);
1811
1812                PP_ASSERT_WITH_CODE(
1813                                vega12_get_memclocks(hwmgr, &clocks) == 0,
1814                                "Attempt to get memory clk levels Failed!",
1815                                return -1);
1816                for (i = 0; i < clocks.num_levels; i++)
1817                        size += sprintf(buf + size, "%d: %uMhz %s\n",
1818                                i, clocks.data[i].clocks_in_khz / 100,
1819                                (clocks.data[i].clocks_in_khz == now) ? "*" : "");
1820                break;
1821
1822        case PP_PCIE:
1823                break;
1824
1825        default:
1826                break;
1827        }
1828        return size;
1829}
1830
1831static int vega12_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
1832{
1833        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1834        int result = 0;
1835        uint32_t num_turned_on_displays = 1;
1836        Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
1837        struct cgs_display_info info = {0};
1838
1839        if ((data->water_marks_bitmap & WaterMarksExist) &&
1840                        !(data->water_marks_bitmap & WaterMarksLoaded)) {
1841                result = vega12_copy_table_to_smc(hwmgr,
1842                        (uint8_t *)wm_table, TABLE_WATERMARKS);
1843                PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL);
1844                data->water_marks_bitmap |= WaterMarksLoaded;
1845        }
1846
1847        if ((data->water_marks_bitmap & WaterMarksExist) &&
1848                data->smu_features[GNLD_DPM_DCEFCLK].supported &&
1849                data->smu_features[GNLD_DPM_SOCCLK].supported) {
1850                cgs_get_active_displays_info(hwmgr->device, &info);
1851                num_turned_on_displays = info.display_count;
1852                smum_send_msg_to_smc_with_parameter(hwmgr,
1853                        PPSMC_MSG_NumOfDisplays, num_turned_on_displays);
1854        }
1855
1856        return result;
1857}
1858
1859int vega12_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
1860{
1861        struct vega12_hwmgr *data =
1862                        (struct vega12_hwmgr *)(hwmgr->backend);
1863
1864        if (data->smu_features[GNLD_DPM_UVD].supported) {
1865                PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr,
1866                                enable,
1867                                data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap),
1868                                "Attempt to Enable/Disable DPM UVD Failed!",
1869                                return -1);
1870                data->smu_features[GNLD_DPM_UVD].enabled = enable;
1871        }
1872
1873        return 0;
1874}
1875
1876static void vega12_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
1877{
1878        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1879
1880        data->vce_power_gated = bgate;
1881        vega12_enable_disable_vce_dpm(hwmgr, !bgate);
1882}
1883
1884static void vega12_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
1885{
1886        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1887
1888        data->uvd_power_gated = bgate;
1889        vega12_enable_disable_uvd_dpm(hwmgr, !bgate);
1890}
1891
1892static bool
1893vega12_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
1894{
1895        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1896        bool is_update_required = false;
1897        struct cgs_display_info info = {0, 0, NULL};
1898
1899        cgs_get_active_displays_info(hwmgr->device, &info);
1900
1901        if (data->display_timing.num_existing_displays != info.display_count)
1902                is_update_required = true;
1903
1904        if (data->registry_data.gfx_clk_deep_sleep_support) {
1905                if (data->display_timing.min_clock_in_sr != hwmgr->display_config.min_core_set_clock_in_sr)
1906                        is_update_required = true;
1907        }
1908
1909        return is_update_required;
1910}
1911
1912static int vega12_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
1913{
1914        int tmp_result, result = 0;
1915
1916        tmp_result = vega12_disable_all_smu_features(hwmgr);
1917        PP_ASSERT_WITH_CODE((tmp_result == 0),
1918                        "Failed to disable all smu features!", result = tmp_result);
1919
1920        return result;
1921}
1922
1923static int vega12_power_off_asic(struct pp_hwmgr *hwmgr)
1924{
1925        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1926        int result;
1927
1928        result = vega12_disable_dpm_tasks(hwmgr);
1929        PP_ASSERT_WITH_CODE((0 == result),
1930                        "[disable_dpm_tasks] Failed to disable DPM!",
1931                        );
1932        data->water_marks_bitmap &= ~(WaterMarksLoaded);
1933
1934        return result;
1935}
1936
1937#if 0
1938static void vega12_find_min_clock_index(struct pp_hwmgr *hwmgr,
1939                uint32_t *sclk_idx, uint32_t *mclk_idx,
1940                uint32_t min_sclk, uint32_t min_mclk)
1941{
1942        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1943        struct vega12_dpm_table *dpm_table = &(data->dpm_table);
1944        uint32_t i;
1945
1946        for (i = 0; i < dpm_table->gfx_table.count; i++) {
1947                if (dpm_table->gfx_table.dpm_levels[i].enabled &&
1948                        dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) {
1949                        *sclk_idx = i;
1950                        break;
1951                }
1952        }
1953
1954        for (i = 0; i < dpm_table->mem_table.count; i++) {
1955                if (dpm_table->mem_table.dpm_levels[i].enabled &&
1956                        dpm_table->mem_table.dpm_levels[i].value >= min_mclk) {
1957                        *mclk_idx = i;
1958                        break;
1959                }
1960        }
1961}
1962#endif
1963
1964#if 0
1965static int vega12_set_power_profile_state(struct pp_hwmgr *hwmgr,
1966                struct amd_pp_profile *request)
1967{
1968        return 0;
1969}
1970
1971static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)
1972{
1973        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1974        struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
1975        struct vega12_single_dpm_table *golden_sclk_table =
1976                        &(data->golden_dpm_table.gfx_table);
1977        int value;
1978
1979        value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
1980                        golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
1981                        100 /
1982                        golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
1983
1984        return value;
1985}
1986
1987static int vega12_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
1988{
1989        return 0;
1990}
1991
1992static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)
1993{
1994        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1995        struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
1996        struct vega12_single_dpm_table *golden_mclk_table =
1997                        &(data->golden_dpm_table.mem_table);
1998        int value;
1999
2000        value = (mclk_table->dpm_levels
2001                        [mclk_table->count - 1].value -
2002                        golden_mclk_table->dpm_levels
2003                        [golden_mclk_table->count - 1].value) *
2004                        100 /
2005                        golden_mclk_table->dpm_levels
2006                        [golden_mclk_table->count - 1].value;
2007
2008        return value;
2009}
2010
2011static int vega12_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
2012{
2013        return 0;
2014}
2015#endif
2016
2017static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
2018                                        uint32_t virtual_addr_low,
2019                                        uint32_t virtual_addr_hi,
2020                                        uint32_t mc_addr_low,
2021                                        uint32_t mc_addr_hi,
2022                                        uint32_t size)
2023{
2024        smum_send_msg_to_smc_with_parameter(hwmgr,
2025                                        PPSMC_MSG_SetSystemVirtualDramAddrHigh,
2026                                        virtual_addr_hi);
2027        smum_send_msg_to_smc_with_parameter(hwmgr,
2028                                        PPSMC_MSG_SetSystemVirtualDramAddrLow,
2029                                        virtual_addr_low);
2030        smum_send_msg_to_smc_with_parameter(hwmgr,
2031                                        PPSMC_MSG_DramLogSetDramAddrHigh,
2032                                        mc_addr_hi);
2033
2034        smum_send_msg_to_smc_with_parameter(hwmgr,
2035                                        PPSMC_MSG_DramLogSetDramAddrLow,
2036                                        mc_addr_low);
2037
2038        smum_send_msg_to_smc_with_parameter(hwmgr,
2039                                        PPSMC_MSG_DramLogSetDramSize,
2040                                        size);
2041        return 0;
2042}
2043
2044static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
2045                struct PP_TemperatureRange *thermal_data)
2046{
2047        struct phm_ppt_v3_information *pptable_information =
2048                (struct phm_ppt_v3_information *)hwmgr->pptable;
2049
2050        memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
2051
2052        thermal_data->max = pptable_information->us_software_shutdown_temp *
2053                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2054
2055        return 0;
2056}
2057
2058static const struct pp_hwmgr_func vega12_hwmgr_funcs = {
2059        .backend_init = vega12_hwmgr_backend_init,
2060        .backend_fini = vega12_hwmgr_backend_fini,
2061        .asic_setup = vega12_setup_asic_task,
2062        .dynamic_state_management_enable = vega12_enable_dpm_tasks,
2063        .dynamic_state_management_disable = vega12_disable_dpm_tasks,
2064        .patch_boot_state = vega12_patch_boot_state,
2065        .get_sclk = vega12_dpm_get_sclk,
2066        .get_mclk = vega12_dpm_get_mclk,
2067        .notify_smc_display_config_after_ps_adjustment =
2068                        vega12_notify_smc_display_config_after_ps_adjustment,
2069        .force_dpm_level = vega12_dpm_force_dpm_level,
2070        .stop_thermal_controller = vega12_thermal_stop_thermal_controller,
2071        .get_fan_speed_info = vega12_fan_ctrl_get_fan_speed_info,
2072        .reset_fan_speed_to_default =
2073                        vega12_fan_ctrl_reset_fan_speed_to_default,
2074        .get_fan_speed_rpm = vega12_fan_ctrl_get_fan_speed_rpm,
2075        .set_fan_control_mode = vega12_set_fan_control_mode,
2076        .get_fan_control_mode = vega12_get_fan_control_mode,
2077        .read_sensor = vega12_read_sensor,
2078        .get_dal_power_level = vega12_get_dal_power_level,
2079        .get_clock_by_type_with_latency = vega12_get_clock_by_type_with_latency,
2080        .get_clock_by_type_with_voltage = vega12_get_clock_by_type_with_voltage,
2081        .set_watermarks_for_clocks_ranges = vega12_set_watermarks_for_clocks_ranges,
2082        .display_clock_voltage_request = vega12_display_clock_voltage_request,
2083        .force_clock_level = vega12_force_clock_level,
2084        .print_clock_levels = vega12_print_clock_levels,
2085        .display_config_changed = vega12_display_configuration_changed_task,
2086        .powergate_uvd = vega12_power_gate_uvd,
2087        .powergate_vce = vega12_power_gate_vce,
2088        .check_smc_update_required_for_display_configuration =
2089                        vega12_check_smc_update_required_for_display_configuration,
2090        .power_off_asic = vega12_power_off_asic,
2091        .disable_smc_firmware_ctf = vega12_thermal_disable_alert,
2092#if 0
2093        .set_power_profile_state = vega12_set_power_profile_state,
2094        .get_sclk_od = vega12_get_sclk_od,
2095        .set_sclk_od = vega12_set_sclk_od,
2096        .get_mclk_od = vega12_get_mclk_od,
2097        .set_mclk_od = vega12_set_mclk_od,
2098#endif
2099        .notify_cac_buffer_info = vega12_notify_cac_buffer_info,
2100        .get_thermal_temperature_range = vega12_get_thermal_temperature_range,
2101        .register_irq_handlers = smu9_register_irq_handlers,
2102        .start_thermal_controller = vega12_start_thermal_controller,
2103};
2104
2105int vega12_hwmgr_init(struct pp_hwmgr *hwmgr)
2106{
2107        hwmgr->hwmgr_func = &vega12_hwmgr_funcs;
2108        hwmgr->pptable_func = &vega12_pptable_funcs;
2109
2110        return 0;
2111}
2112