LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/pm/powerplay/hwmgr - vega10_hwmgr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 2552 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 116 0.0 %

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

Generated by: LCOV version 1.14