linux/drivers/gpu/drm/amd/pm/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 "pppcielanes.h"
  38#include "vega12_hwmgr.h"
  39#include "vega12_processpptables.h"
  40#include "vega12_pptable.h"
  41#include "vega12_thermal.h"
  42#include "vega12_ppsmc.h"
  43#include "pp_debug.h"
  44#include "amd_pcie_helpers.h"
  45#include "ppinterrupt.h"
  46#include "pp_overdriver.h"
  47#include "pp_thermal.h"
  48#include "vega12_baco.h"
  49
  50#define smnPCIE_LC_SPEED_CNTL                   0x11140290
  51#define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
  52
  53#define LINK_WIDTH_MAX                          6
  54#define LINK_SPEED_MAX                          3
  55static int link_width[] = {0, 1, 2, 4, 8, 12, 16};
  56static int link_speed[] = {25, 50, 80, 160};
  57
  58static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
  59                enum pp_clock_type type, uint32_t mask);
  60static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr,
  61                uint32_t *clock,
  62                PPCLK_e clock_select,
  63                bool max);
  64
  65static void vega12_set_default_registry_data(struct pp_hwmgr *hwmgr)
  66{
  67        struct vega12_hwmgr *data =
  68                        (struct vega12_hwmgr *)(hwmgr->backend);
  69
  70        data->gfxclk_average_alpha = PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT;
  71        data->socclk_average_alpha = PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT;
  72        data->uclk_average_alpha = PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT;
  73        data->gfx_activity_average_alpha = PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT;
  74        data->lowest_uclk_reserved_for_ulv = PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT;
  75
  76        data->display_voltage_mode = PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT;
  77        data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  78        data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  79        data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  80        data->disp_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  81        data->disp_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  82        data->disp_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  83        data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  84        data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  85        data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  86        data->phy_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  87        data->phy_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  88        data->phy_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT;
  89
  90        data->registry_data.disallowed_features = 0x0;
  91        data->registry_data.od_state_in_dc_support = 0;
  92        data->registry_data.thermal_support = 1;
  93        data->registry_data.skip_baco_hardware = 0;
  94
  95        data->registry_data.log_avfs_param = 0;
  96        data->registry_data.sclk_throttle_low_notification = 1;
  97        data->registry_data.force_dpm_high = 0;
  98        data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
  99
 100        data->registry_data.didt_support = 0;
 101        if (data->registry_data.didt_support) {
 102                data->registry_data.didt_mode = 6;
 103                data->registry_data.sq_ramping_support = 1;
 104                data->registry_data.db_ramping_support = 0;
 105                data->registry_data.td_ramping_support = 0;
 106                data->registry_data.tcp_ramping_support = 0;
 107                data->registry_data.dbr_ramping_support = 0;
 108                data->registry_data.edc_didt_support = 1;
 109                data->registry_data.gc_didt_support = 0;
 110                data->registry_data.psm_didt_support = 0;
 111        }
 112
 113        data->registry_data.pcie_lane_override = 0xff;
 114        data->registry_data.pcie_speed_override = 0xff;
 115        data->registry_data.pcie_clock_override = 0xffffffff;
 116        data->registry_data.regulator_hot_gpio_support = 1;
 117        data->registry_data.ac_dc_switch_gpio_support = 0;
 118        data->registry_data.quick_transition_support = 0;
 119        data->registry_data.zrpm_start_temp = 0xffff;
 120        data->registry_data.zrpm_stop_temp = 0xffff;
 121        data->registry_data.odn_feature_enable = 1;
 122        data->registry_data.disable_water_mark = 0;
 123        data->registry_data.disable_pp_tuning = 0;
 124        data->registry_data.disable_xlpp_tuning = 0;
 125        data->registry_data.disable_workload_policy = 0;
 126        data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
 127        data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
 128        data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
 129        data->registry_data.force_workload_policy_mask = 0;
 130        data->registry_data.disable_3d_fs_detection = 0;
 131        data->registry_data.fps_support = 1;
 132        data->registry_data.disable_auto_wattman = 1;
 133        data->registry_data.auto_wattman_debug = 0;
 134        data->registry_data.auto_wattman_sample_period = 100;
 135        data->registry_data.auto_wattman_threshold = 50;
 136}
 137
 138static int vega12_set_features_platform_caps(struct pp_hwmgr *hwmgr)
 139{
 140        struct vega12_hwmgr *data =
 141                        (struct vega12_hwmgr *)(hwmgr->backend);
 142        struct amdgpu_device *adev = hwmgr->adev;
 143
 144        if (data->vddci_control == VEGA12_VOLTAGE_CONTROL_NONE)
 145                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 146                                PHM_PlatformCaps_ControlVDDCI);
 147
 148        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 149                        PHM_PlatformCaps_TablelessHardwareInterface);
 150
 151        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 152                        PHM_PlatformCaps_EnableSMU7ThermalManagement);
 153
 154        if (adev->pg_flags & AMD_PG_SUPPORT_UVD) {
 155                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 156                                PHM_PlatformCaps_UVDPowerGating);
 157                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 158                                PHM_PlatformCaps_UVDDynamicPowerGating);
 159        }
 160
 161        if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
 162                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 163                                PHM_PlatformCaps_VCEPowerGating);
 164
 165        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 166                        PHM_PlatformCaps_UnTabledHardwareInterface);
 167
 168        if (data->registry_data.odn_feature_enable)
 169                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 170                                PHM_PlatformCaps_ODNinACSupport);
 171        else {
 172                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 173                                PHM_PlatformCaps_OD6inACSupport);
 174                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 175                                PHM_PlatformCaps_OD6PlusinACSupport);
 176        }
 177
 178        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 179                        PHM_PlatformCaps_ActivityReporting);
 180        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 181                        PHM_PlatformCaps_FanSpeedInTableIsRPM);
 182
 183        if (data->registry_data.od_state_in_dc_support) {
 184                if (data->registry_data.odn_feature_enable)
 185                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 186                                        PHM_PlatformCaps_ODNinDCSupport);
 187                else {
 188                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 189                                        PHM_PlatformCaps_OD6inDCSupport);
 190                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 191                                        PHM_PlatformCaps_OD6PlusinDCSupport);
 192                }
 193        }
 194
 195        if (data->registry_data.thermal_support
 196                        && data->registry_data.fuzzy_fan_control_support
 197                        && hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
 198                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 199                                PHM_PlatformCaps_ODFuzzyFanControlSupport);
 200
 201        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 202                                PHM_PlatformCaps_DynamicPowerManagement);
 203        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 204                        PHM_PlatformCaps_SMC);
 205        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 206                        PHM_PlatformCaps_ThermalPolicyDelay);
 207
 208        if (data->registry_data.force_dpm_high)
 209                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 210                                PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
 211
 212        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 213                        PHM_PlatformCaps_DynamicUVDState);
 214
 215        if (data->registry_data.sclk_throttle_low_notification)
 216                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 217                                PHM_PlatformCaps_SclkThrottleLowNotification);
 218
 219        /* power tune caps */
 220        /* assume disabled */
 221        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 222                        PHM_PlatformCaps_PowerContainment);
 223        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 224                        PHM_PlatformCaps_DiDtSupport);
 225        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 226                        PHM_PlatformCaps_SQRamping);
 227        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 228                        PHM_PlatformCaps_DBRamping);
 229        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 230                        PHM_PlatformCaps_TDRamping);
 231        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 232                        PHM_PlatformCaps_TCPRamping);
 233        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 234                        PHM_PlatformCaps_DBRRamping);
 235        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 236                        PHM_PlatformCaps_DiDtEDCEnable);
 237        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 238                        PHM_PlatformCaps_GCEDC);
 239        phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 240                        PHM_PlatformCaps_PSM);
 241
 242        if (data->registry_data.didt_support) {
 243                phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport);
 244                if (data->registry_data.sq_ramping_support)
 245                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping);
 246                if (data->registry_data.db_ramping_support)
 247                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping);
 248                if (data->registry_data.td_ramping_support)
 249                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping);
 250                if (data->registry_data.tcp_ramping_support)
 251                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping);
 252                if (data->registry_data.dbr_ramping_support)
 253                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping);
 254                if (data->registry_data.edc_didt_support)
 255                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable);
 256                if (data->registry_data.gc_didt_support)
 257                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC);
 258                if (data->registry_data.psm_didt_support)
 259                        phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM);
 260        }
 261
 262        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 263                        PHM_PlatformCaps_RegulatorHot);
 264
 265        if (data->registry_data.ac_dc_switch_gpio_support) {
 266                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 267                                PHM_PlatformCaps_AutomaticDCTransition);
 268                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 269                                PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 270        }
 271
 272        if (data->registry_data.quick_transition_support) {
 273                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 274                                PHM_PlatformCaps_AutomaticDCTransition);
 275                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 276                                PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
 277                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 278                                PHM_PlatformCaps_Falcon_QuickTransition);
 279        }
 280
 281        if (data->lowest_uclk_reserved_for_ulv != PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT) {
 282                phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 283                                PHM_PlatformCaps_LowestUclkReservedForUlv);
 284                if (data->lowest_uclk_reserved_for_ulv == 1)
 285                        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 286                                        PHM_PlatformCaps_LowestUclkReservedForUlv);
 287        }
 288
 289        if (data->registry_data.custom_fan_support)
 290                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 291                                PHM_PlatformCaps_CustomFanControlSupport);
 292
 293        return 0;
 294}
 295
 296static void vega12_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 297{
 298        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
 299        struct amdgpu_device *adev = hwmgr->adev;
 300        uint32_t top32, bottom32;
 301        int i;
 302
 303        data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
 304                        FEATURE_DPM_PREFETCHER_BIT;
 305        data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
 306                        FEATURE_DPM_GFXCLK_BIT;
 307        data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
 308                        FEATURE_DPM_UCLK_BIT;
 309        data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
 310                        FEATURE_DPM_SOCCLK_BIT;
 311        data->smu_features[GNLD_DPM_UVD].smu_feature_id =
 312                        FEATURE_DPM_UVD_BIT;
 313        data->smu_features[GNLD_DPM_VCE].smu_feature_id =
 314                        FEATURE_DPM_VCE_BIT;
 315        data->smu_features[GNLD_ULV].smu_feature_id =
 316                        FEATURE_ULV_BIT;
 317        data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
 318                        FEATURE_DPM_MP0CLK_BIT;
 319        data->smu_features[GNLD_DPM_LINK].smu_feature_id =
 320                        FEATURE_DPM_LINK_BIT;
 321        data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
 322                        FEATURE_DPM_DCEFCLK_BIT;
 323        data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
 324                        FEATURE_DS_GFXCLK_BIT;
 325        data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
 326                        FEATURE_DS_SOCCLK_BIT;
 327        data->smu_features[GNLD_DS_LCLK].smu_feature_id =
 328                        FEATURE_DS_LCLK_BIT;
 329        data->smu_features[GNLD_PPT].smu_feature_id =
 330                        FEATURE_PPT_BIT;
 331        data->smu_features[GNLD_TDC].smu_feature_id =
 332                        FEATURE_TDC_BIT;
 333        data->smu_features[GNLD_THERMAL].smu_feature_id =
 334                        FEATURE_THERMAL_BIT;
 335        data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
 336                        FEATURE_GFX_PER_CU_CG_BIT;
 337        data->smu_features[GNLD_RM].smu_feature_id =
 338                        FEATURE_RM_BIT;
 339        data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
 340                        FEATURE_DS_DCEFCLK_BIT;
 341        data->smu_features[GNLD_ACDC].smu_feature_id =
 342                        FEATURE_ACDC_BIT;
 343        data->smu_features[GNLD_VR0HOT].smu_feature_id =
 344                        FEATURE_VR0HOT_BIT;
 345        data->smu_features[GNLD_VR1HOT].smu_feature_id =
 346                        FEATURE_VR1HOT_BIT;
 347        data->smu_features[GNLD_FW_CTF].smu_feature_id =
 348                        FEATURE_FW_CTF_BIT;
 349        data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
 350                        FEATURE_LED_DISPLAY_BIT;
 351        data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
 352                        FEATURE_FAN_CONTROL_BIT;
 353        data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
 354        data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
 355        data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
 356        data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
 357
 358        for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 359                data->smu_features[i].smu_feature_bitmap =
 360                        (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
 361                data->smu_features[i].allowed =
 362                        ((data->registry_data.disallowed_features >> i) & 1) ?
 363                        false : true;
 364        }
 365
 366        /* Get the SN to turn into a Unique ID */
 367        smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32);
 368        smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32);
 369
 370        adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
 371}
 372
 373static int vega12_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
 374{
 375        return 0;
 376}
 377
 378static int vega12_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 379{
 380        kfree(hwmgr->backend);
 381        hwmgr->backend = NULL;
 382
 383        return 0;
 384}
 385
 386static int vega12_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 387{
 388        int result = 0;
 389        struct vega12_hwmgr *data;
 390        struct amdgpu_device *adev = hwmgr->adev;
 391
 392        data = kzalloc(sizeof(struct vega12_hwmgr), GFP_KERNEL);
 393        if (data == NULL)
 394                return -ENOMEM;
 395
 396        hwmgr->backend = data;
 397
 398        vega12_set_default_registry_data(hwmgr);
 399
 400        data->disable_dpm_mask = 0xff;
 401        data->workload_mask = 0xff;
 402
 403        /* need to set voltage control types before EVV patching */
 404        data->vddc_control = VEGA12_VOLTAGE_CONTROL_NONE;
 405        data->mvdd_control = VEGA12_VOLTAGE_CONTROL_NONE;
 406        data->vddci_control = VEGA12_VOLTAGE_CONTROL_NONE;
 407
 408        data->water_marks_bitmap = 0;
 409        data->avfs_exist = false;
 410
 411        vega12_set_features_platform_caps(hwmgr);
 412
 413        vega12_init_dpm_defaults(hwmgr);
 414
 415        /* Parse pptable data read from VBIOS */
 416        vega12_set_private_data_based_on_pptable(hwmgr);
 417
 418        data->is_tlu_enabled = false;
 419
 420        hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
 421                        VEGA12_MAX_HARDWARE_POWERLEVELS;
 422        hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
 423        hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
 424
 425        hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
 426        /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
 427        hwmgr->platform_descriptor.clockStep.engineClock = 500;
 428        hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 429
 430        data->total_active_cus = adev->gfx.cu_info.number;
 431        /* Setup default Overdrive Fan control settings */
 432        data->odn_fan_table.target_fan_speed =
 433                        hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
 434        data->odn_fan_table.target_temperature =
 435                        hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature;
 436        data->odn_fan_table.min_performance_clock =
 437                        hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit;
 438        data->odn_fan_table.min_fan_limit =
 439                        hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit *
 440                        hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
 441
 442        if (hwmgr->feature_mask & PP_GFXOFF_MASK)
 443                data->gfxoff_controlled_by_driver = true;
 444        else
 445                data->gfxoff_controlled_by_driver = false;
 446
 447        return result;
 448}
 449
 450static int vega12_init_sclk_threshold(struct pp_hwmgr *hwmgr)
 451{
 452        struct vega12_hwmgr *data =
 453                        (struct vega12_hwmgr *)(hwmgr->backend);
 454
 455        data->low_sclk_interrupt_threshold = 0;
 456
 457        return 0;
 458}
 459
 460static int vega12_setup_asic_task(struct pp_hwmgr *hwmgr)
 461{
 462        PP_ASSERT_WITH_CODE(!vega12_init_sclk_threshold(hwmgr),
 463                        "Failed to init sclk threshold!",
 464                        return -EINVAL);
 465
 466        return 0;
 467}
 468
 469/*
 470 * @fn vega12_init_dpm_state
 471 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
 472 *
 473 * @param    dpm_state - the address of the DPM Table to initiailize.
 474 * @return   None.
 475 */
 476static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state)
 477{
 478        dpm_state->soft_min_level = 0x0;
 479        dpm_state->soft_max_level = 0xffff;
 480        dpm_state->hard_min_level = 0x0;
 481        dpm_state->hard_max_level = 0xffff;
 482}
 483
 484static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
 485                PPCLK_e clk_id, uint32_t *num_of_levels)
 486{
 487        int ret = 0;
 488
 489        ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 490                        PPSMC_MSG_GetDpmFreqByIndex,
 491                        (clk_id << 16 | 0xFF),
 492                        num_of_levels);
 493        PP_ASSERT_WITH_CODE(!ret,
 494                        "[GetNumOfDpmLevel] failed to get dpm levels!",
 495                        return ret);
 496
 497        return ret;
 498}
 499
 500static int vega12_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
 501                PPCLK_e clkID, uint32_t index, uint32_t *clock)
 502{
 503        /*
 504         *SMU expects the Clock ID to be in the top 16 bits.
 505         *Lower 16 bits specify the level
 506         */
 507        PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 508                PPSMC_MSG_GetDpmFreqByIndex, (clkID << 16 | index),
 509                clock) == 0,
 510                "[GetDpmFrequencyByIndex] Failed to get dpm frequency from SMU!",
 511                return -EINVAL);
 512
 513        return 0;
 514}
 515
 516static int vega12_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
 517                struct vega12_single_dpm_table *dpm_table, PPCLK_e clk_id)
 518{
 519        int ret = 0;
 520        uint32_t i, num_of_levels, clk;
 521
 522        ret = vega12_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
 523        PP_ASSERT_WITH_CODE(!ret,
 524                        "[SetupSingleDpmTable] failed to get clk levels!",
 525                        return ret);
 526
 527        dpm_table->count = num_of_levels;
 528
 529        for (i = 0; i < num_of_levels; i++) {
 530                ret = vega12_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
 531                PP_ASSERT_WITH_CODE(!ret,
 532                        "[SetupSingleDpmTable] failed to get clk of specific level!",
 533                        return ret);
 534                dpm_table->dpm_levels[i].value = clk;
 535                dpm_table->dpm_levels[i].enabled = true;
 536        }
 537
 538        return ret;
 539}
 540
 541/*
 542 * This function is to initialize all DPM state tables
 543 * for SMU based on the dependency table.
 544 * Dynamic state patching function will then trim these
 545 * state tables to the allowed range based
 546 * on the power policy or external client requests,
 547 * such as UVD request, etc.
 548 */
 549static int vega12_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 550{
 551
 552        struct vega12_hwmgr *data =
 553                        (struct vega12_hwmgr *)(hwmgr->backend);
 554        struct vega12_single_dpm_table *dpm_table;
 555        int ret = 0;
 556
 557        memset(&data->dpm_table, 0, sizeof(data->dpm_table));
 558
 559        /* socclk */
 560        dpm_table = &(data->dpm_table.soc_table);
 561        if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
 562                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
 563                PP_ASSERT_WITH_CODE(!ret,
 564                                "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
 565                                return ret);
 566        } else {
 567                dpm_table->count = 1;
 568                dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
 569        }
 570        vega12_init_dpm_state(&(dpm_table->dpm_state));
 571
 572        /* gfxclk */
 573        dpm_table = &(data->dpm_table.gfx_table);
 574        if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
 575                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
 576                PP_ASSERT_WITH_CODE(!ret,
 577                                "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
 578                                return ret);
 579        } else {
 580                dpm_table->count = 1;
 581                dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
 582        }
 583        vega12_init_dpm_state(&(dpm_table->dpm_state));
 584
 585        /* memclk */
 586        dpm_table = &(data->dpm_table.mem_table);
 587        if (data->smu_features[GNLD_DPM_UCLK].enabled) {
 588                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
 589                PP_ASSERT_WITH_CODE(!ret,
 590                                "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
 591                                return ret);
 592        } else {
 593                dpm_table->count = 1;
 594                dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
 595        }
 596        vega12_init_dpm_state(&(dpm_table->dpm_state));
 597
 598        /* eclk */
 599        dpm_table = &(data->dpm_table.eclk_table);
 600        if (data->smu_features[GNLD_DPM_VCE].enabled) {
 601                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
 602                PP_ASSERT_WITH_CODE(!ret,
 603                                "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
 604                                return ret);
 605        } else {
 606                dpm_table->count = 1;
 607                dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
 608        }
 609        vega12_init_dpm_state(&(dpm_table->dpm_state));
 610
 611        /* vclk */
 612        dpm_table = &(data->dpm_table.vclk_table);
 613        if (data->smu_features[GNLD_DPM_UVD].enabled) {
 614                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
 615                PP_ASSERT_WITH_CODE(!ret,
 616                                "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
 617                                return ret);
 618        } else {
 619                dpm_table->count = 1;
 620                dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
 621        }
 622        vega12_init_dpm_state(&(dpm_table->dpm_state));
 623
 624        /* dclk */
 625        dpm_table = &(data->dpm_table.dclk_table);
 626        if (data->smu_features[GNLD_DPM_UVD].enabled) {
 627                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
 628                PP_ASSERT_WITH_CODE(!ret,
 629                                "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
 630                                return ret);
 631        } else {
 632                dpm_table->count = 1;
 633                dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
 634        }
 635        vega12_init_dpm_state(&(dpm_table->dpm_state));
 636
 637        /* dcefclk */
 638        dpm_table = &(data->dpm_table.dcef_table);
 639        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 640                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
 641                PP_ASSERT_WITH_CODE(!ret,
 642                                "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
 643                                return ret);
 644        } else {
 645                dpm_table->count = 1;
 646                dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
 647        }
 648        vega12_init_dpm_state(&(dpm_table->dpm_state));
 649
 650        /* pixclk */
 651        dpm_table = &(data->dpm_table.pixel_table);
 652        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 653                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
 654                PP_ASSERT_WITH_CODE(!ret,
 655                                "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
 656                                return ret);
 657        } else
 658                dpm_table->count = 0;
 659        vega12_init_dpm_state(&(dpm_table->dpm_state));
 660
 661        /* dispclk */
 662        dpm_table = &(data->dpm_table.display_table);
 663        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 664                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
 665                PP_ASSERT_WITH_CODE(!ret,
 666                                "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
 667                                return ret);
 668        } else
 669                dpm_table->count = 0;
 670        vega12_init_dpm_state(&(dpm_table->dpm_state));
 671
 672        /* phyclk */
 673        dpm_table = &(data->dpm_table.phy_table);
 674        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
 675                ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
 676                PP_ASSERT_WITH_CODE(!ret,
 677                                "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
 678                                return ret);
 679        } else
 680                dpm_table->count = 0;
 681        vega12_init_dpm_state(&(dpm_table->dpm_state));
 682
 683        /* save a copy of the default DPM table */
 684        memcpy(&(data->golden_dpm_table), &(data->dpm_table),
 685                        sizeof(struct vega12_dpm_table));
 686
 687        return 0;
 688}
 689
 690#if 0
 691static int vega12_save_default_power_profile(struct pp_hwmgr *hwmgr)
 692{
 693        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
 694        struct vega12_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
 695        uint32_t min_level;
 696
 697        hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
 698        hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
 699
 700        /* Optimize compute power profile: Use only highest
 701         * 2 power levels (if more than 2 are available)
 702         */
 703        if (dpm_table->count > 2)
 704                min_level = dpm_table->count - 2;
 705        else if (dpm_table->count == 2)
 706                min_level = 1;
 707        else
 708                min_level = 0;
 709
 710        hwmgr->default_compute_power_profile.min_sclk =
 711                        dpm_table->dpm_levels[min_level].value;
 712
 713        hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
 714        hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
 715
 716        return 0;
 717}
 718#endif
 719
 720/**
 721* Initializes the SMC table and uploads it
 722*
 723* @param    hwmgr  the address of the powerplay hardware manager.
 724* @param    pInput  the pointer to input data (PowerState)
 725* @return   always 0
 726*/
 727static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
 728{
 729        int result;
 730        struct vega12_hwmgr *data =
 731                        (struct vega12_hwmgr *)(hwmgr->backend);
 732        PPTable_t *pp_table = &(data->smc_state_table.pp_table);
 733        struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
 734        struct phm_ppt_v3_information *pptable_information =
 735                (struct phm_ppt_v3_information *)hwmgr->pptable;
 736
 737        result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
 738        if (!result) {
 739                data->vbios_boot_state.vddc     = boot_up_values.usVddc;
 740                data->vbios_boot_state.vddci    = boot_up_values.usVddci;
 741                data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
 742                data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
 743                data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
 744                data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
 745                data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
 746                data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
 747                data->vbios_boot_state.eclock = boot_up_values.ulEClk;
 748                data->vbios_boot_state.dclock = boot_up_values.ulDClk;
 749                data->vbios_boot_state.vclock = boot_up_values.ulVClk;
 750                smum_send_msg_to_smc_with_parameter(hwmgr,
 751                                PPSMC_MSG_SetMinDeepSleepDcefclk,
 752                        (uint32_t)(data->vbios_boot_state.dcef_clock / 100),
 753                                NULL);
 754        }
 755
 756        memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
 757
 758        result = smum_smc_table_manager(hwmgr,
 759                                        (uint8_t *)pp_table, TABLE_PPTABLE, false);
 760        PP_ASSERT_WITH_CODE(!result,
 761                        "Failed to upload PPtable!", return result);
 762
 763        return 0;
 764}
 765
 766static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
 767{
 768        uint32_t result;
 769
 770        PP_ASSERT_WITH_CODE(
 771                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &result) == 0,
 772                "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
 773                return -EINVAL);
 774
 775        PP_ASSERT_WITH_CODE(result == 1,
 776                        "Failed to run ACG BTC!", return -EINVAL);
 777
 778        return 0;
 779}
 780
 781static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 782{
 783        struct vega12_hwmgr *data =
 784                        (struct vega12_hwmgr *)(hwmgr->backend);
 785        int i;
 786        uint32_t allowed_features_low = 0, allowed_features_high = 0;
 787
 788        for (i = 0; i < GNLD_FEATURES_MAX; i++)
 789                if (data->smu_features[i].allowed)
 790                        data->smu_features[i].smu_feature_id > 31 ?
 791                                (allowed_features_high |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) & 0xFFFFFFFF)) :
 792                                (allowed_features_low |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) & 0xFFFFFFFF));
 793
 794        PP_ASSERT_WITH_CODE(
 795                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high,
 796                        NULL) == 0,
 797                "[SetAllowedFeaturesMask] Attempt to set allowed features mask (high) failed!",
 798                return -1);
 799
 800        PP_ASSERT_WITH_CODE(
 801                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low,
 802                        NULL) == 0,
 803                "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
 804                return -1);
 805
 806        return 0;
 807}
 808
 809static void vega12_init_powergate_state(struct pp_hwmgr *hwmgr)
 810{
 811        struct vega12_hwmgr *data =
 812                        (struct vega12_hwmgr *)(hwmgr->backend);
 813
 814        data->uvd_power_gated = true;
 815        data->vce_power_gated = true;
 816
 817        if (data->smu_features[GNLD_DPM_UVD].enabled)
 818                data->uvd_power_gated = false;
 819
 820        if (data->smu_features[GNLD_DPM_VCE].enabled)
 821                data->vce_power_gated = false;
 822}
 823
 824static int vega12_enable_all_smu_features(struct pp_hwmgr *hwmgr)
 825{
 826        struct vega12_hwmgr *data =
 827                        (struct vega12_hwmgr *)(hwmgr->backend);
 828        uint64_t features_enabled;
 829        int i;
 830        bool enabled;
 831
 832        PP_ASSERT_WITH_CODE(
 833                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, NULL) == 0,
 834                "[EnableAllSMUFeatures] Failed to enable all smu features!",
 835                return -1);
 836
 837        if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) {
 838                for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 839                        enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false;
 840                        data->smu_features[i].enabled = enabled;
 841                        data->smu_features[i].supported = enabled;
 842                }
 843        }
 844
 845        vega12_init_powergate_state(hwmgr);
 846
 847        return 0;
 848}
 849
 850static int vega12_disable_all_smu_features(struct pp_hwmgr *hwmgr)
 851{
 852        struct vega12_hwmgr *data =
 853                        (struct vega12_hwmgr *)(hwmgr->backend);
 854        uint64_t features_enabled;
 855        int i;
 856        bool enabled;
 857
 858        PP_ASSERT_WITH_CODE(
 859                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, NULL) == 0,
 860                "[DisableAllSMUFeatures] Failed to disable all smu features!",
 861                return -1);
 862
 863        if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) {
 864                for (i = 0; i < GNLD_FEATURES_MAX; i++) {
 865                        enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false;
 866                        data->smu_features[i].enabled = enabled;
 867                        data->smu_features[i].supported = enabled;
 868                }
 869        }
 870
 871        return 0;
 872}
 873
 874static int vega12_odn_initialize_default_settings(
 875                struct pp_hwmgr *hwmgr)
 876{
 877        return 0;
 878}
 879
 880static int vega12_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr,
 881                uint32_t adjust_percent)
 882{
 883        return smum_send_msg_to_smc_with_parameter(hwmgr,
 884                        PPSMC_MSG_OverDriveSetPercentage, adjust_percent,
 885                        NULL);
 886}
 887
 888static int vega12_power_control_set_level(struct pp_hwmgr *hwmgr)
 889{
 890        int adjust_percent, result = 0;
 891
 892        if (PP_CAP(PHM_PlatformCaps_PowerContainment)) {
 893                adjust_percent =
 894                                hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
 895                                hwmgr->platform_descriptor.TDPAdjustment :
 896                                (-1 * hwmgr->platform_descriptor.TDPAdjustment);
 897                result = vega12_set_overdrive_target_percentage(hwmgr,
 898                                (uint32_t)adjust_percent);
 899        }
 900        return result;
 901}
 902
 903static int vega12_get_all_clock_ranges_helper(struct pp_hwmgr *hwmgr,
 904                PPCLK_e clkid, struct vega12_clock_range *clock)
 905{
 906        /* AC Max */
 907        PP_ASSERT_WITH_CODE(
 908                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMaxDpmFreq, (clkid << 16),
 909                        &(clock->ACMax)) == 0,
 910                "[GetClockRanges] Failed to get max ac clock from SMC!",
 911                return -EINVAL);
 912
 913        /* AC Min */
 914        PP_ASSERT_WITH_CODE(
 915                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMinDpmFreq, (clkid << 16),
 916                        &(clock->ACMin)) == 0,
 917                "[GetClockRanges] Failed to get min ac clock from SMC!",
 918                return -EINVAL);
 919
 920        /* DC Max */
 921        PP_ASSERT_WITH_CODE(
 922                smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDcModeMaxDpmFreq, (clkid << 16),
 923                        &(clock->DCMax)) == 0,
 924                "[GetClockRanges] Failed to get max dc clock from SMC!",
 925                return -EINVAL);
 926
 927        return 0;
 928}
 929
 930static int vega12_get_all_clock_ranges(struct pp_hwmgr *hwmgr)
 931{
 932        struct vega12_hwmgr *data =
 933                        (struct vega12_hwmgr *)(hwmgr->backend);
 934        uint32_t i;
 935
 936        for (i = 0; i < PPCLK_COUNT; i++)
 937                PP_ASSERT_WITH_CODE(!vega12_get_all_clock_ranges_helper(hwmgr,
 938                                        i, &(data->clk_range[i])),
 939                                "Failed to get clk range from SMC!",
 940                                return -EINVAL);
 941
 942        return 0;
 943}
 944
 945static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
 946{
 947        int tmp_result, result = 0;
 948
 949        smum_send_msg_to_smc_with_parameter(hwmgr,
 950                        PPSMC_MSG_NumOfDisplays, 0, NULL);
 951
 952        result = vega12_set_allowed_featuresmask(hwmgr);
 953        PP_ASSERT_WITH_CODE(result == 0,
 954                        "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
 955                        return result);
 956
 957        tmp_result = vega12_init_smc_table(hwmgr);
 958        PP_ASSERT_WITH_CODE(!tmp_result,
 959                        "Failed to initialize SMC table!",
 960                        result = tmp_result);
 961
 962        tmp_result = vega12_run_acg_btc(hwmgr);
 963        PP_ASSERT_WITH_CODE(!tmp_result,
 964                        "Failed to run ACG BTC!",
 965                        result = tmp_result);
 966
 967        result = vega12_enable_all_smu_features(hwmgr);
 968        PP_ASSERT_WITH_CODE(!result,
 969                        "Failed to enable all smu features!",
 970                        return result);
 971
 972        tmp_result = vega12_power_control_set_level(hwmgr);
 973        PP_ASSERT_WITH_CODE(!tmp_result,
 974                        "Failed to power control set level!",
 975                        result = tmp_result);
 976
 977        result = vega12_get_all_clock_ranges(hwmgr);
 978        PP_ASSERT_WITH_CODE(!result,
 979                        "Failed to get all clock ranges!",
 980                        return result);
 981
 982        result = vega12_odn_initialize_default_settings(hwmgr);
 983        PP_ASSERT_WITH_CODE(!result,
 984                        "Failed to power control set level!",
 985                        return result);
 986
 987        result = vega12_setup_default_dpm_tables(hwmgr);
 988        PP_ASSERT_WITH_CODE(!result,
 989                        "Failed to setup default DPM tables!",
 990                        return result);
 991        return result;
 992}
 993
 994static int vega12_patch_boot_state(struct pp_hwmgr *hwmgr,
 995             struct pp_hw_power_state *hw_ps)
 996{
 997        return 0;
 998}
 999
1000static uint32_t vega12_find_lowest_dpm_level(
1001                struct vega12_single_dpm_table *table)
1002{
1003        uint32_t i;
1004
1005        for (i = 0; i < table->count; i++) {
1006                if (table->dpm_levels[i].enabled)
1007                        break;
1008        }
1009
1010        if (i >= table->count) {
1011                i = 0;
1012                table->dpm_levels[i].enabled = true;
1013        }
1014
1015        return i;
1016}
1017
1018static uint32_t vega12_find_highest_dpm_level(
1019                struct vega12_single_dpm_table *table)
1020{
1021        int32_t i = 0;
1022        PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER,
1023                        "[FindHighestDPMLevel] DPM Table has too many entries!",
1024                        return MAX_REGULAR_DPM_NUMBER - 1);
1025
1026        for (i = table->count - 1; i >= 0; i--) {
1027                if (table->dpm_levels[i].enabled)
1028                        break;
1029        }
1030
1031        if (i < 0) {
1032                i = 0;
1033                table->dpm_levels[i].enabled = true;
1034        }
1035
1036        return (uint32_t)i;
1037}
1038
1039static int vega12_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
1040{
1041        struct vega12_hwmgr *data = hwmgr->backend;
1042        uint32_t min_freq;
1043        int ret = 0;
1044
1045        if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1046                min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
1047                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1048                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1049                                        (PPCLK_GFXCLK << 16) | (min_freq & 0xffff),
1050                                        NULL)),
1051                                        "Failed to set soft min gfxclk !",
1052                                        return ret);
1053        }
1054
1055        if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1056                min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
1057                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1058                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1059                                        (PPCLK_UCLK << 16) | (min_freq & 0xffff),
1060                                        NULL)),
1061                                        "Failed to set soft min memclk !",
1062                                        return ret);
1063
1064                min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
1065                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1066                                        hwmgr, PPSMC_MSG_SetHardMinByFreq,
1067                                        (PPCLK_UCLK << 16) | (min_freq & 0xffff),
1068                                        NULL)),
1069                                        "Failed to set hard min memclk !",
1070                                        return ret);
1071        }
1072
1073        if (data->smu_features[GNLD_DPM_UVD].enabled) {
1074                min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
1075
1076                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1077                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1078                                        (PPCLK_VCLK << 16) | (min_freq & 0xffff),
1079                                        NULL)),
1080                                        "Failed to set soft min vclk!",
1081                                        return ret);
1082
1083                min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level;
1084
1085                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1086                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1087                                        (PPCLK_DCLK << 16) | (min_freq & 0xffff),
1088                                        NULL)),
1089                                        "Failed to set soft min dclk!",
1090                                        return ret);
1091        }
1092
1093        if (data->smu_features[GNLD_DPM_VCE].enabled) {
1094                min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
1095
1096                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1097                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1098                                        (PPCLK_ECLK << 16) | (min_freq & 0xffff),
1099                                        NULL)),
1100                                        "Failed to set soft min eclk!",
1101                                        return ret);
1102        }
1103
1104        if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
1105                min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
1106
1107                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1108                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1109                                        (PPCLK_SOCCLK << 16) | (min_freq & 0xffff),
1110                                        NULL)),
1111                                        "Failed to set soft min socclk!",
1112                                        return ret);
1113        }
1114
1115        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1116                min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
1117
1118                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1119                                        hwmgr, PPSMC_MSG_SetHardMinByFreq,
1120                                        (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff),
1121                                        NULL)),
1122                                        "Failed to set hard min dcefclk!",
1123                                        return ret);
1124        }
1125
1126        return ret;
1127
1128}
1129
1130static int vega12_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
1131{
1132        struct vega12_hwmgr *data = hwmgr->backend;
1133        uint32_t max_freq;
1134        int ret = 0;
1135
1136        if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
1137                max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
1138
1139                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1140                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1141                                        (PPCLK_GFXCLK << 16) | (max_freq & 0xffff),
1142                                        NULL)),
1143                                        "Failed to set soft max gfxclk!",
1144                                        return ret);
1145        }
1146
1147        if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1148                max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
1149
1150                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1151                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1152                                        (PPCLK_UCLK << 16) | (max_freq & 0xffff),
1153                                        NULL)),
1154                                        "Failed to set soft max memclk!",
1155                                        return ret);
1156        }
1157
1158        if (data->smu_features[GNLD_DPM_UVD].enabled) {
1159                max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
1160
1161                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1162                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1163                                        (PPCLK_VCLK << 16) | (max_freq & 0xffff),
1164                                        NULL)),
1165                                        "Failed to set soft max vclk!",
1166                                        return ret);
1167
1168                max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level;
1169                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1170                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1171                                        (PPCLK_DCLK << 16) | (max_freq & 0xffff),
1172                                        NULL)),
1173                                        "Failed to set soft max dclk!",
1174                                        return ret);
1175        }
1176
1177        if (data->smu_features[GNLD_DPM_VCE].enabled) {
1178                max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
1179
1180                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1181                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1182                                        (PPCLK_ECLK << 16) | (max_freq & 0xffff),
1183                                        NULL)),
1184                                        "Failed to set soft max eclk!",
1185                                        return ret);
1186        }
1187
1188        if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
1189                max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
1190
1191                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1192                                        hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1193                                        (PPCLK_SOCCLK << 16) | (max_freq & 0xffff),
1194                                        NULL)),
1195                                        "Failed to set soft max socclk!",
1196                                        return ret);
1197        }
1198
1199        return ret;
1200}
1201
1202int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
1203{
1204        struct vega12_hwmgr *data =
1205                        (struct vega12_hwmgr *)(hwmgr->backend);
1206
1207        if (data->smu_features[GNLD_DPM_VCE].supported) {
1208                PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr,
1209                                enable,
1210                                data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap),
1211                                "Attempt to Enable/Disable DPM VCE Failed!",
1212                                return -1);
1213                data->smu_features[GNLD_DPM_VCE].enabled = enable;
1214        }
1215
1216        return 0;
1217}
1218
1219static uint32_t vega12_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
1220{
1221        struct vega12_hwmgr *data =
1222                        (struct vega12_hwmgr *)(hwmgr->backend);
1223        uint32_t gfx_clk;
1224
1225        if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
1226                return -1;
1227
1228        if (low)
1229                PP_ASSERT_WITH_CODE(
1230                        vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false) == 0,
1231                        "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
1232                        return -1);
1233        else
1234                PP_ASSERT_WITH_CODE(
1235                        vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true) == 0,
1236                        "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
1237                        return -1);
1238
1239        return (gfx_clk * 100);
1240}
1241
1242static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
1243{
1244        struct vega12_hwmgr *data =
1245                        (struct vega12_hwmgr *)(hwmgr->backend);
1246        uint32_t mem_clk;
1247
1248        if (!data->smu_features[GNLD_DPM_UCLK].enabled)
1249                return -1;
1250
1251        if (low)
1252                PP_ASSERT_WITH_CODE(
1253                        vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false) == 0,
1254                        "[GetMclks]: fail to get min PPCLK_UCLK\n",
1255                        return -1);
1256        else
1257                PP_ASSERT_WITH_CODE(
1258                        vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true) == 0,
1259                        "[GetMclks]: fail to get max PPCLK_UCLK\n",
1260                        return -1);
1261
1262        return (mem_clk * 100);
1263}
1264
1265static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr,
1266                                    SmuMetrics_t *metrics_table,
1267                                    bool bypass_cache)
1268{
1269        struct vega12_hwmgr *data =
1270                        (struct vega12_hwmgr *)(hwmgr->backend);
1271        int ret = 0;
1272
1273        if (bypass_cache ||
1274            !data->metrics_time ||
1275            time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) {
1276                ret = smum_smc_table_manager(hwmgr,
1277                                             (uint8_t *)(&data->metrics_table),
1278                                             TABLE_SMU_METRICS,
1279                                             true);
1280                if (ret) {
1281                        pr_info("Failed to export SMU metrics table!\n");
1282                        return ret;
1283                }
1284                data->metrics_time = jiffies;
1285        }
1286
1287        if (metrics_table)
1288                memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t));
1289
1290        return ret;
1291}
1292
1293static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr, uint32_t *query)
1294{
1295        SmuMetrics_t metrics_table;
1296        int ret = 0;
1297
1298        ret = vega12_get_metrics_table(hwmgr, &metrics_table, false);
1299        if (ret)
1300                return ret;
1301
1302        *query = metrics_table.CurrSocketPower << 8;
1303
1304        return ret;
1305}
1306
1307static int vega12_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq)
1308{
1309        uint32_t gfx_clk = 0;
1310
1311        *gfx_freq = 0;
1312
1313        PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
1314                        PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16),
1315                        &gfx_clk) == 0,
1316                        "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!",
1317                        return -EINVAL);
1318
1319        *gfx_freq = gfx_clk * 100;
1320
1321        return 0;
1322}
1323
1324static int vega12_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq)
1325{
1326        uint32_t mem_clk = 0;
1327
1328        *mclk_freq = 0;
1329
1330        PP_ASSERT_WITH_CODE(
1331                        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16),
1332                                &mem_clk) == 0,
1333                        "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!",
1334                        return -EINVAL);
1335
1336        *mclk_freq = mem_clk * 100;
1337
1338        return 0;
1339}
1340
1341static int vega12_get_current_activity_percent(
1342                struct pp_hwmgr *hwmgr,
1343                int idx,
1344                uint32_t *activity_percent)
1345{
1346        SmuMetrics_t metrics_table;
1347        int ret = 0;
1348
1349        ret = vega12_get_metrics_table(hwmgr, &metrics_table, false);
1350        if (ret)
1351                return ret;
1352
1353        switch (idx) {
1354        case AMDGPU_PP_SENSOR_GPU_LOAD:
1355                *activity_percent = metrics_table.AverageGfxActivity;
1356                break;
1357        case AMDGPU_PP_SENSOR_MEM_LOAD:
1358                *activity_percent = metrics_table.AverageUclkActivity;
1359                break;
1360        default:
1361                pr_err("Invalid index for retrieving clock activity\n");
1362                return -EINVAL;
1363        }
1364
1365        return ret;
1366}
1367
1368static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1369                              void *value, int *size)
1370{
1371        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1372        SmuMetrics_t metrics_table;
1373        int ret = 0;
1374
1375        switch (idx) {
1376        case AMDGPU_PP_SENSOR_GFX_SCLK:
1377                ret = vega12_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value);
1378                if (!ret)
1379                        *size = 4;
1380                break;
1381        case AMDGPU_PP_SENSOR_GFX_MCLK:
1382                ret = vega12_get_current_mclk_freq(hwmgr, (uint32_t *)value);
1383                if (!ret)
1384                        *size = 4;
1385                break;
1386        case AMDGPU_PP_SENSOR_GPU_LOAD:
1387        case AMDGPU_PP_SENSOR_MEM_LOAD:
1388                ret = vega12_get_current_activity_percent(hwmgr, idx, (uint32_t *)value);
1389                if (!ret)
1390                        *size = 4;
1391                break;
1392        case AMDGPU_PP_SENSOR_GPU_TEMP:
1393                *((uint32_t *)value) = vega12_thermal_get_temperature(hwmgr);
1394                *size = 4;
1395                break;
1396        case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1397                ret = vega12_get_metrics_table(hwmgr, &metrics_table, false);
1398                if (ret)
1399                        return ret;
1400
1401                *((uint32_t *)value) = metrics_table.TemperatureHotspot *
1402                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1403                *size = 4;
1404                break;
1405        case AMDGPU_PP_SENSOR_MEM_TEMP:
1406                ret = vega12_get_metrics_table(hwmgr, &metrics_table, false);
1407                if (ret)
1408                        return ret;
1409
1410                *((uint32_t *)value) = metrics_table.TemperatureHBM *
1411                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1412                *size = 4;
1413                break;
1414        case AMDGPU_PP_SENSOR_UVD_POWER:
1415                *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
1416                *size = 4;
1417                break;
1418        case AMDGPU_PP_SENSOR_VCE_POWER:
1419                *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
1420                *size = 4;
1421                break;
1422        case AMDGPU_PP_SENSOR_GPU_POWER:
1423                ret = vega12_get_gpu_power(hwmgr, (uint32_t *)value);
1424                if (!ret)
1425                        *size = 4;
1426                break;
1427        case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
1428                ret = vega12_get_enabled_smc_features(hwmgr, (uint64_t *)value);
1429                if (!ret)
1430                        *size = 8;
1431                break;
1432        default:
1433                ret = -EINVAL;
1434                break;
1435        }
1436        return ret;
1437}
1438
1439static int vega12_notify_smc_display_change(struct pp_hwmgr *hwmgr,
1440                bool has_disp)
1441{
1442        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1443
1444        if (data->smu_features[GNLD_DPM_UCLK].enabled)
1445                return smum_send_msg_to_smc_with_parameter(hwmgr,
1446                        PPSMC_MSG_SetUclkFastSwitch,
1447                        has_disp ? 1 : 0,
1448                        NULL);
1449
1450        return 0;
1451}
1452
1453static int vega12_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
1454                struct pp_display_clock_request *clock_req)
1455{
1456        int result = 0;
1457        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1458        enum amd_pp_clock_type clk_type = clock_req->clock_type;
1459        uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
1460        PPCLK_e clk_select = 0;
1461        uint32_t clk_request = 0;
1462
1463        if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1464                switch (clk_type) {
1465                case amd_pp_dcef_clock:
1466                        clk_select = PPCLK_DCEFCLK;
1467                        break;
1468                case amd_pp_disp_clock:
1469                        clk_select = PPCLK_DISPCLK;
1470                        break;
1471                case amd_pp_pixel_clock:
1472                        clk_select = PPCLK_PIXCLK;
1473                        break;
1474                case amd_pp_phy_clock:
1475                        clk_select = PPCLK_PHYCLK;
1476                        break;
1477                default:
1478                        pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
1479                        result = -1;
1480                        break;
1481                }
1482
1483                if (!result) {
1484                        clk_request = (clk_select << 16) | clk_freq;
1485                        result = smum_send_msg_to_smc_with_parameter(hwmgr,
1486                                        PPSMC_MSG_SetHardMinByFreq,
1487                                        clk_request,
1488                                        NULL);
1489                }
1490        }
1491
1492        return result;
1493}
1494
1495static int vega12_notify_smc_display_config_after_ps_adjustment(
1496                struct pp_hwmgr *hwmgr)
1497{
1498        struct vega12_hwmgr *data =
1499                        (struct vega12_hwmgr *)(hwmgr->backend);
1500        struct PP_Clocks min_clocks = {0};
1501        struct pp_display_clock_request clock_req;
1502
1503        if ((hwmgr->display_config->num_display > 1) &&
1504             !hwmgr->display_config->multi_monitor_in_sync &&
1505             !hwmgr->display_config->nb_pstate_switch_disable)
1506                vega12_notify_smc_display_change(hwmgr, false);
1507        else
1508                vega12_notify_smc_display_change(hwmgr, true);
1509
1510        min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
1511        min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
1512        min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
1513
1514        if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
1515                clock_req.clock_type = amd_pp_dcef_clock;
1516                clock_req.clock_freq_in_khz = min_clocks.dcefClock/10;
1517                if (!vega12_display_clock_voltage_request(hwmgr, &clock_req)) {
1518                        if (data->smu_features[GNLD_DS_DCEFCLK].supported)
1519                                PP_ASSERT_WITH_CODE(
1520                                        !smum_send_msg_to_smc_with_parameter(
1521                                        hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
1522                                        min_clocks.dcefClockInSR /100,
1523                                        NULL),
1524                                        "Attempt to set divider for DCEFCLK Failed!",
1525                                        return -1);
1526                } else {
1527                        pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1528                }
1529        }
1530
1531        return 0;
1532}
1533
1534static int vega12_force_dpm_highest(struct pp_hwmgr *hwmgr)
1535{
1536        struct vega12_hwmgr *data =
1537                        (struct vega12_hwmgr *)(hwmgr->backend);
1538
1539        uint32_t soft_level;
1540
1541        soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.gfx_table));
1542
1543        data->dpm_table.gfx_table.dpm_state.soft_min_level =
1544                data->dpm_table.gfx_table.dpm_state.soft_max_level =
1545                data->dpm_table.gfx_table.dpm_levels[soft_level].value;
1546
1547        soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.mem_table));
1548
1549        data->dpm_table.mem_table.dpm_state.soft_min_level =
1550                data->dpm_table.mem_table.dpm_state.soft_max_level =
1551                data->dpm_table.mem_table.dpm_levels[soft_level].value;
1552
1553        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1554                        "Failed to upload boot level to highest!",
1555                        return -1);
1556
1557        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1558                        "Failed to upload dpm max level to highest!",
1559                        return -1);
1560
1561        return 0;
1562}
1563
1564static int vega12_force_dpm_lowest(struct pp_hwmgr *hwmgr)
1565{
1566        struct vega12_hwmgr *data =
1567                        (struct vega12_hwmgr *)(hwmgr->backend);
1568        uint32_t soft_level;
1569
1570        soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
1571
1572        data->dpm_table.gfx_table.dpm_state.soft_min_level =
1573                data->dpm_table.gfx_table.dpm_state.soft_max_level =
1574                data->dpm_table.gfx_table.dpm_levels[soft_level].value;
1575
1576        soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.mem_table));
1577
1578        data->dpm_table.mem_table.dpm_state.soft_min_level =
1579                data->dpm_table.mem_table.dpm_state.soft_max_level =
1580                data->dpm_table.mem_table.dpm_levels[soft_level].value;
1581
1582        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1583                        "Failed to upload boot level to highest!",
1584                        return -1);
1585
1586        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1587                        "Failed to upload dpm max level to highest!",
1588                        return -1);
1589
1590        return 0;
1591
1592}
1593
1594static int vega12_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
1595{
1596        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr),
1597                        "Failed to upload DPM Bootup Levels!",
1598                        return -1);
1599
1600        PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr),
1601                        "Failed to upload DPM Max Levels!",
1602                        return -1);
1603
1604        return 0;
1605}
1606
1607static int vega12_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
1608                                uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
1609{
1610        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1611        struct vega12_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table);
1612        struct vega12_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table);
1613        struct vega12_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table);
1614
1615        *sclk_mask = 0;
1616        *mclk_mask = 0;
1617        *soc_mask  = 0;
1618
1619        if (gfx_dpm_table->count > VEGA12_UMD_PSTATE_GFXCLK_LEVEL &&
1620            mem_dpm_table->count > VEGA12_UMD_PSTATE_MCLK_LEVEL &&
1621            soc_dpm_table->count > VEGA12_UMD_PSTATE_SOCCLK_LEVEL) {
1622                *sclk_mask = VEGA12_UMD_PSTATE_GFXCLK_LEVEL;
1623                *mclk_mask = VEGA12_UMD_PSTATE_MCLK_LEVEL;
1624                *soc_mask  = VEGA12_UMD_PSTATE_SOCCLK_LEVEL;
1625        }
1626
1627        if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1628                *sclk_mask = 0;
1629        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1630                *mclk_mask = 0;
1631        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1632                *sclk_mask = gfx_dpm_table->count - 1;
1633                *mclk_mask = mem_dpm_table->count - 1;
1634                *soc_mask  = soc_dpm_table->count - 1;
1635        }
1636
1637        return 0;
1638}
1639
1640static void vega12_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
1641{
1642        switch (mode) {
1643        case AMD_FAN_CTRL_NONE:
1644                break;
1645        case AMD_FAN_CTRL_MANUAL:
1646                if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
1647                        vega12_fan_ctrl_stop_smc_fan_control(hwmgr);
1648                break;
1649        case AMD_FAN_CTRL_AUTO:
1650                if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
1651                        vega12_fan_ctrl_start_smc_fan_control(hwmgr);
1652                break;
1653        default:
1654                break;
1655        }
1656}
1657
1658static int vega12_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
1659                                enum amd_dpm_forced_level level)
1660{
1661        int ret = 0;
1662        uint32_t sclk_mask = 0;
1663        uint32_t mclk_mask = 0;
1664        uint32_t soc_mask = 0;
1665
1666        switch (level) {
1667        case AMD_DPM_FORCED_LEVEL_HIGH:
1668                ret = vega12_force_dpm_highest(hwmgr);
1669                break;
1670        case AMD_DPM_FORCED_LEVEL_LOW:
1671                ret = vega12_force_dpm_lowest(hwmgr);
1672                break;
1673        case AMD_DPM_FORCED_LEVEL_AUTO:
1674                ret = vega12_unforce_dpm_levels(hwmgr);
1675                break;
1676        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1677        case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1678        case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1679        case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1680                ret = vega12_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
1681                if (ret)
1682                        return ret;
1683                vega12_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
1684                vega12_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
1685                break;
1686        case AMD_DPM_FORCED_LEVEL_MANUAL:
1687        case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1688        default:
1689                break;
1690        }
1691
1692        return ret;
1693}
1694
1695static uint32_t vega12_get_fan_control_mode(struct pp_hwmgr *hwmgr)
1696{
1697        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1698
1699        if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
1700                return AMD_FAN_CTRL_MANUAL;
1701        else
1702                return AMD_FAN_CTRL_AUTO;
1703}
1704
1705static int vega12_get_dal_power_level(struct pp_hwmgr *hwmgr,
1706                struct amd_pp_simple_clock_info *info)
1707{
1708#if 0
1709        struct phm_ppt_v2_information *table_info =
1710                        (struct phm_ppt_v2_information *)hwmgr->pptable;
1711        struct phm_clock_and_voltage_limits *max_limits =
1712                        &table_info->max_clock_voltage_on_ac;
1713
1714        info->engine_max_clock = max_limits->sclk;
1715        info->memory_max_clock = max_limits->mclk;
1716#endif
1717        return 0;
1718}
1719
1720static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr,
1721                uint32_t *clock,
1722                PPCLK_e clock_select,
1723                bool max)
1724{
1725        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1726
1727        if (max)
1728                *clock = data->clk_range[clock_select].ACMax;
1729        else
1730                *clock = data->clk_range[clock_select].ACMin;
1731
1732        return 0;
1733}
1734
1735static int vega12_get_sclks(struct pp_hwmgr *hwmgr,
1736                struct pp_clock_levels_with_latency *clocks)
1737{
1738        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1739        uint32_t ucount;
1740        int i;
1741        struct vega12_single_dpm_table *dpm_table;
1742
1743        if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
1744                return -1;
1745
1746        dpm_table = &(data->dpm_table.gfx_table);
1747        ucount = (dpm_table->count > MAX_NUM_CLOCKS) ?
1748                MAX_NUM_CLOCKS : dpm_table->count;
1749
1750        for (i = 0; i < ucount; i++) {
1751                clocks->data[i].clocks_in_khz =
1752                        dpm_table->dpm_levels[i].value * 1000;
1753
1754                clocks->data[i].latency_in_us = 0;
1755        }
1756
1757        clocks->num_levels = ucount;
1758
1759        return 0;
1760}
1761
1762static uint32_t vega12_get_mem_latency(struct pp_hwmgr *hwmgr,
1763                uint32_t clock)
1764{
1765        return 25;
1766}
1767
1768static int vega12_get_memclocks(struct pp_hwmgr *hwmgr,
1769                struct pp_clock_levels_with_latency *clocks)
1770{
1771        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1772        uint32_t ucount;
1773        int i;
1774        struct vega12_single_dpm_table *dpm_table;
1775        if (!data->smu_features[GNLD_DPM_UCLK].enabled)
1776                return -1;
1777
1778        dpm_table = &(data->dpm_table.mem_table);
1779        ucount = (dpm_table->count > MAX_NUM_CLOCKS) ?
1780                MAX_NUM_CLOCKS : dpm_table->count;
1781
1782        for (i = 0; i < ucount; i++) {
1783                clocks->data[i].clocks_in_khz = dpm_table->dpm_levels[i].value * 1000;
1784                data->mclk_latency_table.entries[i].frequency = dpm_table->dpm_levels[i].value * 100;
1785                clocks->data[i].latency_in_us =
1786                        data->mclk_latency_table.entries[i].latency =
1787                        vega12_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
1788        }
1789
1790        clocks->num_levels = data->mclk_latency_table.count = ucount;
1791
1792        return 0;
1793}
1794
1795static int vega12_get_dcefclocks(struct pp_hwmgr *hwmgr,
1796                struct pp_clock_levels_with_latency *clocks)
1797{
1798        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1799        uint32_t ucount;
1800        int i;
1801        struct vega12_single_dpm_table *dpm_table;
1802
1803        if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled)
1804                return -1;
1805
1806
1807        dpm_table = &(data->dpm_table.dcef_table);
1808        ucount = (dpm_table->count > MAX_NUM_CLOCKS) ?
1809                MAX_NUM_CLOCKS : dpm_table->count;
1810
1811        for (i = 0; i < ucount; i++) {
1812                clocks->data[i].clocks_in_khz =
1813                        dpm_table->dpm_levels[i].value * 1000;
1814
1815                clocks->data[i].latency_in_us = 0;
1816        }
1817
1818        clocks->num_levels = ucount;
1819
1820        return 0;
1821}
1822
1823static int vega12_get_socclocks(struct pp_hwmgr *hwmgr,
1824                struct pp_clock_levels_with_latency *clocks)
1825{
1826        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1827        uint32_t ucount;
1828        int i;
1829        struct vega12_single_dpm_table *dpm_table;
1830
1831        if (!data->smu_features[GNLD_DPM_SOCCLK].enabled)
1832                return -1;
1833
1834
1835        dpm_table = &(data->dpm_table.soc_table);
1836        ucount = (dpm_table->count > MAX_NUM_CLOCKS) ?
1837                MAX_NUM_CLOCKS : dpm_table->count;
1838
1839        for (i = 0; i < ucount; i++) {
1840                clocks->data[i].clocks_in_khz =
1841                        dpm_table->dpm_levels[i].value * 1000;
1842
1843                clocks->data[i].latency_in_us = 0;
1844        }
1845
1846        clocks->num_levels = ucount;
1847
1848        return 0;
1849
1850}
1851
1852static int vega12_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
1853                enum amd_pp_clock_type type,
1854                struct pp_clock_levels_with_latency *clocks)
1855{
1856        int ret;
1857
1858        switch (type) {
1859        case amd_pp_sys_clock:
1860                ret = vega12_get_sclks(hwmgr, clocks);
1861                break;
1862        case amd_pp_mem_clock:
1863                ret = vega12_get_memclocks(hwmgr, clocks);
1864                break;
1865        case amd_pp_dcef_clock:
1866                ret = vega12_get_dcefclocks(hwmgr, clocks);
1867                break;
1868        case amd_pp_soc_clock:
1869                ret = vega12_get_socclocks(hwmgr, clocks);
1870                break;
1871        default:
1872                return -EINVAL;
1873        }
1874
1875        return ret;
1876}
1877
1878static int vega12_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
1879                enum amd_pp_clock_type type,
1880                struct pp_clock_levels_with_voltage *clocks)
1881{
1882        clocks->num_levels = 0;
1883
1884        return 0;
1885}
1886
1887static int vega12_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
1888                                                        void *clock_ranges)
1889{
1890        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1891        Watermarks_t *table = &(data->smc_state_table.water_marks_table);
1892        struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
1893
1894        if (!data->registry_data.disable_water_mark &&
1895                        data->smu_features[GNLD_DPM_DCEFCLK].supported &&
1896                        data->smu_features[GNLD_DPM_SOCCLK].supported) {
1897                smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
1898                data->water_marks_bitmap |= WaterMarksExist;
1899                data->water_marks_bitmap &= ~WaterMarksLoaded;
1900        }
1901
1902        return 0;
1903}
1904
1905static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
1906                enum pp_clock_type type, uint32_t mask)
1907{
1908        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
1909        uint32_t soft_min_level, soft_max_level, hard_min_level;
1910        int ret = 0;
1911
1912        switch (type) {
1913        case PP_SCLK:
1914                soft_min_level = mask ? (ffs(mask) - 1) : 0;
1915                soft_max_level = mask ? (fls(mask) - 1) : 0;
1916
1917                data->dpm_table.gfx_table.dpm_state.soft_min_level =
1918                        data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
1919                data->dpm_table.gfx_table.dpm_state.soft_max_level =
1920                        data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
1921
1922                ret = vega12_upload_dpm_min_level(hwmgr);
1923                PP_ASSERT_WITH_CODE(!ret,
1924                        "Failed to upload boot level to lowest!",
1925                        return ret);
1926
1927                ret = vega12_upload_dpm_max_level(hwmgr);
1928                PP_ASSERT_WITH_CODE(!ret,
1929                        "Failed to upload dpm max level to highest!",
1930                        return ret);
1931                break;
1932
1933        case PP_MCLK:
1934                soft_min_level = mask ? (ffs(mask) - 1) : 0;
1935                soft_max_level = mask ? (fls(mask) - 1) : 0;
1936
1937                data->dpm_table.mem_table.dpm_state.soft_min_level =
1938                        data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
1939                data->dpm_table.mem_table.dpm_state.soft_max_level =
1940                        data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
1941
1942                ret = vega12_upload_dpm_min_level(hwmgr);
1943                PP_ASSERT_WITH_CODE(!ret,
1944                        "Failed to upload boot level to lowest!",
1945                        return ret);
1946
1947                ret = vega12_upload_dpm_max_level(hwmgr);
1948                PP_ASSERT_WITH_CODE(!ret,
1949                        "Failed to upload dpm max level to highest!",
1950                        return ret);
1951
1952                break;
1953
1954        case PP_SOCCLK:
1955                soft_min_level = mask ? (ffs(mask) - 1) : 0;
1956                soft_max_level = mask ? (fls(mask) - 1) : 0;
1957
1958                if (soft_max_level >= data->dpm_table.soc_table.count) {
1959                        pr_err("Clock level specified %d is over max allowed %d\n",
1960                                        soft_max_level,
1961                                        data->dpm_table.soc_table.count - 1);
1962                        return -EINVAL;
1963                }
1964
1965                data->dpm_table.soc_table.dpm_state.soft_min_level =
1966                        data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
1967                data->dpm_table.soc_table.dpm_state.soft_max_level =
1968                        data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
1969
1970                ret = vega12_upload_dpm_min_level(hwmgr);
1971                PP_ASSERT_WITH_CODE(!ret,
1972                        "Failed to upload boot level to lowest!",
1973                        return ret);
1974
1975                ret = vega12_upload_dpm_max_level(hwmgr);
1976                PP_ASSERT_WITH_CODE(!ret,
1977                        "Failed to upload dpm max level to highest!",
1978                        return ret);
1979
1980                break;
1981
1982        case PP_DCEFCLK:
1983                hard_min_level = mask ? (ffs(mask) - 1) : 0;
1984
1985                if (hard_min_level >= data->dpm_table.dcef_table.count) {
1986                        pr_err("Clock level specified %d is over max allowed %d\n",
1987                                        hard_min_level,
1988                                        data->dpm_table.dcef_table.count - 1);
1989                        return -EINVAL;
1990                }
1991
1992                data->dpm_table.dcef_table.dpm_state.hard_min_level =
1993                        data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
1994
1995                ret = vega12_upload_dpm_min_level(hwmgr);
1996                PP_ASSERT_WITH_CODE(!ret,
1997                        "Failed to upload boot level to lowest!",
1998                        return ret);
1999
2000                //TODO: Setting DCEFCLK max dpm level is not supported
2001
2002                break;
2003
2004        case PP_PCIE:
2005                break;
2006
2007        default:
2008                break;
2009        }
2010
2011        return 0;
2012}
2013
2014static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
2015{
2016        static const char *ppfeature_name[] = {
2017                        "DPM_PREFETCHER",
2018                        "GFXCLK_DPM",
2019                        "UCLK_DPM",
2020                        "SOCCLK_DPM",
2021                        "UVD_DPM",
2022                        "VCE_DPM",
2023                        "ULV",
2024                        "MP0CLK_DPM",
2025                        "LINK_DPM",
2026                        "DCEFCLK_DPM",
2027                        "GFXCLK_DS",
2028                        "SOCCLK_DS",
2029                        "LCLK_DS",
2030                        "PPT",
2031                        "TDC",
2032                        "THERMAL",
2033                        "GFX_PER_CU_CG",
2034                        "RM",
2035                        "DCEFCLK_DS",
2036                        "ACDC",
2037                        "VR0HOT",
2038                        "VR1HOT",
2039                        "FW_CTF",
2040                        "LED_DISPLAY",
2041                        "FAN_CONTROL",
2042                        "DIDT",
2043                        "GFXOFF",
2044                        "CG",
2045                        "ACG"};
2046        static const char *output_title[] = {
2047                        "FEATURES",
2048                        "BITMASK",
2049                        "ENABLEMENT"};
2050        uint64_t features_enabled;
2051        int i;
2052        int ret = 0;
2053        int size = 0;
2054
2055        ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled);
2056        PP_ASSERT_WITH_CODE(!ret,
2057                "[EnableAllSmuFeatures] Failed to get enabled smc features!",
2058                return ret);
2059
2060        size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
2061        size += sprintf(buf + size, "%-19s %-22s %s\n",
2062                                output_title[0],
2063                                output_title[1],
2064                                output_title[2]);
2065        for (i = 0; i < GNLD_FEATURES_MAX; i++) {
2066                size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
2067                                ppfeature_name[i],
2068                                1ULL << i,
2069                                (features_enabled & (1ULL << i)) ? "Y" : "N");
2070        }
2071
2072        return size;
2073}
2074
2075static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
2076{
2077        uint64_t features_enabled;
2078        uint64_t features_to_enable;
2079        uint64_t features_to_disable;
2080        int ret = 0;
2081
2082        if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
2083                return -EINVAL;
2084
2085        ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled);
2086        if (ret)
2087                return ret;
2088
2089        features_to_disable =
2090                features_enabled & ~new_ppfeature_masks;
2091        features_to_enable =
2092                ~features_enabled & new_ppfeature_masks;
2093
2094        pr_debug("features_to_disable 0x%llx\n", features_to_disable);
2095        pr_debug("features_to_enable 0x%llx\n", features_to_enable);
2096
2097        if (features_to_disable) {
2098                ret = vega12_enable_smc_features(hwmgr, false, features_to_disable);
2099                if (ret)
2100                        return ret;
2101        }
2102
2103        if (features_to_enable) {
2104                ret = vega12_enable_smc_features(hwmgr, true, features_to_enable);
2105                if (ret)
2106                        return ret;
2107        }
2108
2109        return 0;
2110}
2111
2112static int vega12_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr)
2113{
2114        struct amdgpu_device *adev = hwmgr->adev;
2115
2116        return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
2117                PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
2118                >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
2119}
2120
2121static int vega12_get_current_pcie_link_width(struct pp_hwmgr *hwmgr)
2122{
2123        uint32_t width_level;
2124
2125        width_level = vega12_get_current_pcie_link_width_level(hwmgr);
2126        if (width_level > LINK_WIDTH_MAX)
2127                width_level = 0;
2128
2129        return link_width[width_level];
2130}
2131
2132static int vega12_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
2133{
2134        struct amdgpu_device *adev = hwmgr->adev;
2135
2136        return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
2137                PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
2138                >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
2139}
2140
2141static int vega12_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr)
2142{
2143        uint32_t speed_level;
2144
2145        speed_level = vega12_get_current_pcie_link_speed_level(hwmgr);
2146        if (speed_level > LINK_SPEED_MAX)
2147                speed_level = 0;
2148
2149        return link_speed[speed_level];
2150}
2151
2152static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
2153                enum pp_clock_type type, char *buf)
2154{
2155        int i, now, size = 0;
2156        struct pp_clock_levels_with_latency clocks;
2157
2158        switch (type) {
2159        case PP_SCLK:
2160                PP_ASSERT_WITH_CODE(
2161                                vega12_get_current_gfx_clk_freq(hwmgr, &now) == 0,
2162                                "Attempt to get current gfx clk Failed!",
2163                                return -1);
2164
2165                PP_ASSERT_WITH_CODE(
2166                                vega12_get_sclks(hwmgr, &clocks) == 0,
2167                                "Attempt to get gfx clk levels Failed!",
2168                                return -1);
2169                for (i = 0; i < clocks.num_levels; i++)
2170                        size += sprintf(buf + size, "%d: %uMhz %s\n",
2171                                i, clocks.data[i].clocks_in_khz / 1000,
2172                                (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : "");
2173                break;
2174
2175        case PP_MCLK:
2176                PP_ASSERT_WITH_CODE(
2177                                vega12_get_current_mclk_freq(hwmgr, &now) == 0,
2178                                "Attempt to get current mclk freq Failed!",
2179                                return -1);
2180
2181                PP_ASSERT_WITH_CODE(
2182                                vega12_get_memclocks(hwmgr, &clocks) == 0,
2183                                "Attempt to get memory clk levels Failed!",
2184                                return -1);
2185                for (i = 0; i < clocks.num_levels; i++)
2186                        size += sprintf(buf + size, "%d: %uMhz %s\n",
2187                                i, clocks.data[i].clocks_in_khz / 1000,
2188                                (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : "");
2189                break;
2190
2191        case PP_SOCCLK:
2192                PP_ASSERT_WITH_CODE(
2193                                smum_send_msg_to_smc_with_parameter(hwmgr,
2194                                        PPSMC_MSG_GetDpmClockFreq, (PPCLK_SOCCLK << 16),
2195                                        &now) == 0,
2196                                "Attempt to get Current SOCCLK Frequency Failed!",
2197                                return -EINVAL);
2198
2199                PP_ASSERT_WITH_CODE(
2200                                vega12_get_socclocks(hwmgr, &clocks) == 0,
2201                                "Attempt to get soc clk levels Failed!",
2202                                return -1);
2203                for (i = 0; i < clocks.num_levels; i++)
2204                        size += sprintf(buf + size, "%d: %uMhz %s\n",
2205                                i, clocks.data[i].clocks_in_khz / 1000,
2206                                (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
2207                break;
2208
2209        case PP_DCEFCLK:
2210                PP_ASSERT_WITH_CODE(
2211                                smum_send_msg_to_smc_with_parameter(hwmgr,
2212                                        PPSMC_MSG_GetDpmClockFreq, (PPCLK_DCEFCLK << 16),
2213                                        &now) == 0,
2214                                "Attempt to get Current DCEFCLK Frequency Failed!",
2215                                return -EINVAL);
2216
2217                PP_ASSERT_WITH_CODE(
2218                                vega12_get_dcefclocks(hwmgr, &clocks) == 0,
2219                                "Attempt to get dcef clk levels Failed!",
2220                                return -1);
2221                for (i = 0; i < clocks.num_levels; i++)
2222                        size += sprintf(buf + size, "%d: %uMhz %s\n",
2223                                i, clocks.data[i].clocks_in_khz / 1000,
2224                                (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
2225                break;
2226
2227        case PP_PCIE:
2228                break;
2229
2230        default:
2231                break;
2232        }
2233        return size;
2234}
2235
2236static int vega12_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
2237{
2238        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2239        struct vega12_single_dpm_table *dpm_table;
2240        bool vblank_too_short = false;
2241        bool disable_mclk_switching;
2242        uint32_t i, latency;
2243
2244        disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
2245                                  !hwmgr->display_config->multi_monitor_in_sync) ||
2246                                  vblank_too_short;
2247        latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
2248
2249        /* gfxclk */
2250        dpm_table = &(data->dpm_table.gfx_table);
2251        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2252        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2253        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2254        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2255
2256        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2257                if (VEGA12_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
2258                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value;
2259                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value;
2260                }
2261
2262                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2263                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2264                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2265                }
2266
2267                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2268                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2269                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2270                }
2271        }
2272
2273        /* memclk */
2274        dpm_table = &(data->dpm_table.mem_table);
2275        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2276        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2277        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2278        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2279
2280        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2281                if (VEGA12_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
2282                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value;
2283                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value;
2284                }
2285
2286                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2287                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2288                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
2289                }
2290
2291                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2292                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2293                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2294                }
2295        }
2296
2297        /* honour DAL's UCLK Hardmin */
2298        if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
2299                dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
2300
2301        /* Hardmin is dependent on displayconfig */
2302        if (disable_mclk_switching) {
2303                dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2304                for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
2305                        if (data->mclk_latency_table.entries[i].latency <= latency) {
2306                                if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
2307                                        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
2308                                        break;
2309                                }
2310                        }
2311                }
2312        }
2313
2314        if (hwmgr->display_config->nb_pstate_switch_disable)
2315                dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2316
2317        /* vclk */
2318        dpm_table = &(data->dpm_table.vclk_table);
2319        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2320        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2321        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2322        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2323
2324        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2325                if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2326                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value;
2327                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value;
2328                }
2329
2330                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2331                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2332                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2333                }
2334        }
2335
2336        /* dclk */
2337        dpm_table = &(data->dpm_table.dclk_table);
2338        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2339        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2340        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2341        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2342
2343        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2344                if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
2345                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value;
2346                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value;
2347                }
2348
2349                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2350                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2351                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2352                }
2353        }
2354
2355        /* socclk */
2356        dpm_table = &(data->dpm_table.soc_table);
2357        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2358        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2359        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2360        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2361
2362        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2363                if (VEGA12_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
2364                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value;
2365                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value;
2366                }
2367
2368                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2369                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2370                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2371                }
2372        }
2373
2374        /* eclk */
2375        dpm_table = &(data->dpm_table.eclk_table);
2376        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
2377        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2378        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
2379        dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2380
2381        if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
2382                if (VEGA12_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
2383                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value;
2384                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value;
2385                }
2386
2387                if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2388                        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2389                        dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2390                }
2391        }
2392
2393        return 0;
2394}
2395
2396static int vega12_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
2397                struct vega12_single_dpm_table *dpm_table)
2398{
2399        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2400        int ret = 0;
2401
2402        if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2403                PP_ASSERT_WITH_CODE(dpm_table->count > 0,
2404                                "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
2405                                return -EINVAL);
2406                PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
2407                                "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
2408                                return -EINVAL);
2409
2410                dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
2411                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2412                                PPSMC_MSG_SetHardMinByFreq,
2413                                (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level,
2414                                NULL)),
2415                                "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
2416                                return ret);
2417        }
2418
2419        return ret;
2420}
2421
2422static int vega12_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
2423{
2424        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2425        int ret = 0;
2426
2427        smum_send_msg_to_smc_with_parameter(hwmgr,
2428                        PPSMC_MSG_NumOfDisplays, 0,
2429                        NULL);
2430
2431        ret = vega12_set_uclk_to_highest_dpm_level(hwmgr,
2432                        &data->dpm_table.mem_table);
2433
2434        return ret;
2435}
2436
2437static int vega12_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
2438{
2439        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2440        int result = 0;
2441        Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
2442
2443        if ((data->water_marks_bitmap & WaterMarksExist) &&
2444                        !(data->water_marks_bitmap & WaterMarksLoaded)) {
2445                result = smum_smc_table_manager(hwmgr,
2446                                                (uint8_t *)wm_table, TABLE_WATERMARKS, false);
2447                PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL);
2448                data->water_marks_bitmap |= WaterMarksLoaded;
2449        }
2450
2451        if ((data->water_marks_bitmap & WaterMarksExist) &&
2452                data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2453                data->smu_features[GNLD_DPM_SOCCLK].supported)
2454                smum_send_msg_to_smc_with_parameter(hwmgr,
2455                        PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display,
2456                        NULL);
2457
2458        return result;
2459}
2460
2461static int vega12_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
2462{
2463        struct vega12_hwmgr *data =
2464                        (struct vega12_hwmgr *)(hwmgr->backend);
2465
2466        if (data->smu_features[GNLD_DPM_UVD].supported) {
2467                PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr,
2468                                enable,
2469                                data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap),
2470                                "Attempt to Enable/Disable DPM UVD Failed!",
2471                                return -1);
2472                data->smu_features[GNLD_DPM_UVD].enabled = enable;
2473        }
2474
2475        return 0;
2476}
2477
2478static void vega12_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
2479{
2480        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2481
2482        if (data->vce_power_gated == bgate)
2483                return;
2484
2485        data->vce_power_gated = bgate;
2486        vega12_enable_disable_vce_dpm(hwmgr, !bgate);
2487}
2488
2489static void vega12_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
2490{
2491        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2492
2493        if (data->uvd_power_gated == bgate)
2494                return;
2495
2496        data->uvd_power_gated = bgate;
2497        vega12_enable_disable_uvd_dpm(hwmgr, !bgate);
2498}
2499
2500static bool
2501vega12_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
2502{
2503        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2504        bool is_update_required = false;
2505
2506        if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
2507                is_update_required = true;
2508
2509        if (data->registry_data.gfx_clk_deep_sleep_support) {
2510                if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr)
2511                        is_update_required = true;
2512        }
2513
2514        return is_update_required;
2515}
2516
2517static int vega12_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
2518{
2519        int tmp_result, result = 0;
2520
2521        tmp_result = vega12_disable_all_smu_features(hwmgr);
2522        PP_ASSERT_WITH_CODE((tmp_result == 0),
2523                        "Failed to disable all smu features!", result = tmp_result);
2524
2525        return result;
2526}
2527
2528static int vega12_power_off_asic(struct pp_hwmgr *hwmgr)
2529{
2530        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2531        int result;
2532
2533        result = vega12_disable_dpm_tasks(hwmgr);
2534        PP_ASSERT_WITH_CODE((0 == result),
2535                        "[disable_dpm_tasks] Failed to disable DPM!",
2536                        );
2537        data->water_marks_bitmap &= ~(WaterMarksLoaded);
2538
2539        return result;
2540}
2541
2542#if 0
2543static void vega12_find_min_clock_index(struct pp_hwmgr *hwmgr,
2544                uint32_t *sclk_idx, uint32_t *mclk_idx,
2545                uint32_t min_sclk, uint32_t min_mclk)
2546{
2547        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2548        struct vega12_dpm_table *dpm_table = &(data->dpm_table);
2549        uint32_t i;
2550
2551        for (i = 0; i < dpm_table->gfx_table.count; i++) {
2552                if (dpm_table->gfx_table.dpm_levels[i].enabled &&
2553                        dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) {
2554                        *sclk_idx = i;
2555                        break;
2556                }
2557        }
2558
2559        for (i = 0; i < dpm_table->mem_table.count; i++) {
2560                if (dpm_table->mem_table.dpm_levels[i].enabled &&
2561                        dpm_table->mem_table.dpm_levels[i].value >= min_mclk) {
2562                        *mclk_idx = i;
2563                        break;
2564                }
2565        }
2566}
2567#endif
2568
2569#if 0
2570static int vega12_set_power_profile_state(struct pp_hwmgr *hwmgr,
2571                struct amd_pp_profile *request)
2572{
2573        return 0;
2574}
2575
2576static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)
2577{
2578        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2579        struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
2580        struct vega12_single_dpm_table *golden_sclk_table =
2581                        &(data->golden_dpm_table.gfx_table);
2582        int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
2583        int golden_value = golden_sclk_table->dpm_levels
2584                        [golden_sclk_table->count - 1].value;
2585
2586        value -= golden_value;
2587        value = DIV_ROUND_UP(value * 100, golden_value);
2588
2589        return value;
2590}
2591
2592static int vega12_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
2593{
2594        return 0;
2595}
2596
2597static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)
2598{
2599        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
2600        struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
2601        struct vega12_single_dpm_table *golden_mclk_table =
2602                        &(data->golden_dpm_table.mem_table);
2603        int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
2604        int golden_value = golden_mclk_table->dpm_levels
2605                        [golden_mclk_table->count - 1].value;
2606
2607        value -= golden_value;
2608        value = DIV_ROUND_UP(value * 100, golden_value);
2609
2610        return value;
2611}
2612
2613static int vega12_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
2614{
2615        return 0;
2616}
2617#endif
2618
2619static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
2620                                        uint32_t virtual_addr_low,
2621                                        uint32_t virtual_addr_hi,
2622                                        uint32_t mc_addr_low,
2623                                        uint32_t mc_addr_hi,
2624                                        uint32_t size)
2625{
2626        smum_send_msg_to_smc_with_parameter(hwmgr,
2627                                        PPSMC_MSG_SetSystemVirtualDramAddrHigh,
2628                                        virtual_addr_hi,
2629                                        NULL);
2630        smum_send_msg_to_smc_with_parameter(hwmgr,
2631                                        PPSMC_MSG_SetSystemVirtualDramAddrLow,
2632                                        virtual_addr_low,
2633                                        NULL);
2634        smum_send_msg_to_smc_with_parameter(hwmgr,
2635                                        PPSMC_MSG_DramLogSetDramAddrHigh,
2636                                        mc_addr_hi,
2637                                        NULL);
2638
2639        smum_send_msg_to_smc_with_parameter(hwmgr,
2640                                        PPSMC_MSG_DramLogSetDramAddrLow,
2641                                        mc_addr_low,
2642                                        NULL);
2643
2644        smum_send_msg_to_smc_with_parameter(hwmgr,
2645                                        PPSMC_MSG_DramLogSetDramSize,
2646                                        size,
2647                                        NULL);
2648        return 0;
2649}
2650
2651static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
2652                struct PP_TemperatureRange *thermal_data)
2653{
2654        struct vega12_hwmgr *data =
2655                        (struct vega12_hwmgr *)(hwmgr->backend);
2656        PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2657
2658        memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
2659
2660        thermal_data->max = pp_table->TedgeLimit *
2661                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2662        thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
2663                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2664        thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
2665                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2666        thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
2667                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2668        thermal_data->mem_crit_max = pp_table->ThbmLimit *
2669                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2670        thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
2671                PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2672
2673        return 0;
2674}
2675
2676static int vega12_enable_gfx_off(struct pp_hwmgr *hwmgr)
2677{
2678        struct vega12_hwmgr *data =
2679                        (struct vega12_hwmgr *)(hwmgr->backend);
2680        int ret = 0;
2681
2682        if (data->gfxoff_controlled_by_driver)
2683                ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_AllowGfxOff, NULL);
2684
2685        return ret;
2686}
2687
2688static int vega12_disable_gfx_off(struct pp_hwmgr *hwmgr)
2689{
2690        struct vega12_hwmgr *data =
2691                        (struct vega12_hwmgr *)(hwmgr->backend);
2692        int ret = 0;
2693
2694        if (data->gfxoff_controlled_by_driver)
2695                ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisallowGfxOff, NULL);
2696
2697        return ret;
2698}
2699
2700static int vega12_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable)
2701{
2702        if (enable)
2703                return vega12_enable_gfx_off(hwmgr);
2704        else
2705                return vega12_disable_gfx_off(hwmgr);
2706}
2707
2708static int vega12_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
2709                                PHM_PerformanceLevelDesignation designation, uint32_t index,
2710                                PHM_PerformanceLevel *level)
2711{
2712        return 0;
2713}
2714
2715static int vega12_set_mp1_state(struct pp_hwmgr *hwmgr,
2716                                enum pp_mp1_state mp1_state)
2717{
2718        uint16_t msg;
2719        int ret;
2720
2721        switch (mp1_state) {
2722        case PP_MP1_STATE_UNLOAD:
2723                msg = PPSMC_MSG_PrepareMp1ForUnload;
2724                break;
2725        case PP_MP1_STATE_SHUTDOWN:
2726        case PP_MP1_STATE_RESET:
2727        case PP_MP1_STATE_NONE:
2728        default:
2729                return 0;
2730        }
2731
2732        PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0,
2733                            "[PrepareMp1] Failed!",
2734                            return ret);
2735
2736        return 0;
2737}
2738
2739static void vega12_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
2740{
2741        memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0));
2742
2743        gpu_metrics->common_header.structure_size =
2744                                sizeof(struct gpu_metrics_v1_0);
2745        gpu_metrics->common_header.format_revision = 1;
2746        gpu_metrics->common_header.content_revision = 0;
2747
2748        gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
2749}
2750
2751static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr,
2752                                      void **table)
2753{
2754        struct vega12_hwmgr *data =
2755                        (struct vega12_hwmgr *)(hwmgr->backend);
2756        struct gpu_metrics_v1_0 *gpu_metrics =
2757                        &data->gpu_metrics_table;
2758        SmuMetrics_t metrics;
2759        uint32_t fan_speed_rpm;
2760        int ret;
2761
2762        ret = vega12_get_metrics_table(hwmgr, &metrics, true);
2763        if (ret)
2764                return ret;
2765
2766        vega12_init_gpu_metrics_v1_0(gpu_metrics);
2767
2768        gpu_metrics->temperature_edge = metrics.TemperatureEdge;
2769        gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
2770        gpu_metrics->temperature_mem = metrics.TemperatureHBM;
2771        gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
2772        gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem;
2773
2774        gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
2775        gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
2776
2777        gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
2778        gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
2779        gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
2780
2781        gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
2782        gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
2783        gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
2784        gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
2785        gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
2786
2787        gpu_metrics->throttle_status = metrics.ThrottlerStatus;
2788
2789        vega12_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm);
2790        gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm;
2791
2792        gpu_metrics->pcie_link_width =
2793                        vega12_get_current_pcie_link_width(hwmgr);
2794        gpu_metrics->pcie_link_speed =
2795                        vega12_get_current_pcie_link_speed(hwmgr);
2796
2797        *table = (void *)gpu_metrics;
2798
2799        return sizeof(struct gpu_metrics_v1_0);
2800}
2801
2802static const struct pp_hwmgr_func vega12_hwmgr_funcs = {
2803        .backend_init = vega12_hwmgr_backend_init,
2804        .backend_fini = vega12_hwmgr_backend_fini,
2805        .asic_setup = vega12_setup_asic_task,
2806        .dynamic_state_management_enable = vega12_enable_dpm_tasks,
2807        .dynamic_state_management_disable = vega12_disable_dpm_tasks,
2808        .patch_boot_state = vega12_patch_boot_state,
2809        .get_sclk = vega12_dpm_get_sclk,
2810        .get_mclk = vega12_dpm_get_mclk,
2811        .notify_smc_display_config_after_ps_adjustment =
2812                        vega12_notify_smc_display_config_after_ps_adjustment,
2813        .force_dpm_level = vega12_dpm_force_dpm_level,
2814        .stop_thermal_controller = vega12_thermal_stop_thermal_controller,
2815        .get_fan_speed_info = vega12_fan_ctrl_get_fan_speed_info,
2816        .reset_fan_speed_to_default =
2817                        vega12_fan_ctrl_reset_fan_speed_to_default,
2818        .get_fan_speed_rpm = vega12_fan_ctrl_get_fan_speed_rpm,
2819        .set_fan_control_mode = vega12_set_fan_control_mode,
2820        .get_fan_control_mode = vega12_get_fan_control_mode,
2821        .read_sensor = vega12_read_sensor,
2822        .get_dal_power_level = vega12_get_dal_power_level,
2823        .get_clock_by_type_with_latency = vega12_get_clock_by_type_with_latency,
2824        .get_clock_by_type_with_voltage = vega12_get_clock_by_type_with_voltage,
2825        .set_watermarks_for_clocks_ranges = vega12_set_watermarks_for_clocks_ranges,
2826        .display_clock_voltage_request = vega12_display_clock_voltage_request,
2827        .force_clock_level = vega12_force_clock_level,
2828        .print_clock_levels = vega12_print_clock_levels,
2829        .apply_clocks_adjust_rules =
2830                vega12_apply_clocks_adjust_rules,
2831        .pre_display_config_changed =
2832                vega12_pre_display_configuration_changed_task,
2833        .display_config_changed = vega12_display_configuration_changed_task,
2834        .powergate_uvd = vega12_power_gate_uvd,
2835        .powergate_vce = vega12_power_gate_vce,
2836        .check_smc_update_required_for_display_configuration =
2837                        vega12_check_smc_update_required_for_display_configuration,
2838        .power_off_asic = vega12_power_off_asic,
2839        .disable_smc_firmware_ctf = vega12_thermal_disable_alert,
2840#if 0
2841        .set_power_profile_state = vega12_set_power_profile_state,
2842        .get_sclk_od = vega12_get_sclk_od,
2843        .set_sclk_od = vega12_set_sclk_od,
2844        .get_mclk_od = vega12_get_mclk_od,
2845        .set_mclk_od = vega12_set_mclk_od,
2846#endif
2847        .notify_cac_buffer_info = vega12_notify_cac_buffer_info,
2848        .get_thermal_temperature_range = vega12_get_thermal_temperature_range,
2849        .register_irq_handlers = smu9_register_irq_handlers,
2850        .start_thermal_controller = vega12_start_thermal_controller,
2851        .powergate_gfx = vega12_gfx_off_control,
2852        .get_performance_level = vega12_get_performance_level,
2853        .get_asic_baco_capability = smu9_baco_get_capability,
2854        .get_asic_baco_state = smu9_baco_get_state,
2855        .set_asic_baco_state = vega12_baco_set_state,
2856        .get_ppfeature_status = vega12_get_ppfeature_status,
2857        .set_ppfeature_status = vega12_set_ppfeature_status,
2858        .set_mp1_state = vega12_set_mp1_state,
2859        .get_gpu_metrics = vega12_get_gpu_metrics,
2860};
2861
2862int vega12_hwmgr_init(struct pp_hwmgr *hwmgr)
2863{
2864        hwmgr->hwmgr_func = &vega12_hwmgr_funcs;
2865        hwmgr->pptable_func = &vega12_pptable_funcs;
2866
2867        return 0;
2868}
2869