cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vega10_hwmgr.c (185166B)


      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
     62static 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
     79typedef 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
     94static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic);
     95
     96static struct vega10_power_state *cast_phw_vega10_power_state(
     97				  struct pp_hw_power_state *hw_ps)
     98{
     99	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
    106static const struct vega10_power_state *cast_const_phw_vega10_power_state(
    107				 const struct pp_hw_power_state *hw_ps)
    108{
    109	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
    116static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
    117{
    118	struct vega10_hwmgr *data = hwmgr->backend;
    119
    120	data->registry_data.sclk_dpm_key_disabled =
    121			hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
    122	data->registry_data.socclk_dpm_key_disabled =
    123			hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true;
    124	data->registry_data.mclk_dpm_key_disabled =
    125			hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
    126	data->registry_data.pcie_dpm_key_disabled =
    127			hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
    128
    129	data->registry_data.dcefclk_dpm_key_disabled =
    130			hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true;
    131
    132	if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
    133		data->registry_data.power_containment_support = 1;
    134		data->registry_data.enable_pkg_pwr_tracking_feature = 1;
    135		data->registry_data.enable_tdc_limit_feature = 1;
    136	}
    137
    138	data->registry_data.clock_stretcher_support =
    139			hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false;
    140
    141	data->registry_data.ulv_support =
    142			hwmgr->feature_mask & PP_ULV_MASK ? true : false;
    143
    144	data->registry_data.sclk_deep_sleep_support =
    145			hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false;
    146
    147	data->registry_data.disable_water_mark = 0;
    148
    149	data->registry_data.fan_control_support = 1;
    150	data->registry_data.thermal_support = 1;
    151	data->registry_data.fw_ctf_enabled = 1;
    152
    153	data->registry_data.avfs_support =
    154		hwmgr->feature_mask & PP_AVFS_MASK ? true : false;
    155	data->registry_data.led_dpm_enabled = 1;
    156
    157	data->registry_data.vr0hot_enabled = 1;
    158	data->registry_data.vr1hot_enabled = 1;
    159	data->registry_data.regulator_hot_gpio_support = 1;
    160
    161	data->registry_data.didt_support = 1;
    162	if (data->registry_data.didt_support) {
    163		data->registry_data.didt_mode = 6;
    164		data->registry_data.sq_ramping_support = 1;
    165		data->registry_data.db_ramping_support = 0;
    166		data->registry_data.td_ramping_support = 0;
    167		data->registry_data.tcp_ramping_support = 0;
    168		data->registry_data.dbr_ramping_support = 0;
    169		data->registry_data.edc_didt_support = 1;
    170		data->registry_data.gc_didt_support = 0;
    171		data->registry_data.psm_didt_support = 0;
    172	}
    173
    174	data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT;
    175	data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    176	data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    177	data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    178	data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    179	data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    180	data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    181	data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    182	data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    183	data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    184	data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    185	data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    186	data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
    187
    188	data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT;
    189	data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT;
    190	data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT;
    191	data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT;
    192}
    193
    194static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
    195{
    196	struct vega10_hwmgr *data = hwmgr->backend;
    197	struct phm_ppt_v2_information *table_info =
    198			(struct phm_ppt_v2_information *)hwmgr->pptable;
    199	struct amdgpu_device *adev = hwmgr->adev;
    200
    201	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    202			PHM_PlatformCaps_SclkDeepSleep);
    203
    204	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    205			PHM_PlatformCaps_DynamicPatchPowerState);
    206
    207	if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE)
    208		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    209				PHM_PlatformCaps_ControlVDDCI);
    210
    211	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    212			PHM_PlatformCaps_EnableSMU7ThermalManagement);
    213
    214	if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
    215		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    216				PHM_PlatformCaps_UVDPowerGating);
    217
    218	if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
    219		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    220				PHM_PlatformCaps_VCEPowerGating);
    221
    222	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    223			PHM_PlatformCaps_UnTabledHardwareInterface);
    224
    225	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    226			PHM_PlatformCaps_FanSpeedInTableIsRPM);
    227
    228	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    229			PHM_PlatformCaps_ODFuzzyFanControlSupport);
    230
    231	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    232				PHM_PlatformCaps_DynamicPowerManagement);
    233
    234	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    235			PHM_PlatformCaps_SMC);
    236
    237	/* power tune caps */
    238	/* assume disabled */
    239	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    240			PHM_PlatformCaps_PowerContainment);
    241	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    242			PHM_PlatformCaps_DiDtSupport);
    243	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    244			PHM_PlatformCaps_SQRamping);
    245	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    246			PHM_PlatformCaps_DBRamping);
    247	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    248			PHM_PlatformCaps_TDRamping);
    249	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    250			PHM_PlatformCaps_TCPRamping);
    251	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    252			PHM_PlatformCaps_DBRRamping);
    253	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    254			PHM_PlatformCaps_DiDtEDCEnable);
    255	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    256			PHM_PlatformCaps_GCEDC);
    257	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
    258			PHM_PlatformCaps_PSM);
    259
    260	if (data->registry_data.didt_support) {
    261		phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport);
    262		if (data->registry_data.sq_ramping_support)
    263			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping);
    264		if (data->registry_data.db_ramping_support)
    265			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping);
    266		if (data->registry_data.td_ramping_support)
    267			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping);
    268		if (data->registry_data.tcp_ramping_support)
    269			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping);
    270		if (data->registry_data.dbr_ramping_support)
    271			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping);
    272		if (data->registry_data.edc_didt_support)
    273			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable);
    274		if (data->registry_data.gc_didt_support)
    275			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC);
    276		if (data->registry_data.psm_didt_support)
    277			phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM);
    278	}
    279
    280	if (data->registry_data.power_containment_support)
    281		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    282				PHM_PlatformCaps_PowerContainment);
    283	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    284			PHM_PlatformCaps_CAC);
    285
    286	if (table_info->tdp_table->usClockStretchAmount &&
    287			data->registry_data.clock_stretcher_support)
    288		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    289				PHM_PlatformCaps_ClockStretcher);
    290
    291	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    292			PHM_PlatformCaps_RegulatorHot);
    293	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    294			PHM_PlatformCaps_AutomaticDCTransition);
    295
    296	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    297			PHM_PlatformCaps_UVDDPM);
    298	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    299			PHM_PlatformCaps_VCEDPM);
    300
    301	return 0;
    302}
    303
    304static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
    305{
    306	struct vega10_hwmgr *data = hwmgr->backend;
    307	struct phm_ppt_v2_information *table_info =
    308			(struct phm_ppt_v2_information *)(hwmgr->pptable);
    309	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	struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
    315	uint32_t i;
    316	int result;
    317
    318	result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
    319	if (!result) {
    320		data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc;
    321		data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc;
    322	}
    323
    324	od_lookup_table = &odn_table->vddc_lookup_table;
    325	vddc_lookup_table = table_info->vddc_lookup_table;
    326
    327	for (i = 0; i < vddc_lookup_table->count; i++)
    328		od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd;
    329
    330	od_lookup_table->count = vddc_lookup_table->count;
    331
    332	dep_table[0] = table_info->vdd_dep_on_sclk;
    333	dep_table[1] = table_info->vdd_dep_on_mclk;
    334	dep_table[2] = table_info->vdd_dep_on_socclk;
    335	od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk;
    336	od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk;
    337	od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk;
    338
    339	for (i = 0; i < 3; i++)
    340		smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]);
    341
    342	if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000)
    343		odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc;
    344	if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000)
    345		odn_table->min_vddc = dep_table[0]->entries[0].vddc;
    346
    347	i = od_table[2]->count - 1;
    348	od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ?
    349					hwmgr->platform_descriptor.overdriveLimit.memoryClock :
    350					od_table[2]->entries[i].clk;
    351	od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ?
    352					odn_table->max_vddc :
    353					od_table[2]->entries[i].vddc;
    354
    355	return 0;
    356}
    357
    358static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
    359{
    360	struct vega10_hwmgr *data = hwmgr->backend;
    361	int i;
    362	uint32_t sub_vendor_id, hw_revision;
    363	uint32_t top32, bottom32;
    364	struct amdgpu_device *adev = hwmgr->adev;
    365
    366	vega10_initialize_power_tune_defaults(hwmgr);
    367
    368	for (i = 0; i < GNLD_FEATURES_MAX; i++) {
    369		data->smu_features[i].smu_feature_id = 0xffff;
    370		data->smu_features[i].smu_feature_bitmap = 1 << i;
    371		data->smu_features[i].enabled = false;
    372		data->smu_features[i].supported = false;
    373	}
    374
    375	data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
    376			FEATURE_DPM_PREFETCHER_BIT;
    377	data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
    378			FEATURE_DPM_GFXCLK_BIT;
    379	data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
    380			FEATURE_DPM_UCLK_BIT;
    381	data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
    382			FEATURE_DPM_SOCCLK_BIT;
    383	data->smu_features[GNLD_DPM_UVD].smu_feature_id =
    384			FEATURE_DPM_UVD_BIT;
    385	data->smu_features[GNLD_DPM_VCE].smu_feature_id =
    386			FEATURE_DPM_VCE_BIT;
    387	data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
    388			FEATURE_DPM_MP0CLK_BIT;
    389	data->smu_features[GNLD_DPM_LINK].smu_feature_id =
    390			FEATURE_DPM_LINK_BIT;
    391	data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
    392			FEATURE_DPM_DCEFCLK_BIT;
    393	data->smu_features[GNLD_ULV].smu_feature_id =
    394			FEATURE_ULV_BIT;
    395	data->smu_features[GNLD_AVFS].smu_feature_id =
    396			FEATURE_AVFS_BIT;
    397	data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
    398			FEATURE_DS_GFXCLK_BIT;
    399	data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
    400			FEATURE_DS_SOCCLK_BIT;
    401	data->smu_features[GNLD_DS_LCLK].smu_feature_id =
    402			FEATURE_DS_LCLK_BIT;
    403	data->smu_features[GNLD_PPT].smu_feature_id =
    404			FEATURE_PPT_BIT;
    405	data->smu_features[GNLD_TDC].smu_feature_id =
    406			FEATURE_TDC_BIT;
    407	data->smu_features[GNLD_THERMAL].smu_feature_id =
    408			FEATURE_THERMAL_BIT;
    409	data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
    410			FEATURE_GFX_PER_CU_CG_BIT;
    411	data->smu_features[GNLD_RM].smu_feature_id =
    412			FEATURE_RM_BIT;
    413	data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
    414			FEATURE_DS_DCEFCLK_BIT;
    415	data->smu_features[GNLD_ACDC].smu_feature_id =
    416			FEATURE_ACDC_BIT;
    417	data->smu_features[GNLD_VR0HOT].smu_feature_id =
    418			FEATURE_VR0HOT_BIT;
    419	data->smu_features[GNLD_VR1HOT].smu_feature_id =
    420			FEATURE_VR1HOT_BIT;
    421	data->smu_features[GNLD_FW_CTF].smu_feature_id =
    422			FEATURE_FW_CTF_BIT;
    423	data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
    424			FEATURE_LED_DISPLAY_BIT;
    425	data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
    426			FEATURE_FAN_CONTROL_BIT;
    427	data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
    428	data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
    429	data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT;
    430
    431	if (!data->registry_data.prefetcher_dpm_key_disabled)
    432		data->smu_features[GNLD_DPM_PREFETCHER].supported = true;
    433
    434	if (!data->registry_data.sclk_dpm_key_disabled)
    435		data->smu_features[GNLD_DPM_GFXCLK].supported = true;
    436
    437	if (!data->registry_data.mclk_dpm_key_disabled)
    438		data->smu_features[GNLD_DPM_UCLK].supported = true;
    439
    440	if (!data->registry_data.socclk_dpm_key_disabled)
    441		data->smu_features[GNLD_DPM_SOCCLK].supported = true;
    442
    443	if (PP_CAP(PHM_PlatformCaps_UVDDPM))
    444		data->smu_features[GNLD_DPM_UVD].supported = true;
    445
    446	if (PP_CAP(PHM_PlatformCaps_VCEDPM))
    447		data->smu_features[GNLD_DPM_VCE].supported = true;
    448
    449	data->smu_features[GNLD_DPM_LINK].supported = true;
    450
    451	if (!data->registry_data.dcefclk_dpm_key_disabled)
    452		data->smu_features[GNLD_DPM_DCEFCLK].supported = true;
    453
    454	if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) &&
    455	    data->registry_data.sclk_deep_sleep_support) {
    456		data->smu_features[GNLD_DS_GFXCLK].supported = true;
    457		data->smu_features[GNLD_DS_SOCCLK].supported = true;
    458		data->smu_features[GNLD_DS_LCLK].supported = true;
    459		data->smu_features[GNLD_DS_DCEFCLK].supported = true;
    460	}
    461
    462	if (data->registry_data.enable_pkg_pwr_tracking_feature)
    463		data->smu_features[GNLD_PPT].supported = true;
    464
    465	if (data->registry_data.enable_tdc_limit_feature)
    466		data->smu_features[GNLD_TDC].supported = true;
    467
    468	if (data->registry_data.thermal_support)
    469		data->smu_features[GNLD_THERMAL].supported = true;
    470
    471	if (data->registry_data.fan_control_support)
    472		data->smu_features[GNLD_FAN_CONTROL].supported = true;
    473
    474	if (data->registry_data.fw_ctf_enabled)
    475		data->smu_features[GNLD_FW_CTF].supported = true;
    476
    477	if (data->registry_data.avfs_support)
    478		data->smu_features[GNLD_AVFS].supported = true;
    479
    480	if (data->registry_data.led_dpm_enabled)
    481		data->smu_features[GNLD_LED_DISPLAY].supported = true;
    482
    483	if (data->registry_data.vr1hot_enabled)
    484		data->smu_features[GNLD_VR1HOT].supported = true;
    485
    486	if (data->registry_data.vr0hot_enabled)
    487		data->smu_features[GNLD_VR0HOT].supported = true;
    488
    489	smum_send_msg_to_smc(hwmgr,
    490			PPSMC_MSG_GetSmuVersion,
    491			&hwmgr->smu_version);
    492		/* ACG firmware has major version 5 */
    493	if ((hwmgr->smu_version & 0xff000000) == 0x5000000)
    494		data->smu_features[GNLD_ACG].supported = true;
    495	if (data->registry_data.didt_support)
    496		data->smu_features[GNLD_DIDT].supported = true;
    497
    498	hw_revision = adev->pdev->revision;
    499	sub_vendor_id = adev->pdev->subsystem_vendor;
    500
    501	if ((hwmgr->chip_id == 0x6862 ||
    502		hwmgr->chip_id == 0x6861 ||
    503		hwmgr->chip_id == 0x6868) &&
    504		(hw_revision == 0) &&
    505		(sub_vendor_id != 0x1002))
    506		data->smu_features[GNLD_PCC_LIMIT].supported = true;
    507
    508	/* Get the SN to turn into a Unique ID */
    509	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32);
    510	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32);
    511
    512	adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
    513}
    514
    515#ifdef PPLIB_VEGA10_EVV_SUPPORT
    516static 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 */
    552static 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 */
    609static 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 */
    636static 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
    649static 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
    659static 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	struct phm_ppt_v2_information *table_info =
    665			(struct phm_ppt_v2_information *)(hwmgr->pptable);
    666	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
    667			table_info->mm_dep_table;
    668	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
    669			table_info->vdd_dep_on_mclk;
    670
    671	for (i = 0; i < 6; i++) {
    672		struct phm_ppt_v1_clock_voltage_dependency_table *vdt;
    673		switch (i) {
    674			case 0: vdt = table_info->vdd_dep_on_socclk; break;
    675			case 1: vdt = table_info->vdd_dep_on_sclk; break;
    676			case 2: vdt = table_info->vdd_dep_on_dcefclk; break;
    677			case 3: vdt = table_info->vdd_dep_on_pixclk; break;
    678			case 4: vdt = table_info->vdd_dep_on_dispclk; break;
    679			case 5: vdt = table_info->vdd_dep_on_phyclk; break;
    680		}
    681
    682		for (entry_id = 0; entry_id < vdt->count; entry_id++) {
    683			voltage_id = vdt->entries[entry_id].vddInd;
    684			vdt->entries[entry_id].vddc =
    685					table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
    686		}
    687	}
    688
    689	for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
    690		voltage_id = mm_table->entries[entry_id].vddcInd;
    691		mm_table->entries[entry_id].vddc =
    692			table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
    693	}
    694
    695	for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
    696		voltage_id = mclk_table->entries[entry_id].vddInd;
    697		mclk_table->entries[entry_id].vddc =
    698				table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
    699		voltage_id = mclk_table->entries[entry_id].vddciInd;
    700		mclk_table->entries[entry_id].vddci =
    701				table_info->vddci_lookup_table->entries[voltage_id].us_vdd;
    702		voltage_id = mclk_table->entries[entry_id].mvddInd;
    703		mclk_table->entries[entry_id].mvdd =
    704				table_info->vddmem_lookup_table->entries[voltage_id].us_vdd;
    705	}
    706
    707
    708	return 0;
    709
    710}
    711
    712static 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	PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count,
    718		"Lookup table is empty", return -EINVAL);
    719
    720	table_size = lookup_table->count;
    721
    722	/* Sorting voltages */
    723	for (i = 0; i < table_size - 1; i++) {
    724		for (j = i + 1; j > 0; j--) {
    725			if (lookup_table->entries[j].us_vdd <
    726					lookup_table->entries[j - 1].us_vdd) {
    727				swap(lookup_table->entries[j - 1],
    728				     lookup_table->entries[j]);
    729			}
    730		}
    731	}
    732
    733	return 0;
    734}
    735
    736static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr)
    737{
    738	int result = 0;
    739	int tmp_result;
    740	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	tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
    757	if (tmp_result)
    758		result = tmp_result;
    759
    760	tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
    761	if (tmp_result)
    762		result = tmp_result;
    763
    764	return result;
    765}
    766
    767static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
    768{
    769	struct phm_ppt_v2_information *table_info =
    770			(struct phm_ppt_v2_information *)(hwmgr->pptable);
    771	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
    772			table_info->vdd_dep_on_socclk;
    773	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
    774			table_info->vdd_dep_on_mclk;
    775
    776	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table,
    777		"VDD dependency on SCLK table is missing. This table is mandatory", return -EINVAL);
    778	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	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table,
    782		"VDD dependency on MCLK table is missing.  This table is mandatory", return -EINVAL);
    783	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	table_info->max_clock_voltage_on_ac.sclk =
    787		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
    788	table_info->max_clock_voltage_on_ac.mclk =
    789		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
    790	table_info->max_clock_voltage_on_ac.vddc =
    791		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
    792	table_info->max_clock_voltage_on_ac.vddci =
    793		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
    794
    795	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
    796		table_info->max_clock_voltage_on_ac.sclk;
    797	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
    798		table_info->max_clock_voltage_on_ac.mclk;
    799	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
    800		table_info->max_clock_voltage_on_ac.vddc;
    801	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
    802		table_info->max_clock_voltage_on_ac.vddci;
    803
    804	return 0;
    805}
    806
    807static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
    808{
    809	kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
    810	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
    811
    812	kfree(hwmgr->backend);
    813	hwmgr->backend = NULL;
    814
    815	return 0;
    816}
    817
    818static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
    819{
    820	int result = 0;
    821	struct vega10_hwmgr *data;
    822	uint32_t config_telemetry = 0;
    823	struct pp_atomfwctrl_voltage_table vol_table;
    824	struct amdgpu_device *adev = hwmgr->adev;
    825
    826	data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
    827	if (data == NULL)
    828		return -ENOMEM;
    829
    830	hwmgr->backend = data;
    831
    832	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
    833	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
    834	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
    835
    836	vega10_set_default_registry_data(hwmgr);
    837	data->disable_dpm_mask = 0xff;
    838
    839	/* need to set voltage control types before EVV patching */
    840	data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
    841	data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE;
    842	data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE;
    843
    844	/* VDDCR_SOC */
    845	if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
    846			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
    847		if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
    848				VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2,
    849				&vol_table)) {
    850			config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) |
    851					(vol_table.telemetry_offset & 0xff);
    852			data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
    853		}
    854	} else {
    855		kfree(hwmgr->backend);
    856		hwmgr->backend = NULL;
    857		PP_ASSERT_WITH_CODE(false,
    858				"VDDCR_SOC is not SVID2!",
    859				return -1);
    860	}
    861
    862	/* MVDDC */
    863	if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
    864			VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) {
    865		if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
    866				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2,
    867				&vol_table)) {
    868			config_telemetry |=
    869					((vol_table.telemetry_slope << 24) & 0xff000000) |
    870					((vol_table.telemetry_offset << 16) & 0xff0000);
    871			data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
    872		}
    873	}
    874
    875	 /* VDDCI_MEM */
    876	if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) {
    877		if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
    878				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
    879			data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO;
    880	}
    881
    882	data->config_telemetry = config_telemetry;
    883
    884	vega10_set_features_platform_caps(hwmgr);
    885
    886	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	vega10_complete_dependency_tables(hwmgr);
    899
    900	/* Parse pptable data read from VBIOS */
    901	vega10_set_private_data_based_on_pptable(hwmgr);
    902
    903	data->is_tlu_enabled = false;
    904
    905	hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
    906			VEGA10_MAX_HARDWARE_POWERLEVELS;
    907	hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
    908	hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
    909
    910	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	hwmgr->platform_descriptor.clockStep.engineClock = 500;
    913	hwmgr->platform_descriptor.clockStep.memoryClock = 500;
    914
    915	data->total_active_cus = adev->gfx.cu_info.number;
    916	if (!hwmgr->not_vf)
    917		return result;
    918
    919	/* Setup default Overdrive Fan control settings */
    920	data->odn_fan_table.target_fan_speed =
    921			hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
    922	data->odn_fan_table.target_temperature =
    923			hwmgr->thermal_controller.
    924			advanceFanControlParameters.ucTargetTemperature;
    925	data->odn_fan_table.min_performance_clock =
    926			hwmgr->thermal_controller.advanceFanControlParameters.
    927			ulMinFanSCLKAcousticLimit;
    928	data->odn_fan_table.min_fan_limit =
    929			hwmgr->thermal_controller.
    930			advanceFanControlParameters.usFanPWMMinLimit *
    931			hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
    932
    933	data->mem_channels = (RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0) &
    934			DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
    935			DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
    936	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
    943static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr)
    944{
    945	struct vega10_hwmgr *data = hwmgr->backend;
    946
    947	data->low_sclk_interrupt_threshold = 0;
    948
    949	return 0;
    950}
    951
    952static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
    953{
    954	struct vega10_hwmgr *data = hwmgr->backend;
    955	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
    956
    957	struct pp_atomfwctrl_voltage_table table;
    958	uint8_t i, j;
    959	uint32_t mask = 0;
    960	uint32_t tmp;
    961	int32_t ret = 0;
    962
    963	ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM,
    964						VOLTAGE_OBJ_GPIO_LUT, &table);
    965
    966	if (!ret) {
    967		tmp = table.mask_low;
    968		for (i = 0, j = 0; i < 32; i++) {
    969			if (tmp & 1) {
    970				mask |= (uint32_t)(i << (8 * j));
    971				if (++j >= 3)
    972					break;
    973			}
    974			tmp >>= 1;
    975		}
    976	}
    977
    978	pp_table->LedPin0 = (uint8_t)(mask & 0xff);
    979	pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff);
    980	pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff);
    981	return 0;
    982}
    983
    984static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr)
    985{
    986	if (!hwmgr->not_vf)
    987		return 0;
    988
    989	PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr),
    990			"Failed to init sclk threshold!",
    991			return -EINVAL);
    992
    993	PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr),
    994			"Failed to set up led dpm config!",
    995			return -EINVAL);
    996
    997	smum_send_msg_to_smc_with_parameter(hwmgr,
    998				PPSMC_MSG_NumOfDisplays,
    999				0,
   1000				NULL);
   1001
   1002	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 */
   1012static 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	bool found = false;
   1018	struct pp_atomfwctrl_voltage_table *table;
   1019
   1020	PP_ASSERT_WITH_CODE(vol_table,
   1021			"Voltage Table empty.", return -EINVAL);
   1022	table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table),
   1023			GFP_KERNEL);
   1024
   1025	if (!table)
   1026		return -ENOMEM;
   1027
   1028	table->mask_low = vol_table->mask_low;
   1029	table->phase_delay = vol_table->phase_delay;
   1030
   1031	for (i = 0; i < vol_table->count; i++) {
   1032		vvalue = vol_table->entries[i].value;
   1033		found = false;
   1034
   1035		for (j = 0; j < table->count; j++) {
   1036			if (vvalue == table->entries[j].value) {
   1037				found = true;
   1038				break;
   1039			}
   1040		}
   1041
   1042		if (!found) {
   1043			table->entries[table->count].value = vvalue;
   1044			table->entries[table->count].smio_low =
   1045					vol_table->entries[i].smio_low;
   1046			table->count++;
   1047		}
   1048	}
   1049
   1050	memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table));
   1051	kfree(table);
   1052
   1053	return 0;
   1054}
   1055
   1056static 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	PP_ASSERT_WITH_CODE(dep_table->count,
   1063			"Voltage Dependency Table empty.",
   1064			return -EINVAL);
   1065
   1066	vol_table->mask_low = 0;
   1067	vol_table->phase_delay = 0;
   1068	vol_table->count = dep_table->count;
   1069
   1070	for (i = 0; i < vol_table->count; i++) {
   1071		vol_table->entries[i].value = dep_table->entries[i].mvdd;
   1072		vol_table->entries[i].smio_low = 0;
   1073	}
   1074
   1075	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
   1083static 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	PP_ASSERT_WITH_CODE(dep_table->count,
   1090			"Voltage Dependency Table empty.",
   1091			return -EINVAL);
   1092
   1093	vol_table->mask_low = 0;
   1094	vol_table->phase_delay = 0;
   1095	vol_table->count = dep_table->count;
   1096
   1097	for (i = 0; i < dep_table->count; i++) {
   1098		vol_table->entries[i].value = dep_table->entries[i].vddci;
   1099		vol_table->entries[i].smio_low = 0;
   1100	}
   1101
   1102	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
   1109static 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	PP_ASSERT_WITH_CODE(dep_table->count,
   1116			"Voltage Dependency Table empty.",
   1117			return -EINVAL);
   1118
   1119	vol_table->mask_low = 0;
   1120	vol_table->phase_delay = 0;
   1121	vol_table->count = dep_table->count;
   1122
   1123	for (i = 0; i < vol_table->count; i++) {
   1124		vol_table->entries[i].value = dep_table->entries[i].vddc;
   1125		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 */
   1136static 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	if (vol_table->count <= max_vol_steps)
   1144		return;
   1145
   1146	diff = vol_table->count - max_vol_steps;
   1147
   1148	for (i = 0; i < max_vol_steps; i++)
   1149		vol_table->entries[i] = vol_table->entries[i + diff];
   1150
   1151	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 */
   1160static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr)
   1161{
   1162	struct vega10_hwmgr *data = hwmgr->backend;
   1163	struct phm_ppt_v2_information *table_info =
   1164			(struct phm_ppt_v2_information *)hwmgr->pptable;
   1165	int result;
   1166
   1167	if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
   1168			data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) {
   1169		result = vega10_get_mvdd_voltage_table(hwmgr,
   1170				table_info->vdd_dep_on_mclk,
   1171				&(data->mvdd_voltage_table));
   1172		PP_ASSERT_WITH_CODE(!result,
   1173				"Failed to retrieve MVDDC table!",
   1174				return result);
   1175	}
   1176
   1177	if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) {
   1178		result = vega10_get_vddci_voltage_table(hwmgr,
   1179				table_info->vdd_dep_on_mclk,
   1180				&(data->vddci_voltage_table));
   1181		PP_ASSERT_WITH_CODE(!result,
   1182				"Failed to retrieve VDDCI_MEM table!",
   1183				return result);
   1184	}
   1185
   1186	if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
   1187			data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) {
   1188		result = vega10_get_vdd_voltage_table(hwmgr,
   1189				table_info->vdd_dep_on_sclk,
   1190				&(data->vddc_voltage_table));
   1191		PP_ASSERT_WITH_CODE(!result,
   1192				"Failed to retrieve VDDCR_SOC table!",
   1193				return result);
   1194	}
   1195
   1196	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	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	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 */
   1222static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state)
   1223{
   1224	dpm_state->soft_min_level = 0xff;
   1225	dpm_state->soft_max_level = 0xff;
   1226	dpm_state->hard_min_level = 0xff;
   1227	dpm_state->hard_max_level = 0xff;
   1228}
   1229
   1230static 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	dpm_table->count = 0;
   1237
   1238	for (i = 0; i < dep_table->count; i++) {
   1239		if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
   1240				dep_table->entries[i].clk) {
   1241			dpm_table->dpm_levels[dpm_table->count].value =
   1242					dep_table->entries[i].clk;
   1243			dpm_table->dpm_levels[dpm_table->count].enabled = true;
   1244			dpm_table->count++;
   1245		}
   1246	}
   1247}
   1248static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
   1249{
   1250	struct vega10_hwmgr *data = hwmgr->backend;
   1251	struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
   1252	struct phm_ppt_v2_information *table_info =
   1253			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   1254	struct phm_ppt_v1_pcie_table *bios_pcie_table =
   1255			table_info->pcie_table;
   1256	uint32_t i;
   1257
   1258	PP_ASSERT_WITH_CODE(bios_pcie_table->count,
   1259			"Incorrect number of PCIE States from VBIOS!",
   1260			return -1);
   1261
   1262	for (i = 0; i < NUM_LINK_LEVELS; i++) {
   1263		if (data->registry_data.pcieSpeedOverride)
   1264			pcie_table->pcie_gen[i] =
   1265					data->registry_data.pcieSpeedOverride;
   1266		else
   1267			pcie_table->pcie_gen[i] =
   1268					bios_pcie_table->entries[i].gen_speed;
   1269
   1270		if (data->registry_data.pcieLaneOverride)
   1271			pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
   1272					data->registry_data.pcieLaneOverride);
   1273		else
   1274			pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
   1275							bios_pcie_table->entries[i].lane_width);
   1276		if (data->registry_data.pcieClockOverride)
   1277			pcie_table->lclk[i] =
   1278					data->registry_data.pcieClockOverride;
   1279		else
   1280			pcie_table->lclk[i] =
   1281					bios_pcie_table->entries[i].pcie_sclk;
   1282	}
   1283
   1284	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 */
   1297static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
   1298{
   1299	struct vega10_hwmgr *data = hwmgr->backend;
   1300	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	struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table =
   1306			table_info->vdd_dep_on_socclk;
   1307	struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table =
   1308			table_info->vdd_dep_on_sclk;
   1309	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
   1310			table_info->vdd_dep_on_mclk;
   1311	struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table =
   1312			table_info->mm_dep_table;
   1313	struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table =
   1314			table_info->vdd_dep_on_dcefclk;
   1315	struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table =
   1316			table_info->vdd_dep_on_pixclk;
   1317	struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table =
   1318			table_info->vdd_dep_on_dispclk;
   1319	struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table =
   1320			table_info->vdd_dep_on_phyclk;
   1321
   1322	PP_ASSERT_WITH_CODE(dep_soc_table,
   1323			"SOCCLK dependency table is missing. This table is mandatory",
   1324			return -EINVAL);
   1325	PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1,
   1326			"SOCCLK dependency table is empty. This table is mandatory",
   1327			return -EINVAL);
   1328
   1329	PP_ASSERT_WITH_CODE(dep_gfx_table,
   1330			"GFXCLK dependency table is missing. This table is mandatory",
   1331			return -EINVAL);
   1332	PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1,
   1333			"GFXCLK dependency table is empty. This table is mandatory",
   1334			return -EINVAL);
   1335
   1336	PP_ASSERT_WITH_CODE(dep_mclk_table,
   1337			"MCLK dependency table is missing. This table is mandatory",
   1338			return -EINVAL);
   1339	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	dpm_table = &(data->dpm_table.soc_table);
   1345	vega10_setup_default_single_dpm_table(hwmgr,
   1346			dpm_table,
   1347			dep_soc_table);
   1348
   1349	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1350
   1351	dpm_table = &(data->dpm_table.gfx_table);
   1352	vega10_setup_default_single_dpm_table(hwmgr,
   1353			dpm_table,
   1354			dep_gfx_table);
   1355	if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
   1356		hwmgr->platform_descriptor.overdriveLimit.engineClock =
   1357					dpm_table->dpm_levels[dpm_table->count-1].value;
   1358	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1359
   1360	/* Initialize Mclk DPM table based on allow Mclk values */
   1361	data->dpm_table.mem_table.count = 0;
   1362	dpm_table = &(data->dpm_table.mem_table);
   1363	vega10_setup_default_single_dpm_table(hwmgr,
   1364			dpm_table,
   1365			dep_mclk_table);
   1366	if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
   1367		hwmgr->platform_descriptor.overdriveLimit.memoryClock =
   1368					dpm_table->dpm_levels[dpm_table->count-1].value;
   1369	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1370
   1371	data->dpm_table.eclk_table.count = 0;
   1372	dpm_table = &(data->dpm_table.eclk_table);
   1373	for (i = 0; i < dep_mm_table->count; i++) {
   1374		if (i == 0 || dpm_table->dpm_levels
   1375				[dpm_table->count - 1].value <=
   1376						dep_mm_table->entries[i].eclk) {
   1377			dpm_table->dpm_levels[dpm_table->count].value =
   1378					dep_mm_table->entries[i].eclk;
   1379			dpm_table->dpm_levels[dpm_table->count].enabled =
   1380					(i == 0) ? true : false;
   1381			dpm_table->count++;
   1382		}
   1383	}
   1384	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1385
   1386	data->dpm_table.vclk_table.count = 0;
   1387	data->dpm_table.dclk_table.count = 0;
   1388	dpm_table = &(data->dpm_table.vclk_table);
   1389	for (i = 0; i < dep_mm_table->count; i++) {
   1390		if (i == 0 || dpm_table->dpm_levels
   1391				[dpm_table->count - 1].value <=
   1392						dep_mm_table->entries[i].vclk) {
   1393			dpm_table->dpm_levels[dpm_table->count].value =
   1394					dep_mm_table->entries[i].vclk;
   1395			dpm_table->dpm_levels[dpm_table->count].enabled =
   1396					(i == 0) ? true : false;
   1397			dpm_table->count++;
   1398		}
   1399	}
   1400	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1401
   1402	dpm_table = &(data->dpm_table.dclk_table);
   1403	for (i = 0; i < dep_mm_table->count; i++) {
   1404		if (i == 0 || dpm_table->dpm_levels
   1405				[dpm_table->count - 1].value <=
   1406						dep_mm_table->entries[i].dclk) {
   1407			dpm_table->dpm_levels[dpm_table->count].value =
   1408					dep_mm_table->entries[i].dclk;
   1409			dpm_table->dpm_levels[dpm_table->count].enabled =
   1410					(i == 0) ? true : false;
   1411			dpm_table->count++;
   1412		}
   1413	}
   1414	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1415
   1416	/* Assume there is no headless Vega10 for now */
   1417	dpm_table = &(data->dpm_table.dcef_table);
   1418	vega10_setup_default_single_dpm_table(hwmgr,
   1419			dpm_table,
   1420			dep_dcef_table);
   1421
   1422	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1423
   1424	dpm_table = &(data->dpm_table.pixel_table);
   1425	vega10_setup_default_single_dpm_table(hwmgr,
   1426			dpm_table,
   1427			dep_pix_table);
   1428
   1429	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1430
   1431	dpm_table = &(data->dpm_table.display_table);
   1432	vega10_setup_default_single_dpm_table(hwmgr,
   1433			dpm_table,
   1434			dep_disp_table);
   1435
   1436	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1437
   1438	dpm_table = &(data->dpm_table.phy_table);
   1439	vega10_setup_default_single_dpm_table(hwmgr,
   1440			dpm_table,
   1441			dep_phy_table);
   1442
   1443	vega10_init_dpm_state(&(dpm_table->dpm_state));
   1444
   1445	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	data->custom_profile_mode[0] = 0;
   1452	data->custom_profile_mode[1] = 0;
   1453	data->custom_profile_mode[2] = 0;
   1454	data->custom_profile_mode[3] = 0;
   1455
   1456	/* save a copy of the default DPM table */
   1457	memcpy(&(data->golden_dpm_table), &(data->dpm_table),
   1458			sizeof(struct vega10_dpm_table));
   1459
   1460	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 */
   1470static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
   1471{
   1472	struct vega10_hwmgr *data = hwmgr->backend;
   1473	struct phm_ppt_v2_information *table_info =
   1474			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   1475
   1476	data->smc_state_table.pp_table.UlvOffsetVid =
   1477			(uint8_t)table_info->us_ulv_voltage_offset;
   1478
   1479	data->smc_state_table.pp_table.UlvSmnclkDid =
   1480			(uint8_t)(table_info->us_ulv_smnclk_did);
   1481	data->smc_state_table.pp_table.UlvMp1clkDid =
   1482			(uint8_t)(table_info->us_ulv_mp1clk_did);
   1483	data->smc_state_table.pp_table.UlvGfxclkBypass =
   1484			(uint8_t)(table_info->us_ulv_gfxclk_bypass);
   1485	data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 =
   1486			(uint8_t)(data->vddc_voltage_table.psi0_enable);
   1487	data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 =
   1488			(uint8_t)(data->vddc_voltage_table.psi1_enable);
   1489
   1490	return 0;
   1491}
   1492
   1493static 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	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	*curr_lclk_did = dividers.ulDid;
   1506
   1507	return 0;
   1508}
   1509
   1510static int vega10_override_pcie_parameters(struct pp_hwmgr *hwmgr)
   1511{
   1512	struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
   1513	struct vega10_hwmgr *data =
   1514			(struct vega10_hwmgr *)(hwmgr->backend);
   1515	uint32_t pcie_gen = 0, pcie_width = 0;
   1516	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1517	int i;
   1518
   1519	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
   1520		pcie_gen = 3;
   1521	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
   1522		pcie_gen = 2;
   1523	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	if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
   1529		pcie_width = 6;
   1530	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
   1531		pcie_width = 5;
   1532	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
   1533		pcie_width = 4;
   1534	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
   1535		pcie_width = 3;
   1536	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
   1537		pcie_width = 2;
   1538	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
   1539		pcie_width = 1;
   1540
   1541	for (i = 0; i < NUM_LINK_LEVELS; i++) {
   1542		if (pp_table->PcieGenSpeed[i] > pcie_gen)
   1543			pp_table->PcieGenSpeed[i] = pcie_gen;
   1544
   1545		if (pp_table->PcieLaneCount[i] > pcie_width)
   1546			pp_table->PcieLaneCount[i] = pcie_width;
   1547	}
   1548
   1549	if (data->registry_data.pcie_dpm_key_disabled) {
   1550		for (i = 0; i < NUM_LINK_LEVELS; i++) {
   1551			pp_table->PcieGenSpeed[i] = pcie_gen;
   1552			pp_table->PcieLaneCount[i] = pcie_width;
   1553		}
   1554	}
   1555
   1556	return 0;
   1557}
   1558
   1559static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
   1560{
   1561	int result = -1;
   1562	struct vega10_hwmgr *data = hwmgr->backend;
   1563	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1564	struct vega10_pcie_table *pcie_table =
   1565			&(data->dpm_table.pcie_table);
   1566	uint32_t i, j;
   1567
   1568	for (i = 0; i < pcie_table->count; i++) {
   1569		pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i];
   1570		pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i];
   1571
   1572		result = vega10_populate_single_lclk_level(hwmgr,
   1573				pcie_table->lclk[i], &(pp_table->LclkDid[i]));
   1574		if (result) {
   1575			pr_info("Populate LClock Level %d Failed!\n", i);
   1576			return result;
   1577		}
   1578	}
   1579
   1580	j = i - 1;
   1581	while (i < NUM_LINK_LEVELS) {
   1582		pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j];
   1583		pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j];
   1584
   1585		result = vega10_populate_single_lclk_level(hwmgr,
   1586				pcie_table->lclk[j], &(pp_table->LclkDid[i]));
   1587		if (result) {
   1588			pr_info("Populate LClock Level %d Failed!\n", i);
   1589			return result;
   1590		}
   1591		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 */
   1606static 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	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	struct vega10_hwmgr *data = hwmgr->backend;
   1614	struct pp_atomfwctrl_clock_dividers_soc15 dividers;
   1615	uint32_t gfx_max_clock =
   1616			hwmgr->platform_descriptor.overdriveLimit.engineClock;
   1617	uint32_t i = 0;
   1618
   1619	if (hwmgr->od_enabled)
   1620		dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
   1621						&(data->odn_dpm_table.vdd_dep_on_sclk);
   1622	else
   1623		dep_on_sclk = table_info->vdd_dep_on_sclk;
   1624
   1625	PP_ASSERT_WITH_CODE(dep_on_sclk,
   1626			"Invalid SOC_VDD-GFX_CLK Dependency Table!",
   1627			return -EINVAL);
   1628
   1629	if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK)
   1630		gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock;
   1631	else {
   1632		for (i = 0; i < dep_on_sclk->count; i++) {
   1633			if (dep_on_sclk->entries[i].clk == gfx_clock)
   1634				break;
   1635		}
   1636		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	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	current_gfxclk_level->FbMult =
   1649			cpu_to_le32(dividers.ulPll_fb_mult);
   1650	/* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
   1651	current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
   1652	current_gfxclk_level->SsFbMult =
   1653			cpu_to_le32(dividers.ulPll_ss_fbsmult);
   1654	current_gfxclk_level->SsSlewFrac =
   1655			cpu_to_le16(dividers.usPll_ss_slew_frac);
   1656	current_gfxclk_level->Did = (uint8_t)(dividers.ulDid);
   1657
   1658	*acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */
   1659
   1660	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 */
   1673static 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	struct vega10_hwmgr *data = hwmgr->backend;
   1678	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	if (hwmgr->od_enabled) {
   1685		dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *)
   1686						&data->odn_dpm_table.vdd_dep_on_socclk;
   1687		for (i = 0; i < dep_on_soc->count; i++) {
   1688			if (dep_on_soc->entries[i].clk >= soc_clock)
   1689				break;
   1690		}
   1691	} else {
   1692		dep_on_soc = table_info->vdd_dep_on_socclk;
   1693		for (i = 0; i < dep_on_soc->count; i++) {
   1694			if (dep_on_soc->entries[i].clk == soc_clock)
   1695				break;
   1696		}
   1697	}
   1698
   1699	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	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	*current_soc_did = (uint8_t)dividers.ulDid;
   1710	*current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
   1711	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 */
   1720static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
   1721{
   1722	struct vega10_hwmgr *data = hwmgr->backend;
   1723	struct phm_ppt_v2_information *table_info =
   1724			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   1725	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1726	struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
   1727	int result = 0;
   1728	uint32_t i, j;
   1729
   1730	for (i = 0; i < dpm_table->count; i++) {
   1731		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		if (result)
   1736			return result;
   1737	}
   1738
   1739	j = i - 1;
   1740	while (i < NUM_GFXCLK_DPM_LEVELS) {
   1741		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		if (result)
   1746			return result;
   1747		i++;
   1748	}
   1749
   1750	pp_table->GfxclkSlewRate =
   1751			cpu_to_le16(table_info->us_gfxclk_slew_rate);
   1752
   1753	dpm_table = &(data->dpm_table.soc_table);
   1754	for (i = 0; i < dpm_table->count; i++) {
   1755		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		if (result)
   1760			return result;
   1761	}
   1762
   1763	j = i - 1;
   1764	while (i < NUM_SOCCLK_DPM_LEVELS) {
   1765		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		if (result)
   1770			return result;
   1771		i++;
   1772	}
   1773
   1774	return result;
   1775}
   1776
   1777static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr)
   1778{
   1779	struct vega10_hwmgr *data = hwmgr->backend;
   1780	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1781	struct phm_ppt_v2_information *table_info = hwmgr->pptable;
   1782	struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
   1783
   1784	uint8_t soc_vid = 0;
   1785	uint32_t i, max_vddc_level;
   1786
   1787	if (hwmgr->od_enabled)
   1788		vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table;
   1789	else
   1790		vddc_lookup_table = table_info->vddc_lookup_table;
   1791
   1792	max_vddc_level = vddc_lookup_table->count;
   1793	for (i = 0; i < max_vddc_level; i++) {
   1794		soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd);
   1795		pp_table->SocVid[i] = soc_vid;
   1796	}
   1797	while (i < MAX_REGULAR_DPM_NUMBER) {
   1798		pp_table->SocVid[i] = soc_vid;
   1799		i++;
   1800	}
   1801}
   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 */
   1810static 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	struct vega10_hwmgr *data = hwmgr->backend;
   1815	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	uint32_t mem_max_clock =
   1820			hwmgr->platform_descriptor.overdriveLimit.memoryClock;
   1821	uint32_t i = 0;
   1822
   1823	if (hwmgr->od_enabled)
   1824		dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
   1825					&data->odn_dpm_table.vdd_dep_on_mclk;
   1826	else
   1827		dep_on_mclk = table_info->vdd_dep_on_mclk;
   1828
   1829	PP_ASSERT_WITH_CODE(dep_on_mclk,
   1830			"Invalid SOC_VDD-UCLK Dependency Table!",
   1831			return -EINVAL);
   1832
   1833	if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
   1834		mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock;
   1835	} else {
   1836		for (i = 0; i < dep_on_mclk->count; i++) {
   1837			if (dep_on_mclk->entries[i].clk == mem_clock)
   1838				break;
   1839		}
   1840		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	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	*current_mem_vid =
   1851			(uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd));
   1852	*current_mem_soc_vind =
   1853			(uint8_t)(dep_on_mclk->entries[i].vddInd);
   1854	current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult);
   1855	current_memclk_level->Did = (uint8_t)(dividers.ulDid);
   1856
   1857	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 */
   1871static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
   1872{
   1873	struct vega10_hwmgr *data = hwmgr->backend;
   1874	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1875	struct vega10_single_dpm_table *dpm_table =
   1876			&(data->dpm_table.mem_table);
   1877	int result = 0;
   1878	uint32_t i, j;
   1879
   1880	for (i = 0; i < dpm_table->count; i++) {
   1881		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		if (result)
   1887			return result;
   1888	}
   1889
   1890	j = i - 1;
   1891	while (i < NUM_UCLK_DPM_LEVELS) {
   1892		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		if (result)
   1898			return result;
   1899		i++;
   1900	}
   1901
   1902	pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels);
   1903	pp_table->MemoryChannelWidth =
   1904			(uint16_t)(HBM_MEMORY_CHANNEL_WIDTH *
   1905					channel_number[data->mem_channels]);
   1906
   1907	pp_table->LowestUclkReservedForUlv =
   1908			(uint8_t)(data->lowest_uclk_reserved_for_ulv);
   1909
   1910	return result;
   1911}
   1912
   1913static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr,
   1914		DSPCLK_e disp_clock)
   1915{
   1916	struct vega10_hwmgr *data = hwmgr->backend;
   1917	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   1918	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	uint16_t clk = 0, vddc = 0;
   1924	uint8_t vid = 0;
   1925
   1926	switch (disp_clock) {
   1927	case DSPCLK_DCEFCLK:
   1928		dep_table = table_info->vdd_dep_on_dcefclk;
   1929		break;
   1930	case DSPCLK_DISPCLK:
   1931		dep_table = table_info->vdd_dep_on_dispclk;
   1932		break;
   1933	case DSPCLK_PIXCLK:
   1934		dep_table = table_info->vdd_dep_on_pixclk;
   1935		break;
   1936	case DSPCLK_PHYCLK:
   1937		dep_table = table_info->vdd_dep_on_phyclk;
   1938		break;
   1939	default:
   1940		return -1;
   1941	}
   1942
   1943	PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS,
   1944			"Number Of Entries Exceeded maximum!",
   1945			return -1);
   1946
   1947	for (i = 0; i < dep_table->count; i++) {
   1948		clk = (uint16_t)(dep_table->entries[i].clk / 100);
   1949		vddc = table_info->vddc_lookup_table->
   1950				entries[dep_table->entries[i].vddInd].us_vdd;
   1951		vid = (uint8_t)convert_to_vid(vddc);
   1952		pp_table->DisplayClockTable[disp_clock][i].Freq =
   1953				cpu_to_le16(clk);
   1954		pp_table->DisplayClockTable[disp_clock][i].Vid =
   1955				cpu_to_le16(vid);
   1956	}
   1957
   1958	while (i < NUM_DSPCLK_LEVELS) {
   1959		pp_table->DisplayClockTable[disp_clock][i].Freq =
   1960				cpu_to_le16(clk);
   1961		pp_table->DisplayClockTable[disp_clock][i].Vid =
   1962				cpu_to_le16(vid);
   1963		i++;
   1964	}
   1965
   1966	return 0;
   1967}
   1968
   1969static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr)
   1970{
   1971	uint32_t i;
   1972
   1973	for (i = 0; i < DSPCLK_COUNT; i++) {
   1974		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
   1982static 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	struct phm_ppt_v2_information *table_info =
   1987			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   1988	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	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	*current_eclk_did = (uint8_t)dividers.ulDid;
   2000
   2001	for (i = 0; i < dep_table->count; i++) {
   2002		if (dep_table->entries[i].eclk == eclock)
   2003			*current_soc_vol = dep_table->entries[i].vddcInd;
   2004	}
   2005
   2006	return 0;
   2007}
   2008
   2009static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr)
   2010{
   2011	struct vega10_hwmgr *data = hwmgr->backend;
   2012	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   2013	struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table);
   2014	int result = -EINVAL;
   2015	uint32_t i, j;
   2016
   2017	for (i = 0; i < dpm_table->count; i++) {
   2018		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		if (result)
   2023			return result;
   2024	}
   2025
   2026	j = i - 1;
   2027	while (i < NUM_VCE_DPM_LEVELS) {
   2028		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		if (result)
   2033			return result;
   2034		i++;
   2035	}
   2036
   2037	return result;
   2038}
   2039
   2040static 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	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	*current_vclk_did = (uint8_t)dividers.ulDid;
   2052
   2053	return 0;
   2054}
   2055
   2056static 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	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	*current_dclk_did = (uint8_t)dividers.ulDid;
   2068
   2069	return 0;
   2070}
   2071
   2072static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr)
   2073{
   2074	struct vega10_hwmgr *data = hwmgr->backend;
   2075	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   2076	struct vega10_single_dpm_table *vclk_dpm_table =
   2077			&(data->dpm_table.vclk_table);
   2078	struct vega10_single_dpm_table *dclk_dpm_table =
   2079			&(data->dpm_table.dclk_table);
   2080	struct phm_ppt_v2_information *table_info =
   2081			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   2082	struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
   2083			table_info->mm_dep_table;
   2084	int result = -EINVAL;
   2085	uint32_t i, j;
   2086
   2087	for (i = 0; i < vclk_dpm_table->count; i++) {
   2088		result = vega10_populate_single_vclock_level(hwmgr,
   2089				vclk_dpm_table->dpm_levels[i].value,
   2090				&(pp_table->VclkDid[i]));
   2091		if (result)
   2092			return result;
   2093	}
   2094
   2095	j = i - 1;
   2096	while (i < NUM_UVD_DPM_LEVELS) {
   2097		result = vega10_populate_single_vclock_level(hwmgr,
   2098				vclk_dpm_table->dpm_levels[j].value,
   2099				&(pp_table->VclkDid[i]));
   2100		if (result)
   2101			return result;
   2102		i++;
   2103	}
   2104
   2105	for (i = 0; i < dclk_dpm_table->count; i++) {
   2106		result = vega10_populate_single_dclock_level(hwmgr,
   2107				dclk_dpm_table->dpm_levels[i].value,
   2108				&(pp_table->DclkDid[i]));
   2109		if (result)
   2110			return result;
   2111	}
   2112
   2113	j = i - 1;
   2114	while (i < NUM_UVD_DPM_LEVELS) {
   2115		result = vega10_populate_single_dclock_level(hwmgr,
   2116				dclk_dpm_table->dpm_levels[j].value,
   2117				&(pp_table->DclkDid[i]));
   2118		if (result)
   2119			return result;
   2120		i++;
   2121	}
   2122
   2123	for (i = 0; i < dep_table->count; i++) {
   2124		if (dep_table->entries[i].vclk ==
   2125				vclk_dpm_table->dpm_levels[i].value &&
   2126			dep_table->entries[i].dclk ==
   2127				dclk_dpm_table->dpm_levels[i].value)
   2128			pp_table->UvdDpmVoltageIndex[i] =
   2129					dep_table->entries[i].vddcInd;
   2130		else
   2131			return -1;
   2132	}
   2133
   2134	j = i - 1;
   2135	while (i < NUM_UVD_DPM_LEVELS) {
   2136		pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd;
   2137		i++;
   2138	}
   2139
   2140	return 0;
   2141}
   2142
   2143static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
   2144{
   2145	struct vega10_hwmgr *data = hwmgr->backend;
   2146	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   2147	struct phm_ppt_v2_information *table_info =
   2148			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   2149	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   2150			table_info->vdd_dep_on_sclk;
   2151	uint32_t i;
   2152
   2153	for (i = 0; i < dep_table->count; i++) {
   2154		pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
   2155		pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
   2156				* VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
   2157	}
   2158
   2159	return 0;
   2160}
   2161
   2162static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
   2163{
   2164	struct vega10_hwmgr *data = hwmgr->backend;
   2165	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   2166	struct phm_ppt_v2_information *table_info =
   2167			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   2168	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   2169			table_info->vdd_dep_on_sclk;
   2170	struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
   2171	int result = 0;
   2172	uint32_t i;
   2173
   2174	pp_table->MinVoltageVid = (uint8_t)0xff;
   2175	pp_table->MaxVoltageVid = (uint8_t)0;
   2176
   2177	if (data->smu_features[GNLD_AVFS].supported) {
   2178		result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
   2179		if (!result) {
   2180			pp_table->MinVoltageVid = (uint8_t)
   2181					convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
   2182			pp_table->MaxVoltageVid = (uint8_t)
   2183					convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
   2184
   2185			pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
   2186			pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
   2187			pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
   2188			pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
   2189			pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
   2190			pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
   2191			pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
   2192
   2193			pp_table->BtcGbVdroopTableCksOff.a0 =
   2194					cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
   2195			pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
   2196			pp_table->BtcGbVdroopTableCksOff.a1 =
   2197					cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
   2198			pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
   2199			pp_table->BtcGbVdroopTableCksOff.a2 =
   2200					cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
   2201			pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
   2202
   2203			pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
   2204			pp_table->BtcGbVdroopTableCksOn.a0 =
   2205					cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
   2206			pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
   2207			pp_table->BtcGbVdroopTableCksOn.a1 =
   2208					cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
   2209			pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
   2210			pp_table->BtcGbVdroopTableCksOn.a2 =
   2211					cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
   2212			pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
   2213
   2214			pp_table->AvfsGbCksOn.m1 =
   2215					cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
   2216			pp_table->AvfsGbCksOn.m2 =
   2217					cpu_to_le32(avfs_params.ulGbFuseTableCksonM2);
   2218			pp_table->AvfsGbCksOn.b =
   2219					cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
   2220			pp_table->AvfsGbCksOn.m1_shift = 24;
   2221			pp_table->AvfsGbCksOn.m2_shift = 12;
   2222			pp_table->AvfsGbCksOn.b_shift = 0;
   2223
   2224			pp_table->OverrideAvfsGbCksOn =
   2225					avfs_params.ucEnableGbFuseTableCkson;
   2226			pp_table->AvfsGbCksOff.m1 =
   2227					cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
   2228			pp_table->AvfsGbCksOff.m2 =
   2229					cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2);
   2230			pp_table->AvfsGbCksOff.b =
   2231					cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
   2232			pp_table->AvfsGbCksOff.m1_shift = 24;
   2233			pp_table->AvfsGbCksOff.m2_shift = 12;
   2234			pp_table->AvfsGbCksOff.b_shift = 0;
   2235
   2236			for (i = 0; i < dep_table->count; i++)
   2237				pp_table->StaticVoltageOffsetVid[i] =
   2238						convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset));
   2239
   2240			if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2241					data->disp_clk_quad_eqn_a) &&
   2242				(PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2243					data->disp_clk_quad_eqn_b)) {
   2244				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
   2245						(int32_t)data->disp_clk_quad_eqn_a;
   2246				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
   2247						(int32_t)data->disp_clk_quad_eqn_b;
   2248				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
   2249						(int32_t)data->disp_clk_quad_eqn_c;
   2250			} else {
   2251				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
   2252						(int32_t)avfs_params.ulDispclk2GfxclkM1;
   2253				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
   2254						(int32_t)avfs_params.ulDispclk2GfxclkM2;
   2255				pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
   2256						(int32_t)avfs_params.ulDispclk2GfxclkB;
   2257			}
   2258
   2259			pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
   2260			pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
   2261			pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
   2262
   2263			if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2264					data->dcef_clk_quad_eqn_a) &&
   2265				(PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2266					data->dcef_clk_quad_eqn_b)) {
   2267				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
   2268						(int32_t)data->dcef_clk_quad_eqn_a;
   2269				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
   2270						(int32_t)data->dcef_clk_quad_eqn_b;
   2271				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
   2272						(int32_t)data->dcef_clk_quad_eqn_c;
   2273			} else {
   2274				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
   2275						(int32_t)avfs_params.ulDcefclk2GfxclkM1;
   2276				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
   2277						(int32_t)avfs_params.ulDcefclk2GfxclkM2;
   2278				pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
   2279						(int32_t)avfs_params.ulDcefclk2GfxclkB;
   2280			}
   2281
   2282			pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
   2283			pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
   2284			pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
   2285
   2286			if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2287					data->pixel_clk_quad_eqn_a) &&
   2288				(PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2289					data->pixel_clk_quad_eqn_b)) {
   2290				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
   2291						(int32_t)data->pixel_clk_quad_eqn_a;
   2292				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
   2293						(int32_t)data->pixel_clk_quad_eqn_b;
   2294				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
   2295						(int32_t)data->pixel_clk_quad_eqn_c;
   2296			} else {
   2297				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
   2298						(int32_t)avfs_params.ulPixelclk2GfxclkM1;
   2299				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
   2300						(int32_t)avfs_params.ulPixelclk2GfxclkM2;
   2301				pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
   2302						(int32_t)avfs_params.ulPixelclk2GfxclkB;
   2303			}
   2304
   2305			pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
   2306			pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
   2307			pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
   2308			if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2309					data->phy_clk_quad_eqn_a) &&
   2310				(PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
   2311					data->phy_clk_quad_eqn_b)) {
   2312				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
   2313						(int32_t)data->phy_clk_quad_eqn_a;
   2314				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
   2315						(int32_t)data->phy_clk_quad_eqn_b;
   2316				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
   2317						(int32_t)data->phy_clk_quad_eqn_c;
   2318			} else {
   2319				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
   2320						(int32_t)avfs_params.ulPhyclk2GfxclkM1;
   2321				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
   2322						(int32_t)avfs_params.ulPhyclk2GfxclkM2;
   2323				pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
   2324						(int32_t)avfs_params.ulPhyclk2GfxclkB;
   2325			}
   2326
   2327			pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
   2328			pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
   2329			pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
   2330
   2331			pp_table->AcgBtcGbVdroopTable.a0       = avfs_params.ulAcgGbVdroopTableA0;
   2332			pp_table->AcgBtcGbVdroopTable.a0_shift = 20;
   2333			pp_table->AcgBtcGbVdroopTable.a1       = avfs_params.ulAcgGbVdroopTableA1;
   2334			pp_table->AcgBtcGbVdroopTable.a1_shift = 20;
   2335			pp_table->AcgBtcGbVdroopTable.a2       = avfs_params.ulAcgGbVdroopTableA2;
   2336			pp_table->AcgBtcGbVdroopTable.a2_shift = 20;
   2337
   2338			pp_table->AcgAvfsGb.m1                   = avfs_params.ulAcgGbFuseTableM1;
   2339			pp_table->AcgAvfsGb.m2                   = avfs_params.ulAcgGbFuseTableM2;
   2340			pp_table->AcgAvfsGb.b                    = avfs_params.ulAcgGbFuseTableB;
   2341			pp_table->AcgAvfsGb.m1_shift             = 24;
   2342			pp_table->AcgAvfsGb.m2_shift             = 12;
   2343			pp_table->AcgAvfsGb.b_shift              = 0;
   2344
   2345		} else {
   2346			data->smu_features[GNLD_AVFS].supported = false;
   2347		}
   2348	}
   2349
   2350	return 0;
   2351}
   2352
   2353static int vega10_acg_enable(struct pp_hwmgr *hwmgr)
   2354{
   2355	struct vega10_hwmgr *data = hwmgr->backend;
   2356	uint32_t agc_btc_response;
   2357
   2358	if (data->smu_features[GNLD_ACG].supported) {
   2359		if (0 == vega10_enable_smc_features(hwmgr, true,
   2360					data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap))
   2361			data->smu_features[GNLD_DPM_PREFETCHER].enabled = true;
   2362
   2363		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg, NULL);
   2364
   2365		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &agc_btc_response);
   2366
   2367		if (1 == agc_btc_response) {
   2368			if (1 == data->acg_loop_state)
   2369				smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop, NULL);
   2370			else if (2 == data->acg_loop_state)
   2371				smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop, NULL);
   2372			if (0 == vega10_enable_smc_features(hwmgr, true,
   2373				data->smu_features[GNLD_ACG].smu_feature_bitmap))
   2374					data->smu_features[GNLD_ACG].enabled = true;
   2375		} else {
   2376			pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n");
   2377			data->smu_features[GNLD_ACG].enabled = false;
   2378		}
   2379	}
   2380
   2381	return 0;
   2382}
   2383
   2384static int vega10_acg_disable(struct pp_hwmgr *hwmgr)
   2385{
   2386	struct vega10_hwmgr *data = hwmgr->backend;
   2387
   2388	if (data->smu_features[GNLD_ACG].supported &&
   2389	    data->smu_features[GNLD_ACG].enabled)
   2390		if (!vega10_enable_smc_features(hwmgr, false,
   2391			data->smu_features[GNLD_ACG].smu_feature_bitmap))
   2392			data->smu_features[GNLD_ACG].enabled = false;
   2393
   2394	return 0;
   2395}
   2396
   2397static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr)
   2398{
   2399	struct vega10_hwmgr *data = hwmgr->backend;
   2400	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   2401	struct pp_atomfwctrl_gpio_parameters gpio_params = {0};
   2402	int result;
   2403
   2404	result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params);
   2405	if (!result) {
   2406		if (PP_CAP(PHM_PlatformCaps_RegulatorHot) &&
   2407		    data->registry_data.regulator_hot_gpio_support) {
   2408			pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio;
   2409			pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity;
   2410			pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio;
   2411			pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity;
   2412		} else {
   2413			pp_table->VR0HotGpio = 0;
   2414			pp_table->VR0HotPolarity = 0;
   2415			pp_table->VR1HotGpio = 0;
   2416			pp_table->VR1HotPolarity = 0;
   2417		}
   2418
   2419		if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) &&
   2420		    data->registry_data.ac_dc_switch_gpio_support) {
   2421			pp_table->AcDcGpio = gpio_params.ucAcDcGpio;
   2422			pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity;
   2423		} else {
   2424			pp_table->AcDcGpio = 0;
   2425			pp_table->AcDcPolarity = 0;
   2426		}
   2427	}
   2428
   2429	return result;
   2430}
   2431
   2432static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
   2433{
   2434	struct vega10_hwmgr *data = hwmgr->backend;
   2435
   2436	if (data->smu_features[GNLD_AVFS].supported) {
   2437		/* Already enabled or disabled */
   2438		if (!(enable ^ data->smu_features[GNLD_AVFS].enabled))
   2439			return 0;
   2440
   2441		if (enable) {
   2442			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			data->smu_features[GNLD_AVFS].enabled = true;
   2448		} else {
   2449			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			data->smu_features[GNLD_AVFS].enabled = false;
   2455		}
   2456	}
   2457
   2458	return 0;
   2459}
   2460
   2461static int vega10_update_avfs(struct pp_hwmgr *hwmgr)
   2462{
   2463	struct vega10_hwmgr *data = hwmgr->backend;
   2464
   2465	if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
   2466		vega10_avfs_enable(hwmgr, false);
   2467	} else if (data->need_update_dpm_table) {
   2468		vega10_avfs_enable(hwmgr, false);
   2469		vega10_avfs_enable(hwmgr, true);
   2470	} else {
   2471		vega10_avfs_enable(hwmgr, true);
   2472	}
   2473
   2474	return 0;
   2475}
   2476
   2477static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
   2478{
   2479	int result = 0;
   2480
   2481	uint64_t serial_number = 0;
   2482	uint32_t top32, bottom32;
   2483	struct phm_fuses_default fuse;
   2484
   2485	struct vega10_hwmgr *data = hwmgr->backend;
   2486	AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table);
   2487
   2488	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32);
   2489
   2490	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32);
   2491
   2492	serial_number = ((uint64_t)bottom32 << 32) | top32;
   2493
   2494	if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) {
   2495		avfs_fuse_table->VFT0_b  = fuse.VFT0_b;
   2496		avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1;
   2497		avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2;
   2498		avfs_fuse_table->VFT1_b  = fuse.VFT1_b;
   2499		avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1;
   2500		avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2;
   2501		avfs_fuse_table->VFT2_b  = fuse.VFT2_b;
   2502		avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1;
   2503		avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2;
   2504		result = smum_smc_table_manager(hwmgr,  (uint8_t *)avfs_fuse_table,
   2505						AVFSFUSETABLE, false);
   2506		PP_ASSERT_WITH_CODE(!result,
   2507			"Failed to upload FuseOVerride!",
   2508			);
   2509	}
   2510
   2511	return result;
   2512}
   2513
   2514static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
   2515{
   2516	struct vega10_hwmgr *data = hwmgr->backend;
   2517	struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
   2518	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	dep_table = table_info->vdd_dep_on_mclk;
   2524	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk);
   2525
   2526	for (i = 0; i < dep_table->count; i++) {
   2527		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
   2528			data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
   2529			return;
   2530		}
   2531	}
   2532
   2533	dep_table = table_info->vdd_dep_on_sclk;
   2534	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk);
   2535	for (i = 0; i < dep_table->count; i++) {
   2536		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
   2537			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 */
   2549static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
   2550{
   2551	int result;
   2552	struct vega10_hwmgr *data = hwmgr->backend;
   2553	struct phm_ppt_v2_information *table_info =
   2554			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   2555	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	struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
   2559
   2560	result = vega10_setup_default_dpm_tables(hwmgr);
   2561	PP_ASSERT_WITH_CODE(!result,
   2562			"Failed to setup default DPM tables!",
   2563			return result);
   2564
   2565	if (!hwmgr->not_vf)
   2566		return 0;
   2567
   2568	/* initialize ODN table */
   2569	if (hwmgr->od_enabled) {
   2570		if (odn_table->max_vddc) {
   2571			data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
   2572			vega10_check_dpm_table_updated(hwmgr);
   2573		} else {
   2574			vega10_odn_initial_default_setting(hwmgr);
   2575		}
   2576	}
   2577
   2578	pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
   2579			VOLTAGE_OBJ_SVID2,  &voltage_table);
   2580	pp_table->MaxVidStep = voltage_table.max_vid_step;
   2581
   2582	pp_table->GfxDpmVoltageMode =
   2583			(uint8_t)(table_info->uc_gfx_dpm_voltage_mode);
   2584	pp_table->SocDpmVoltageMode =
   2585			(uint8_t)(table_info->uc_soc_dpm_voltage_mode);
   2586	pp_table->UclkDpmVoltageMode =
   2587			(uint8_t)(table_info->uc_uclk_dpm_voltage_mode);
   2588	pp_table->UvdDpmVoltageMode =
   2589			(uint8_t)(table_info->uc_uvd_dpm_voltage_mode);
   2590	pp_table->VceDpmVoltageMode =
   2591			(uint8_t)(table_info->uc_vce_dpm_voltage_mode);
   2592	pp_table->Mp0DpmVoltageMode =
   2593			(uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
   2594
   2595	pp_table->DisplayDpmVoltageMode =
   2596			(uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
   2597
   2598	data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable;
   2599	data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable;
   2600
   2601	if (data->registry_data.ulv_support &&
   2602			table_info->us_ulv_voltage_offset) {
   2603		result = vega10_populate_ulv_state(hwmgr);
   2604		PP_ASSERT_WITH_CODE(!result,
   2605				"Failed to initialize ULV state!",
   2606				return result);
   2607	}
   2608
   2609	result = vega10_populate_smc_link_levels(hwmgr);
   2610	PP_ASSERT_WITH_CODE(!result,
   2611			"Failed to initialize Link Level!",
   2612			return result);
   2613
   2614	result = vega10_override_pcie_parameters(hwmgr);
   2615	PP_ASSERT_WITH_CODE(!result,
   2616			"Failed to override pcie parameters!",
   2617			return result);
   2618
   2619	result = vega10_populate_all_graphic_levels(hwmgr);
   2620	PP_ASSERT_WITH_CODE(!result,
   2621			"Failed to initialize Graphics Level!",
   2622			return result);
   2623
   2624	result = vega10_populate_all_memory_levels(hwmgr);
   2625	PP_ASSERT_WITH_CODE(!result,
   2626			"Failed to initialize Memory Level!",
   2627			return result);
   2628
   2629	vega10_populate_vddc_soc_levels(hwmgr);
   2630
   2631	result = vega10_populate_all_display_clock_levels(hwmgr);
   2632	PP_ASSERT_WITH_CODE(!result,
   2633			"Failed to initialize Display Level!",
   2634			return result);
   2635
   2636	result = vega10_populate_smc_vce_levels(hwmgr);
   2637	PP_ASSERT_WITH_CODE(!result,
   2638			"Failed to initialize VCE Level!",
   2639			return result);
   2640
   2641	result = vega10_populate_smc_uvd_levels(hwmgr);
   2642	PP_ASSERT_WITH_CODE(!result,
   2643			"Failed to initialize UVD Level!",
   2644			return result);
   2645
   2646	if (data->registry_data.clock_stretcher_support) {
   2647		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	result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
   2654	if (!result) {
   2655		data->vbios_boot_state.vddc     = boot_up_values.usVddc;
   2656		data->vbios_boot_state.vddci    = boot_up_values.usVddci;
   2657		data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
   2658		data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
   2659		data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
   2660		pp_atomfwctrl_get_clk_information_by_clkid(hwmgr,
   2661				SMU9_SYSPLL0_SOCCLK_ID, 0, &boot_up_values.ulSocClk);
   2662
   2663		pp_atomfwctrl_get_clk_information_by_clkid(hwmgr,
   2664				SMU9_SYSPLL0_DCEFCLK_ID, 0, &boot_up_values.ulDCEFClk);
   2665
   2666		data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
   2667		data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
   2668		if (0 != boot_up_values.usVddc) {
   2669			smum_send_msg_to_smc_with_parameter(hwmgr,
   2670						PPSMC_MSG_SetFloorSocVoltage,
   2671						(boot_up_values.usVddc * 4),
   2672						NULL);
   2673			data->vbios_boot_state.bsoc_vddc_lock = true;
   2674		} else {
   2675			data->vbios_boot_state.bsoc_vddc_lock = false;
   2676		}
   2677		smum_send_msg_to_smc_with_parameter(hwmgr,
   2678				PPSMC_MSG_SetMinDeepSleepDcefclk,
   2679			(uint32_t)(data->vbios_boot_state.dcef_clock / 100),
   2680				NULL);
   2681	}
   2682
   2683	result = vega10_populate_avfs_parameters(hwmgr);
   2684	PP_ASSERT_WITH_CODE(!result,
   2685			"Failed to initialize AVFS Parameters!",
   2686			return result);
   2687
   2688	result = vega10_populate_gpio_parameters(hwmgr);
   2689	PP_ASSERT_WITH_CODE(!result,
   2690			"Failed to initialize GPIO Parameters!",
   2691			return result);
   2692
   2693	pp_table->GfxclkAverageAlpha = (uint8_t)
   2694			(data->gfxclk_average_alpha);
   2695	pp_table->SocclkAverageAlpha = (uint8_t)
   2696			(data->socclk_average_alpha);
   2697	pp_table->UclkAverageAlpha = (uint8_t)
   2698			(data->uclk_average_alpha);
   2699	pp_table->GfxActivityAverageAlpha = (uint8_t)
   2700			(data->gfx_activity_average_alpha);
   2701
   2702	vega10_populate_and_upload_avfs_fuse_override(hwmgr);
   2703
   2704	result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false);
   2705
   2706	PP_ASSERT_WITH_CODE(!result,
   2707			"Failed to upload PPtable!", return result);
   2708
   2709	result = vega10_avfs_enable(hwmgr, true);
   2710	PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
   2711					return result);
   2712	vega10_acg_enable(hwmgr);
   2713
   2714	return 0;
   2715}
   2716
   2717static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
   2718{
   2719	struct vega10_hwmgr *data = hwmgr->backend;
   2720
   2721	if (data->smu_features[GNLD_THERMAL].supported) {
   2722		if (data->smu_features[GNLD_THERMAL].enabled)
   2723			pr_info("THERMAL Feature Already enabled!");
   2724
   2725		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		data->smu_features[GNLD_THERMAL].enabled = true;
   2732	}
   2733
   2734	return 0;
   2735}
   2736
   2737static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
   2738{
   2739	struct vega10_hwmgr *data = hwmgr->backend;
   2740
   2741	if (data->smu_features[GNLD_THERMAL].supported) {
   2742		if (!data->smu_features[GNLD_THERMAL].enabled)
   2743			pr_info("THERMAL Feature Already disabled!");
   2744
   2745		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		data->smu_features[GNLD_THERMAL].enabled = false;
   2752	}
   2753
   2754	return 0;
   2755}
   2756
   2757static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
   2758{
   2759	struct vega10_hwmgr *data = hwmgr->backend;
   2760
   2761	if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) {
   2762		if (data->smu_features[GNLD_VR0HOT].supported) {
   2763			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			data->smu_features[GNLD_VR0HOT].enabled = true;
   2770		} else {
   2771			if (data->smu_features[GNLD_VR1HOT].supported) {
   2772				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				data->smu_features[GNLD_VR1HOT].enabled = true;
   2779			}
   2780		}
   2781	}
   2782	return 0;
   2783}
   2784
   2785static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
   2786{
   2787	struct vega10_hwmgr *data = hwmgr->backend;
   2788
   2789	if (data->registry_data.ulv_support) {
   2790		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		data->smu_features[GNLD_ULV].enabled = true;
   2795	}
   2796
   2797	return 0;
   2798}
   2799
   2800static int vega10_disable_ulv(struct pp_hwmgr *hwmgr)
   2801{
   2802	struct vega10_hwmgr *data = hwmgr->backend;
   2803
   2804	if (data->registry_data.ulv_support) {
   2805		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		data->smu_features[GNLD_ULV].enabled = false;
   2810	}
   2811
   2812	return 0;
   2813}
   2814
   2815static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
   2816{
   2817	struct vega10_hwmgr *data = hwmgr->backend;
   2818
   2819	if (data->smu_features[GNLD_DS_GFXCLK].supported) {
   2820		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		data->smu_features[GNLD_DS_GFXCLK].enabled = true;
   2825	}
   2826
   2827	if (data->smu_features[GNLD_DS_SOCCLK].supported) {
   2828		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		data->smu_features[GNLD_DS_SOCCLK].enabled = true;
   2833	}
   2834
   2835	if (data->smu_features[GNLD_DS_LCLK].supported) {
   2836		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		data->smu_features[GNLD_DS_LCLK].enabled = true;
   2841	}
   2842
   2843	if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
   2844		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		data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
   2849	}
   2850
   2851	return 0;
   2852}
   2853
   2854static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
   2855{
   2856	struct vega10_hwmgr *data = hwmgr->backend;
   2857
   2858	if (data->smu_features[GNLD_DS_GFXCLK].supported) {
   2859		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		data->smu_features[GNLD_DS_GFXCLK].enabled = false;
   2864	}
   2865
   2866	if (data->smu_features[GNLD_DS_SOCCLK].supported) {
   2867		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		data->smu_features[GNLD_DS_SOCCLK].enabled = false;
   2872	}
   2873
   2874	if (data->smu_features[GNLD_DS_LCLK].supported) {
   2875		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		data->smu_features[GNLD_DS_LCLK].enabled = false;
   2880	}
   2881
   2882	if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
   2883		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		data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
   2888	}
   2889
   2890	return 0;
   2891}
   2892
   2893static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
   2894{
   2895	struct vega10_hwmgr *data = hwmgr->backend;
   2896	uint32_t i, feature_mask = 0;
   2897
   2898	if (!hwmgr->not_vf)
   2899		return 0;
   2900
   2901	if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
   2902		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		data->smu_features[GNLD_LED_DISPLAY].enabled = false;
   2906	}
   2907
   2908	for (i = 0; i < GNLD_DPM_MAX; i++) {
   2909		if (data->smu_features[i].smu_feature_bitmap & bitmap) {
   2910			if (data->smu_features[i].supported) {
   2911				if (data->smu_features[i].enabled) {
   2912					feature_mask |= data->smu_features[i].
   2913							smu_feature_bitmap;
   2914					data->smu_features[i].enabled = false;
   2915				}
   2916			}
   2917		}
   2918	}
   2919
   2920	vega10_enable_smc_features(hwmgr, false, feature_mask);
   2921
   2922	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 */
   2932static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
   2933{
   2934	struct vega10_hwmgr *data = hwmgr->backend;
   2935	uint32_t i, feature_mask = 0;
   2936
   2937	for (i = 0; i < GNLD_DPM_MAX; i++) {
   2938		if (data->smu_features[i].smu_feature_bitmap & bitmap) {
   2939			if (data->smu_features[i].supported) {
   2940				if (!data->smu_features[i].enabled) {
   2941					feature_mask |= data->smu_features[i].
   2942							smu_feature_bitmap;
   2943					data->smu_features[i].enabled = true;
   2944				}
   2945			}
   2946		}
   2947	}
   2948
   2949	if (vega10_enable_smc_features(hwmgr,
   2950			true, feature_mask)) {
   2951		for (i = 0; i < GNLD_DPM_MAX; i++) {
   2952			if (data->smu_features[i].smu_feature_bitmap &
   2953					feature_mask)
   2954				data->smu_features[i].enabled = false;
   2955		}
   2956	}
   2957
   2958	if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
   2959		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		data->smu_features[GNLD_LED_DISPLAY].enabled = true;
   2963	}
   2964
   2965	if (data->vbios_boot_state.bsoc_vddc_lock) {
   2966		smum_send_msg_to_smc_with_parameter(hwmgr,
   2967						PPSMC_MSG_SetFloorSocVoltage, 0,
   2968						NULL);
   2969		data->vbios_boot_state.bsoc_vddc_lock = false;
   2970	}
   2971
   2972	if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) {
   2973		if (data->smu_features[GNLD_ACDC].supported) {
   2974			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			data->smu_features[GNLD_ACDC].enabled = true;
   2979		}
   2980	}
   2981
   2982	if (data->registry_data.pcie_dpm_key_disabled) {
   2983		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		data->smu_features[GNLD_DPM_LINK].enabled = false;
   2987		data->smu_features[GNLD_DPM_LINK].supported = false;
   2988	}
   2989
   2990	return 0;
   2991}
   2992
   2993
   2994static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
   2995{
   2996	struct vega10_hwmgr *data = hwmgr->backend;
   2997
   2998	if (data->smu_features[GNLD_PCC_LIMIT].supported) {
   2999		if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled)
   3000			pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled");
   3001		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		data->smu_features[GNLD_PCC_LIMIT].enabled = enable;
   3006	}
   3007
   3008	return 0;
   3009}
   3010
   3011static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
   3012{
   3013	struct vega10_hwmgr *data = hwmgr->backend;
   3014	int tmp_result, result = 0;
   3015
   3016	if (hwmgr->not_vf) {
   3017		vega10_enable_disable_PCC_limit_feature(hwmgr, true);
   3018
   3019		smum_send_msg_to_smc_with_parameter(hwmgr,
   3020			PPSMC_MSG_ConfigureTelemetry, data->config_telemetry,
   3021			NULL);
   3022
   3023		tmp_result = vega10_construct_voltage_tables(hwmgr);
   3024		PP_ASSERT_WITH_CODE(!tmp_result,
   3025				    "Failed to construct voltage tables!",
   3026				    result = tmp_result);
   3027	}
   3028
   3029	if (hwmgr->not_vf || hwmgr->pp_one_vf) {
   3030		tmp_result = vega10_init_smc_table(hwmgr);
   3031		PP_ASSERT_WITH_CODE(!tmp_result,
   3032				    "Failed to initialize SMC table!",
   3033				    result = tmp_result);
   3034	}
   3035
   3036	if (hwmgr->not_vf) {
   3037		if (PP_CAP(PHM_PlatformCaps_ThermalController)) {
   3038			tmp_result = vega10_enable_thermal_protection(hwmgr);
   3039			PP_ASSERT_WITH_CODE(!tmp_result,
   3040					    "Failed to enable thermal protection!",
   3041					    result = tmp_result);
   3042		}
   3043
   3044		tmp_result = vega10_enable_vrhot_feature(hwmgr);
   3045		PP_ASSERT_WITH_CODE(!tmp_result,
   3046				    "Failed to enable VR hot feature!",
   3047				    result = tmp_result);
   3048
   3049		tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr);
   3050		PP_ASSERT_WITH_CODE(!tmp_result,
   3051				    "Failed to enable deep sleep master switch!",
   3052				    result = tmp_result);
   3053	}
   3054
   3055	if (hwmgr->not_vf) {
   3056		tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES);
   3057		PP_ASSERT_WITH_CODE(!tmp_result,
   3058				    "Failed to start DPM!", result = tmp_result);
   3059	}
   3060
   3061	if (hwmgr->not_vf) {
   3062		/* enable didt, do not abort if failed didt */
   3063		tmp_result = vega10_enable_didt_config(hwmgr);
   3064		PP_ASSERT(!tmp_result,
   3065			  "Failed to enable didt config!");
   3066	}
   3067
   3068	tmp_result = vega10_enable_power_containment(hwmgr);
   3069	PP_ASSERT_WITH_CODE(!tmp_result,
   3070			    "Failed to enable power containment!",
   3071			    result = tmp_result);
   3072
   3073	if (hwmgr->not_vf) {
   3074		tmp_result = vega10_power_control_set_level(hwmgr);
   3075		PP_ASSERT_WITH_CODE(!tmp_result,
   3076				    "Failed to power control set level!",
   3077				    result = tmp_result);
   3078
   3079		tmp_result = vega10_enable_ulv(hwmgr);
   3080		PP_ASSERT_WITH_CODE(!tmp_result,
   3081				    "Failed to enable ULV!",
   3082				    result = tmp_result);
   3083	}
   3084
   3085	return result;
   3086}
   3087
   3088static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr)
   3089{
   3090	return sizeof(struct vega10_power_state);
   3091}
   3092
   3093static 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	struct vega10_power_state *vega10_ps =
   3099			cast_phw_vega10_power_state(&(power_state->hardware));
   3100	struct vega10_performance_level *performance_level;
   3101	ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state;
   3102	ATOM_Vega10_POWERPLAYTABLE *powerplay_table =
   3103			(ATOM_Vega10_POWERPLAYTABLE *)pp_table;
   3104	ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
   3105			(ATOM_Vega10_SOCCLK_Dependency_Table *)
   3106			(((unsigned long)powerplay_table) +
   3107			le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
   3108	ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
   3109			(ATOM_Vega10_GFXCLK_Dependency_Table *)
   3110			(((unsigned long)powerplay_table) +
   3111			le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
   3112	ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
   3113			(ATOM_Vega10_MCLK_Dependency_Table *)
   3114			(((unsigned long)powerplay_table) +
   3115			le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
   3116
   3117
   3118	/* The following fields are not initialized here:
   3119	 * id orderedList allStatesList
   3120	 */
   3121	power_state->classification.ui_label =
   3122			(le16_to_cpu(state_entry->usClassification) &
   3123			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
   3124			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
   3125	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	power_state->classification.temporary_state = false;
   3130	power_state->classification.to_be_deleted = false;
   3131
   3132	power_state->validation.disallowOnDC =
   3133			((le32_to_cpu(state_entry->ulCapsAndSettings) &
   3134					ATOM_Vega10_DISALLOW_ON_DC) != 0);
   3135
   3136	power_state->display.disableFrameModulation = false;
   3137	power_state->display.limitRefreshrate = false;
   3138	power_state->display.enableVariBright =
   3139			((le32_to_cpu(state_entry->ulCapsAndSettings) &
   3140					ATOM_Vega10_ENABLE_VARIBRIGHT) != 0);
   3141
   3142	power_state->validation.supportedPowerLevels = 0;
   3143	power_state->uvd_clocks.VCLK = 0;
   3144	power_state->uvd_clocks.DCLK = 0;
   3145	power_state->temperatures.min = 0;
   3146	power_state->temperatures.max = 0;
   3147
   3148	performance_level = &(vega10_ps->performance_levels
   3149			[vega10_ps->performance_level_count++]);
   3150
   3151	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	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	performance_level->soc_clock = socclk_dep_table->entries
   3166			[state_entry->ucSocClockIndexLow].ulClk;
   3167	performance_level->gfx_clock = gfxclk_dep_table->entries
   3168			[state_entry->ucGfxClockIndexLow].ulClk;
   3169	performance_level->mem_clock = mclk_dep_table->entries
   3170			[state_entry->ucMemClockIndexLow].ulMemClk;
   3171
   3172	performance_level = &(vega10_ps->performance_levels
   3173				[vega10_ps->performance_level_count++]);
   3174	performance_level->soc_clock = socclk_dep_table->entries
   3175				[state_entry->ucSocClockIndexHigh].ulClk;
   3176	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		if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0))
   3181			performance_level->gfx_clock =
   3182				gfxclk_dep_table->entries[4].ulClk;
   3183		else
   3184			performance_level->gfx_clock = gfxclk_dep_table->entries
   3185				[state_entry->ucGfxClockIndexHigh].ulClk;
   3186	} else if (gfxclk_dep_table->ucRevId == 1) {
   3187		patom_record_V2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
   3188		if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0))
   3189			performance_level->gfx_clock = patom_record_V2[4].ulClk;
   3190		else
   3191			performance_level->gfx_clock =
   3192				patom_record_V2[state_entry->ucGfxClockIndexHigh].ulClk;
   3193	}
   3194
   3195	performance_level->mem_clock = mclk_dep_table->entries
   3196			[state_entry->ucMemClockIndexHigh].ulMemClk;
   3197	return 0;
   3198}
   3199
   3200static 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	state->hardware.magic = PhwVega10_Magic;
   3207
   3208	vega10_ps = cast_phw_vega10_power_state(&state->hardware);
   3209
   3210	result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state,
   3211			vega10_get_pp_table_entry_callback_func);
   3212	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	if (!state->validation.disallowOnDC)
   3221		vega10_ps->dc_compatible = true;
   3222
   3223	vega10_ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
   3224	vega10_ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
   3225
   3226	return 0;
   3227}
   3228
   3229static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr,
   3230	     struct pp_hw_power_state *hw_ps)
   3231{
   3232	return 0;
   3233}
   3234
   3235static 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	struct amdgpu_device *adev = hwmgr->adev;
   3240	struct vega10_power_state *vega10_ps =
   3241				cast_phw_vega10_power_state(&request_ps->hardware);
   3242	uint32_t sclk;
   3243	uint32_t mclk;
   3244	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	struct vega10_hwmgr *data = hwmgr->backend;
   3252	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	uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
   3257	uint32_t latency;
   3258
   3259	data->battery_state = (PP_StateUILabel_Battery ==
   3260			request_ps->classification.ui_label);
   3261
   3262	if (vega10_ps->performance_level_count != 2)
   3263		pr_info("VI should always have 2 performance levels");
   3264
   3265	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	if (!adev->pm.ac_power) {
   3271		for (i = 0; i < vega10_ps->performance_level_count; i++) {
   3272			if (vega10_ps->performance_levels[i].mem_clock >
   3273				max_limits->mclk)
   3274				vega10_ps->performance_levels[i].mem_clock =
   3275						max_limits->mclk;
   3276			if (vega10_ps->performance_levels[i].gfx_clock >
   3277				max_limits->sclk)
   3278				vega10_ps->performance_levels[i].gfx_clock =
   3279						max_limits->sclk;
   3280		}
   3281	}
   3282
   3283	/* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
   3284	minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock;
   3285	minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
   3286
   3287	if (PP_CAP(PHM_PlatformCaps_StablePState)) {
   3288		stable_pstate_sclk_dpm_percentage =
   3289			data->registry_data.stable_pstate_sclk_dpm_percentage;
   3290		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		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
   3297		stable_pstate_sclk = (max_limits->sclk *
   3298				stable_pstate_sclk_dpm_percentage) / 100;
   3299
   3300		for (count = table_info->vdd_dep_on_sclk->count - 1;
   3301				count >= 0; count--) {
   3302			if (stable_pstate_sclk >=
   3303					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		if (count < 0)
   3311			stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
   3312
   3313		stable_pstate_mclk = max_limits->mclk;
   3314
   3315		minimum_clocks.engineClock = stable_pstate_sclk;
   3316		minimum_clocks.memoryClock = stable_pstate_mclk;
   3317	}
   3318
   3319	disable_mclk_switching_for_frame_lock =
   3320		PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
   3321	disable_mclk_switching_for_vr =
   3322		PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);
   3323	force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh);
   3324
   3325	if (hwmgr->display_config->num_display == 0)
   3326		disable_mclk_switching = false;
   3327	else
   3328		disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
   3329					  !hwmgr->display_config->multi_monitor_in_sync) ||
   3330			disable_mclk_switching_for_frame_lock ||
   3331			disable_mclk_switching_for_vr ||
   3332			force_mclk_high;
   3333
   3334	sclk = vega10_ps->performance_levels[0].gfx_clock;
   3335	mclk = vega10_ps->performance_levels[0].mem_clock;
   3336
   3337	if (sclk < minimum_clocks.engineClock)
   3338		sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
   3339				max_limits->sclk : minimum_clocks.engineClock;
   3340
   3341	if (mclk < minimum_clocks.memoryClock)
   3342		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
   3343				max_limits->mclk : minimum_clocks.memoryClock;
   3344
   3345	vega10_ps->performance_levels[0].gfx_clock = sclk;
   3346	vega10_ps->performance_levels[0].mem_clock = mclk;
   3347
   3348	if (vega10_ps->performance_levels[1].gfx_clock <
   3349			vega10_ps->performance_levels[0].gfx_clock)
   3350		vega10_ps->performance_levels[0].gfx_clock =
   3351				vega10_ps->performance_levels[1].gfx_clock;
   3352
   3353	if (disable_mclk_switching) {
   3354		/* Set Mclk the max of level 0 and level 1 */
   3355		if (mclk < vega10_ps->performance_levels[1].mem_clock)
   3356			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		latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
   3362		for (i = 0; i < data->mclk_latency_table.count; i++) {
   3363			if ((data->mclk_latency_table.entries[i].latency <= latency) &&
   3364				(data->mclk_latency_table.entries[i].frequency >=
   3365						vega10_ps->performance_levels[0].mem_clock) &&
   3366				(data->mclk_latency_table.entries[i].frequency <=
   3367						vega10_ps->performance_levels[1].mem_clock))
   3368				mclk = data->mclk_latency_table.entries[i].frequency;
   3369		}
   3370		vega10_ps->performance_levels[0].mem_clock = mclk;
   3371	} else {
   3372		if (vega10_ps->performance_levels[1].mem_clock <
   3373				vega10_ps->performance_levels[0].mem_clock)
   3374			vega10_ps->performance_levels[0].mem_clock =
   3375					vega10_ps->performance_levels[1].mem_clock;
   3376	}
   3377
   3378	if (PP_CAP(PHM_PlatformCaps_StablePState)) {
   3379		for (i = 0; i < vega10_ps->performance_level_count; i++) {
   3380			vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk;
   3381			vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk;
   3382		}
   3383	}
   3384
   3385	return 0;
   3386}
   3387
   3388static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
   3389{
   3390	struct vega10_hwmgr *data = hwmgr->backend;
   3391	const struct phm_set_power_state_input *states =
   3392			(const struct phm_set_power_state_input *)input;
   3393	const struct vega10_power_state *vega10_ps =
   3394			cast_const_phw_vega10_power_state(states->pnew_state);
   3395	struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
   3396	uint32_t sclk = vega10_ps->performance_levels
   3397			[vega10_ps->performance_level_count - 1].gfx_clock;
   3398	struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
   3399	uint32_t mclk = vega10_ps->performance_levels
   3400			[vega10_ps->performance_level_count - 1].mem_clock;
   3401	uint32_t i;
   3402
   3403	for (i = 0; i < sclk_table->count; i++) {
   3404		if (sclk == sclk_table->dpm_levels[i].value)
   3405			break;
   3406	}
   3407
   3408	if (i >= sclk_table->count) {
   3409		if (sclk > sclk_table->dpm_levels[i-1].value) {
   3410			data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
   3411			sclk_table->dpm_levels[i-1].value = sclk;
   3412		}
   3413	}
   3414
   3415	for (i = 0; i < mclk_table->count; i++) {
   3416		if (mclk == mclk_table->dpm_levels[i].value)
   3417			break;
   3418	}
   3419
   3420	if (i >= mclk_table->count) {
   3421		if (mclk > mclk_table->dpm_levels[i-1].value) {
   3422			data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
   3423			mclk_table->dpm_levels[i-1].value = mclk;
   3424		}
   3425	}
   3426
   3427	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
   3428		data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
   3429
   3430	return 0;
   3431}
   3432
   3433static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
   3434		struct pp_hwmgr *hwmgr, const void *input)
   3435{
   3436	int result = 0;
   3437	struct vega10_hwmgr *data = hwmgr->backend;
   3438	struct vega10_dpm_table *dpm_table = &data->dpm_table;
   3439	struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table;
   3440	struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk;
   3441	int count;
   3442
   3443	if (!data->need_update_dpm_table)
   3444		return 0;
   3445
   3446	if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
   3447		for (count = 0; count < dpm_table->gfx_table.count; count++)
   3448			dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk;
   3449	}
   3450
   3451	odn_clk_table = &odn_table->vdd_dep_on_mclk;
   3452	if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
   3453		for (count = 0; count < dpm_table->mem_table.count; count++)
   3454			dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk;
   3455	}
   3456
   3457	if (data->need_update_dpm_table &
   3458			(DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) {
   3459		result = vega10_populate_all_graphic_levels(hwmgr);
   3460		PP_ASSERT_WITH_CODE((0 == result),
   3461				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
   3462				return result);
   3463	}
   3464
   3465	if (data->need_update_dpm_table &
   3466			(DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) {
   3467		result = vega10_populate_all_memory_levels(hwmgr);
   3468		PP_ASSERT_WITH_CODE((0 == result),
   3469				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
   3470				return result);
   3471	}
   3472
   3473	vega10_populate_vddc_soc_levels(hwmgr);
   3474
   3475	return result;
   3476}
   3477
   3478static 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	for (i = 0; i < dpm_table->count; i++) {
   3485		if ((dpm_table->dpm_levels[i].value < low_limit) ||
   3486		    (dpm_table->dpm_levels[i].value > high_limit))
   3487			dpm_table->dpm_levels[i].enabled = false;
   3488		else
   3489			dpm_table->dpm_levels[i].enabled = true;
   3490	}
   3491	return 0;
   3492}
   3493
   3494static 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	for (i = 0; i < dpm_table->count; i++) {
   3502		if ((dpm_table->dpm_levels[i].value < low_limit) ||
   3503		    (dpm_table->dpm_levels[i].value > high_limit))
   3504			dpm_table->dpm_levels[i].enabled = false;
   3505		else if (!((1 << i) & disable_dpm_mask))
   3506			dpm_table->dpm_levels[i].enabled = false;
   3507		else
   3508			dpm_table->dpm_levels[i].enabled = true;
   3509	}
   3510	return 0;
   3511}
   3512
   3513static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr,
   3514		const struct vega10_power_state *vega10_ps)
   3515{
   3516	struct vega10_hwmgr *data = hwmgr->backend;
   3517	uint32_t high_limit_count;
   3518
   3519	PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1),
   3520			"power state did not have any performance level",
   3521			return -1);
   3522
   3523	high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1;
   3524
   3525	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	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	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
   3544static uint32_t vega10_find_lowest_dpm_level(
   3545		struct vega10_single_dpm_table *table)
   3546{
   3547	uint32_t i;
   3548
   3549	for (i = 0; i < table->count; i++) {
   3550		if (table->dpm_levels[i].enabled)
   3551			break;
   3552	}
   3553
   3554	return i;
   3555}
   3556
   3557static uint32_t vega10_find_highest_dpm_level(
   3558		struct vega10_single_dpm_table *table)
   3559{
   3560	uint32_t i = 0;
   3561
   3562	if (table->count <= MAX_REGULAR_DPM_NUMBER) {
   3563		for (i = table->count; i > 0; i--) {
   3564			if (table->dpm_levels[i - 1].enabled)
   3565				return i - 1;
   3566		}
   3567	} else {
   3568		pr_info("DPM Table Has Too Many Entries!");
   3569		return MAX_REGULAR_DPM_NUMBER - 1;
   3570	}
   3571
   3572	return i;
   3573}
   3574
   3575static void vega10_apply_dal_minimum_voltage_request(
   3576		struct pp_hwmgr *hwmgr)
   3577{
   3578	return;
   3579}
   3580
   3581static 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	struct phm_ppt_v2_information *table_info =
   3585			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   3586
   3587	vdd_dep_table_on_mclk  = table_info->vdd_dep_on_mclk;
   3588
   3589	return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1;
   3590}
   3591
   3592static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
   3593{
   3594	struct vega10_hwmgr *data = hwmgr->backend;
   3595	uint32_t socclk_idx;
   3596
   3597	vega10_apply_dal_minimum_voltage_request(hwmgr);
   3598
   3599	if (!data->registry_data.sclk_dpm_key_disabled) {
   3600		if (data->smc_state_table.gfx_boot_level !=
   3601				data->dpm_table.gfx_table.dpm_state.soft_min_level) {
   3602			smum_send_msg_to_smc_with_parameter(hwmgr,
   3603				PPSMC_MSG_SetSoftMinGfxclkByIndex,
   3604				data->smc_state_table.gfx_boot_level,
   3605				NULL);
   3606
   3607			data->dpm_table.gfx_table.dpm_state.soft_min_level =
   3608					data->smc_state_table.gfx_boot_level;
   3609		}
   3610	}
   3611
   3612	if (!data->registry_data.mclk_dpm_key_disabled) {
   3613		if (data->smc_state_table.mem_boot_level !=
   3614				data->dpm_table.mem_table.dpm_state.soft_min_level) {
   3615			if ((data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1)
   3616			    && hwmgr->not_vf) {
   3617				socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr);
   3618				smum_send_msg_to_smc_with_parameter(hwmgr,
   3619						PPSMC_MSG_SetSoftMinSocclkByIndex,
   3620						socclk_idx,
   3621						NULL);
   3622			} else {
   3623				smum_send_msg_to_smc_with_parameter(hwmgr,
   3624						PPSMC_MSG_SetSoftMinUclkByIndex,
   3625						data->smc_state_table.mem_boot_level,
   3626						NULL);
   3627			}
   3628			data->dpm_table.mem_table.dpm_state.soft_min_level =
   3629					data->smc_state_table.mem_boot_level;
   3630		}
   3631	}
   3632
   3633	if (!hwmgr->not_vf)
   3634		return 0;
   3635
   3636	if (!data->registry_data.socclk_dpm_key_disabled) {
   3637		if (data->smc_state_table.soc_boot_level !=
   3638				data->dpm_table.soc_table.dpm_state.soft_min_level) {
   3639			smum_send_msg_to_smc_with_parameter(hwmgr,
   3640				PPSMC_MSG_SetSoftMinSocclkByIndex,
   3641				data->smc_state_table.soc_boot_level,
   3642				NULL);
   3643			data->dpm_table.soc_table.dpm_state.soft_min_level =
   3644					data->smc_state_table.soc_boot_level;
   3645		}
   3646	}
   3647
   3648	return 0;
   3649}
   3650
   3651static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
   3652{
   3653	struct vega10_hwmgr *data = hwmgr->backend;
   3654
   3655	vega10_apply_dal_minimum_voltage_request(hwmgr);
   3656
   3657	if (!data->registry_data.sclk_dpm_key_disabled) {
   3658		if (data->smc_state_table.gfx_max_level !=
   3659			data->dpm_table.gfx_table.dpm_state.soft_max_level) {
   3660			smum_send_msg_to_smc_with_parameter(hwmgr,
   3661				PPSMC_MSG_SetSoftMaxGfxclkByIndex,
   3662				data->smc_state_table.gfx_max_level,
   3663				NULL);
   3664			data->dpm_table.gfx_table.dpm_state.soft_max_level =
   3665					data->smc_state_table.gfx_max_level;
   3666		}
   3667	}
   3668
   3669	if (!data->registry_data.mclk_dpm_key_disabled) {
   3670		if (data->smc_state_table.mem_max_level !=
   3671			data->dpm_table.mem_table.dpm_state.soft_max_level) {
   3672			smum_send_msg_to_smc_with_parameter(hwmgr,
   3673					PPSMC_MSG_SetSoftMaxUclkByIndex,
   3674					data->smc_state_table.mem_max_level,
   3675					NULL);
   3676			data->dpm_table.mem_table.dpm_state.soft_max_level =
   3677					data->smc_state_table.mem_max_level;
   3678		}
   3679	}
   3680
   3681	if (!hwmgr->not_vf)
   3682		return 0;
   3683
   3684	if (!data->registry_data.socclk_dpm_key_disabled) {
   3685		if (data->smc_state_table.soc_max_level !=
   3686			data->dpm_table.soc_table.dpm_state.soft_max_level) {
   3687			smum_send_msg_to_smc_with_parameter(hwmgr,
   3688				PPSMC_MSG_SetSoftMaxSocclkByIndex,
   3689				data->smc_state_table.soc_max_level,
   3690				NULL);
   3691			data->dpm_table.soc_table.dpm_state.soft_max_level =
   3692					data->smc_state_table.soc_max_level;
   3693		}
   3694	}
   3695
   3696	return 0;
   3697}
   3698
   3699static int vega10_generate_dpm_level_enable_mask(
   3700		struct pp_hwmgr *hwmgr, const void *input)
   3701{
   3702	struct vega10_hwmgr *data = hwmgr->backend;
   3703	const struct phm_set_power_state_input *states =
   3704			(const struct phm_set_power_state_input *)input;
   3705	const struct vega10_power_state *vega10_ps =
   3706			cast_const_phw_vega10_power_state(states->pnew_state);
   3707	int i;
   3708
   3709	PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
   3710			"Attempt to Trim DPM States Failed!",
   3711			return -1);
   3712
   3713	data->smc_state_table.gfx_boot_level =
   3714			vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
   3715	data->smc_state_table.gfx_max_level =
   3716			vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
   3717	data->smc_state_table.mem_boot_level =
   3718			vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
   3719	data->smc_state_table.mem_max_level =
   3720			vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
   3721	data->smc_state_table.soc_boot_level =
   3722			vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table));
   3723	data->smc_state_table.soc_max_level =
   3724			vega10_find_highest_dpm_level(&(data->dpm_table.soc_table));
   3725
   3726	PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   3727			"Attempt to upload DPM Bootup Levels Failed!",
   3728			return -1);
   3729	PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
   3730			"Attempt to upload DPM Max Levels Failed!",
   3731			return -1);
   3732	for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++)
   3733		data->dpm_table.gfx_table.dpm_levels[i].enabled = true;
   3734
   3735
   3736	for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++)
   3737		data->dpm_table.mem_table.dpm_levels[i].enabled = true;
   3738
   3739	for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++)
   3740		data->dpm_table.soc_table.dpm_levels[i].enabled = true;
   3741
   3742	return 0;
   3743}
   3744
   3745int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
   3746{
   3747	struct vega10_hwmgr *data = hwmgr->backend;
   3748
   3749	if (data->smu_features[GNLD_DPM_VCE].supported) {
   3750		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		data->smu_features[GNLD_DPM_VCE].enabled = enable;
   3756	}
   3757
   3758	return 0;
   3759}
   3760
   3761static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
   3762{
   3763	struct vega10_hwmgr *data = hwmgr->backend;
   3764	uint32_t low_sclk_interrupt_threshold = 0;
   3765
   3766	if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) &&
   3767		(data->low_sclk_interrupt_threshold != 0)) {
   3768		low_sclk_interrupt_threshold =
   3769				data->low_sclk_interrupt_threshold;
   3770
   3771		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		smum_send_msg_to_smc_with_parameter(hwmgr,
   3776				PPSMC_MSG_SetLowGfxclkInterruptThreshold,
   3777				(uint32_t)low_sclk_interrupt_threshold,
   3778				NULL);
   3779	}
   3780
   3781	return 0;
   3782}
   3783
   3784static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
   3785		const void *input)
   3786{
   3787	int tmp_result, result = 0;
   3788	struct vega10_hwmgr *data = hwmgr->backend;
   3789	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   3790
   3791	tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
   3792	PP_ASSERT_WITH_CODE(!tmp_result,
   3793			"Failed to find DPM states clocks in DPM table!",
   3794			result = tmp_result);
   3795
   3796	tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
   3797	PP_ASSERT_WITH_CODE(!tmp_result,
   3798			"Failed to populate and upload SCLK MCLK DPM levels!",
   3799			result = tmp_result);
   3800
   3801	tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input);
   3802	PP_ASSERT_WITH_CODE(!tmp_result,
   3803			"Failed to generate DPM level enabled mask!",
   3804			result = tmp_result);
   3805
   3806	tmp_result = vega10_update_sclk_threshold(hwmgr);
   3807	PP_ASSERT_WITH_CODE(!tmp_result,
   3808			"Failed to update SCLK threshold!",
   3809			result = tmp_result);
   3810
   3811	result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false);
   3812	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	if(hwmgr->hardcode_pp_table != NULL)
   3820		data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
   3821
   3822	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	data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC;
   3829
   3830	return 0;
   3831}
   3832
   3833static 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	if (hwmgr == NULL)
   3839		return -EINVAL;
   3840
   3841	ps = hwmgr->request_ps;
   3842
   3843	if (ps == NULL)
   3844		return -EINVAL;
   3845
   3846	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   3847
   3848	if (low)
   3849		return vega10_ps->performance_levels[0].gfx_clock;
   3850	else
   3851		return vega10_ps->performance_levels
   3852				[vega10_ps->performance_level_count - 1].gfx_clock;
   3853}
   3854
   3855static 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	if (hwmgr == NULL)
   3861		return -EINVAL;
   3862
   3863	ps = hwmgr->request_ps;
   3864
   3865	if (ps == NULL)
   3866		return -EINVAL;
   3867
   3868	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   3869
   3870	if (low)
   3871		return vega10_ps->performance_levels[0].mem_clock;
   3872	else
   3873		return vega10_ps->performance_levels
   3874				[vega10_ps->performance_level_count-1].mem_clock;
   3875}
   3876
   3877static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr,
   3878		uint32_t *query)
   3879{
   3880	uint32_t value;
   3881
   3882	if (!query)
   3883		return -EINVAL;
   3884
   3885	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	*query = value << 8;
   3889
   3890	return 0;
   3891}
   3892
   3893static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
   3894			      void *value, int *size)
   3895{
   3896	struct amdgpu_device *adev = hwmgr->adev;
   3897	uint32_t sclk_mhz, mclk_idx, activity_percent = 0;
   3898	struct vega10_hwmgr *data = hwmgr->backend;
   3899	struct vega10_dpm_table *dpm_table = &data->dpm_table;
   3900	int ret = 0;
   3901	uint32_t val_vid;
   3902
   3903	switch (idx) {
   3904	case AMDGPU_PP_SENSOR_GFX_SCLK:
   3905		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency, &sclk_mhz);
   3906		*((uint32_t *)value) = sclk_mhz * 100;
   3907		break;
   3908	case AMDGPU_PP_SENSOR_GFX_MCLK:
   3909		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &mclk_idx);
   3910		if (mclk_idx < dpm_table->mem_table.count) {
   3911			*((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value;
   3912			*size = 4;
   3913		} else {
   3914			ret = -EINVAL;
   3915		}
   3916		break;
   3917	case AMDGPU_PP_SENSOR_GPU_LOAD:
   3918		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0,
   3919						&activity_percent);
   3920		*((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
   3921		*size = 4;
   3922		break;
   3923	case AMDGPU_PP_SENSOR_GPU_TEMP:
   3924		*((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr);
   3925		*size = 4;
   3926		break;
   3927	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
   3928		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot, (uint32_t *)value);
   3929		*((uint32_t *)value) = *((uint32_t *)value) *
   3930			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3931		*size = 4;
   3932		break;
   3933	case AMDGPU_PP_SENSOR_MEM_TEMP:
   3934		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM, (uint32_t *)value);
   3935		*((uint32_t *)value) = *((uint32_t *)value) *
   3936			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   3937		*size = 4;
   3938		break;
   3939	case AMDGPU_PP_SENSOR_UVD_POWER:
   3940		*((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
   3941		*size = 4;
   3942		break;
   3943	case AMDGPU_PP_SENSOR_VCE_POWER:
   3944		*((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
   3945		*size = 4;
   3946		break;
   3947	case AMDGPU_PP_SENSOR_GPU_POWER:
   3948		ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value);
   3949		break;
   3950	case AMDGPU_PP_SENSOR_VDDGFX:
   3951		val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) &
   3952			SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >>
   3953			SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT;
   3954		*((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid);
   3955		return 0;
   3956	case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
   3957		ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value);
   3958		if (!ret)
   3959			*size = 8;
   3960		break;
   3961	default:
   3962		ret = -EOPNOTSUPP;
   3963		break;
   3964	}
   3965
   3966	return ret;
   3967}
   3968
   3969static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
   3970		bool has_disp)
   3971{
   3972	smum_send_msg_to_smc_with_parameter(hwmgr,
   3973			PPSMC_MSG_SetUclkFastSwitch,
   3974			has_disp ? 1 : 0,
   3975			NULL);
   3976}
   3977
   3978static int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
   3979		struct pp_display_clock_request *clock_req)
   3980{
   3981	int result = 0;
   3982	enum amd_pp_clock_type clk_type = clock_req->clock_type;
   3983	uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
   3984	DSPCLK_e clk_select = 0;
   3985	uint32_t clk_request = 0;
   3986
   3987	switch (clk_type) {
   3988	case amd_pp_dcef_clock:
   3989		clk_select = DSPCLK_DCEFCLK;
   3990		break;
   3991	case amd_pp_disp_clock:
   3992		clk_select = DSPCLK_DISPCLK;
   3993		break;
   3994	case amd_pp_pixel_clock:
   3995		clk_select = DSPCLK_PIXCLK;
   3996		break;
   3997	case amd_pp_phy_clock:
   3998		clk_select = DSPCLK_PHYCLK;
   3999		break;
   4000	default:
   4001		pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
   4002		result = -1;
   4003		break;
   4004	}
   4005
   4006	if (!result) {
   4007		clk_request = (clk_freq << 16) | clk_select;
   4008		smum_send_msg_to_smc_with_parameter(hwmgr,
   4009				PPSMC_MSG_RequestDisplayClockByFreq,
   4010				clk_request,
   4011				NULL);
   4012	}
   4013
   4014	return result;
   4015}
   4016
   4017static 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	if (mclk_table == NULL || mclk_table->count == 0)
   4025		return 0;
   4026
   4027	count = (uint8_t)(mclk_table->count);
   4028
   4029	for(i = 0; i < count; i++) {
   4030		if(mclk_table->entries[i].clk >= frequency)
   4031			return i;
   4032	}
   4033
   4034	return i-1;
   4035}
   4036
   4037static int vega10_notify_smc_display_config_after_ps_adjustment(
   4038		struct pp_hwmgr *hwmgr)
   4039{
   4040	struct vega10_hwmgr *data = hwmgr->backend;
   4041	struct vega10_single_dpm_table *dpm_table =
   4042			&data->dpm_table.dcef_table;
   4043	struct phm_ppt_v2_information *table_info =
   4044			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4045	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk;
   4046	uint32_t idx;
   4047	struct PP_Clocks min_clocks = {0};
   4048	uint32_t i;
   4049	struct pp_display_clock_request clock_req;
   4050
   4051	if ((hwmgr->display_config->num_display > 1) &&
   4052	     !hwmgr->display_config->multi_monitor_in_sync &&
   4053	     !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	min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
   4059	min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
   4060	min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
   4061
   4062	for (i = 0; i < dpm_table->count; i++) {
   4063		if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock)
   4064			break;
   4065	}
   4066
   4067	if (i < dpm_table->count) {
   4068		clock_req.clock_type = amd_pp_dcef_clock;
   4069		clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10;
   4070		if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) {
   4071			smum_send_msg_to_smc_with_parameter(
   4072					hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
   4073					min_clocks.dcefClockInSR / 100,
   4074					NULL);
   4075		} else {
   4076			pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
   4077		}
   4078	} else {
   4079		pr_debug("Cannot find requested DCEFCLK!");
   4080	}
   4081
   4082	if (min_clocks.memoryClock != 0) {
   4083		idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock);
   4084		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx,
   4085						NULL);
   4086		data->dpm_table.mem_table.dpm_state.soft_min_level= idx;
   4087	}
   4088
   4089	return 0;
   4090}
   4091
   4092static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr)
   4093{
   4094	struct vega10_hwmgr *data = hwmgr->backend;
   4095
   4096	data->smc_state_table.gfx_boot_level =
   4097	data->smc_state_table.gfx_max_level =
   4098			vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
   4099	data->smc_state_table.mem_boot_level =
   4100	data->smc_state_table.mem_max_level =
   4101			vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
   4102
   4103	PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4104			"Failed to upload boot level to highest!",
   4105			return -1);
   4106
   4107	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
   4114static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr)
   4115{
   4116	struct vega10_hwmgr *data = hwmgr->backend;
   4117
   4118	data->smc_state_table.gfx_boot_level =
   4119	data->smc_state_table.gfx_max_level =
   4120			vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
   4121	data->smc_state_table.mem_boot_level =
   4122	data->smc_state_table.mem_max_level =
   4123			vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
   4124
   4125	PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4126			"Failed to upload boot level to highest!",
   4127			return -1);
   4128
   4129	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
   4137static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
   4138{
   4139	struct vega10_hwmgr *data = hwmgr->backend;
   4140
   4141	data->smc_state_table.gfx_boot_level =
   4142			vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
   4143	data->smc_state_table.gfx_max_level =
   4144			vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
   4145	data->smc_state_table.mem_boot_level =
   4146			vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
   4147	data->smc_state_table.mem_max_level =
   4148			vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
   4149
   4150	PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4151			"Failed to upload DPM Bootup Levels!",
   4152			return -1);
   4153
   4154	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
   4160static 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	struct phm_ppt_v2_information *table_info =
   4164			(struct phm_ppt_v2_information *)(hwmgr->pptable);
   4165
   4166	if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL &&
   4167		table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL &&
   4168		table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) {
   4169		*sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL;
   4170		*soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL;
   4171		*mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL;
   4172		hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk;
   4173		hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk;
   4174	}
   4175
   4176	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
   4177		*sclk_mask = 0;
   4178	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
   4179		*mclk_mask = 0;
   4180	} 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		if (hwmgr->pp_one_vf)
   4185			*sclk_mask = 4;
   4186		else
   4187			*sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
   4188		*soc_mask = table_info->vdd_dep_on_socclk->count - 1;
   4189		*mclk_mask = table_info->vdd_dep_on_mclk->count - 1;
   4190	}
   4191
   4192	return 0;
   4193}
   4194
   4195static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
   4196{
   4197	if (!hwmgr->not_vf)
   4198		return;
   4199
   4200	switch (mode) {
   4201	case AMD_FAN_CTRL_NONE:
   4202		vega10_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
   4203		break;
   4204	case AMD_FAN_CTRL_MANUAL:
   4205		if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
   4206			vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
   4207		break;
   4208	case AMD_FAN_CTRL_AUTO:
   4209		if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
   4210			vega10_fan_ctrl_start_smc_fan_control(hwmgr);
   4211		break;
   4212	default:
   4213		break;
   4214	}
   4215}
   4216
   4217static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
   4218		enum pp_clock_type type, uint32_t mask)
   4219{
   4220	struct vega10_hwmgr *data = hwmgr->backend;
   4221
   4222	switch (type) {
   4223	case PP_SCLK:
   4224		data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0;
   4225		data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0;
   4226
   4227		PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4228			"Failed to upload boot level to lowest!",
   4229			return -EINVAL);
   4230
   4231		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		data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0;
   4238		data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0;
   4239
   4240		PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4241			"Failed to upload boot level to lowest!",
   4242			return -EINVAL);
   4243
   4244		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		data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0;
   4252		data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0;
   4253
   4254		PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
   4255			"Failed to upload boot level to lowest!",
   4256			return -EINVAL);
   4257
   4258		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		pr_info("Setting DCEFCLK min/max dpm level is not supported!\n");
   4266		break;
   4267
   4268	case PP_PCIE:
   4269	default:
   4270		break;
   4271	}
   4272
   4273	return 0;
   4274}
   4275
   4276static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
   4277				enum amd_dpm_forced_level level)
   4278{
   4279	int ret = 0;
   4280	uint32_t sclk_mask = 0;
   4281	uint32_t mclk_mask = 0;
   4282	uint32_t soc_mask = 0;
   4283
   4284	if (hwmgr->pstate_sclk == 0)
   4285		vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
   4286
   4287	switch (level) {
   4288	case AMD_DPM_FORCED_LEVEL_HIGH:
   4289		ret = vega10_force_dpm_highest(hwmgr);
   4290		break;
   4291	case AMD_DPM_FORCED_LEVEL_LOW:
   4292		ret = vega10_force_dpm_lowest(hwmgr);
   4293		break;
   4294	case AMD_DPM_FORCED_LEVEL_AUTO:
   4295		ret = vega10_unforce_dpm_levels(hwmgr);
   4296		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		ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
   4302		if (ret)
   4303			return ret;
   4304		vega10_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
   4305		vega10_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
   4306		break;
   4307	case AMD_DPM_FORCED_LEVEL_MANUAL:
   4308	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
   4309	default:
   4310		break;
   4311	}
   4312
   4313	if (!hwmgr->not_vf)
   4314		return ret;
   4315
   4316	if (!ret) {
   4317		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		else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
   4320			vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO);
   4321	}
   4322
   4323	return ret;
   4324}
   4325
   4326static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
   4327{
   4328	struct vega10_hwmgr *data = hwmgr->backend;
   4329
   4330	if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
   4331		return AMD_FAN_CTRL_MANUAL;
   4332	else
   4333		return AMD_FAN_CTRL_AUTO;
   4334}
   4335
   4336static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr,
   4337		struct amd_pp_simple_clock_info *info)
   4338{
   4339	struct phm_ppt_v2_information *table_info =
   4340			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4341	struct phm_clock_and_voltage_limits *max_limits =
   4342			&table_info->max_clock_voltage_on_ac;
   4343
   4344	info->engine_max_clock = max_limits->sclk;
   4345	info->memory_max_clock = max_limits->mclk;
   4346
   4347	return 0;
   4348}
   4349
   4350static void vega10_get_sclks(struct pp_hwmgr *hwmgr,
   4351		struct pp_clock_levels_with_latency *clocks)
   4352{
   4353	struct phm_ppt_v2_information *table_info =
   4354			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4355	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   4356			table_info->vdd_dep_on_sclk;
   4357	uint32_t i;
   4358
   4359	clocks->num_levels = 0;
   4360	for (i = 0; i < dep_table->count; i++) {
   4361		if (dep_table->entries[i].clk) {
   4362			clocks->data[clocks->num_levels].clocks_in_khz =
   4363					dep_table->entries[i].clk * 10;
   4364			clocks->num_levels++;
   4365		}
   4366	}
   4367
   4368}
   4369
   4370static void vega10_get_memclocks(struct pp_hwmgr *hwmgr,
   4371		struct pp_clock_levels_with_latency *clocks)
   4372{
   4373	struct phm_ppt_v2_information *table_info =
   4374			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4375	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   4376			table_info->vdd_dep_on_mclk;
   4377	struct vega10_hwmgr *data = hwmgr->backend;
   4378	uint32_t j = 0;
   4379	uint32_t i;
   4380
   4381	for (i = 0; i < dep_table->count; i++) {
   4382		if (dep_table->entries[i].clk) {
   4383
   4384			clocks->data[j].clocks_in_khz =
   4385						dep_table->entries[i].clk * 10;
   4386			data->mclk_latency_table.entries[j].frequency =
   4387							dep_table->entries[i].clk;
   4388			clocks->data[j].latency_in_us =
   4389				data->mclk_latency_table.entries[j].latency = 25;
   4390			j++;
   4391		}
   4392	}
   4393	clocks->num_levels = data->mclk_latency_table.count = j;
   4394}
   4395
   4396static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr,
   4397		struct pp_clock_levels_with_latency *clocks)
   4398{
   4399	struct phm_ppt_v2_information *table_info =
   4400			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4401	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   4402			table_info->vdd_dep_on_dcefclk;
   4403	uint32_t i;
   4404
   4405	for (i = 0; i < dep_table->count; i++) {
   4406		clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10;
   4407		clocks->data[i].latency_in_us = 0;
   4408		clocks->num_levels++;
   4409	}
   4410}
   4411
   4412static void vega10_get_socclocks(struct pp_hwmgr *hwmgr,
   4413		struct pp_clock_levels_with_latency *clocks)
   4414{
   4415	struct phm_ppt_v2_information *table_info =
   4416			(struct phm_ppt_v2_information *)hwmgr->pptable;
   4417	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
   4418			table_info->vdd_dep_on_socclk;
   4419	uint32_t i;
   4420
   4421	for (i = 0; i < dep_table->count; i++) {
   4422		clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10;
   4423		clocks->data[i].latency_in_us = 0;
   4424		clocks->num_levels++;
   4425	}
   4426}
   4427
   4428static 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	switch (type) {
   4433	case amd_pp_sys_clock:
   4434		vega10_get_sclks(hwmgr, clocks);
   4435		break;
   4436	case amd_pp_mem_clock:
   4437		vega10_get_memclocks(hwmgr, clocks);
   4438		break;
   4439	case amd_pp_dcef_clock:
   4440		vega10_get_dcefclocks(hwmgr, clocks);
   4441		break;
   4442	case amd_pp_soc_clock:
   4443		vega10_get_socclocks(hwmgr, clocks);
   4444		break;
   4445	default:
   4446		return -1;
   4447	}
   4448
   4449	return 0;
   4450}
   4451
   4452static 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	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	switch (type) {
   4462	case amd_pp_mem_clock:
   4463		dep_table = table_info->vdd_dep_on_mclk;
   4464		break;
   4465	case amd_pp_dcef_clock:
   4466		dep_table = table_info->vdd_dep_on_dcefclk;
   4467		break;
   4468	case amd_pp_disp_clock:
   4469		dep_table = table_info->vdd_dep_on_dispclk;
   4470		break;
   4471	case amd_pp_pixel_clock:
   4472		dep_table = table_info->vdd_dep_on_pixclk;
   4473		break;
   4474	case amd_pp_phy_clock:
   4475		dep_table = table_info->vdd_dep_on_phyclk;
   4476		break;
   4477	default:
   4478		return -1;
   4479	}
   4480
   4481	for (i = 0; i < dep_table->count; i++) {
   4482		clocks->data[i].clocks_in_khz = dep_table->entries[i].clk  * 10;
   4483		clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table->
   4484				entries[dep_table->entries[i].vddInd].us_vdd);
   4485		clocks->num_levels++;
   4486	}
   4487
   4488	if (i < dep_table->count)
   4489		return -1;
   4490
   4491	return 0;
   4492}
   4493
   4494static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
   4495							void *clock_range)
   4496{
   4497	struct vega10_hwmgr *data = hwmgr->backend;
   4498	struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range;
   4499	Watermarks_t *table = &(data->smc_state_table.water_marks_table);
   4500
   4501	if (!data->registry_data.disable_water_mark) {
   4502		smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
   4503		data->water_marks_bitmap = WaterMarksExist;
   4504	}
   4505
   4506	return 0;
   4507}
   4508
   4509static 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	int ret = 0;
   4549	int size = 0;
   4550
   4551	phm_get_sysfs_buf(&buf, &size);
   4552
   4553	ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
   4554	PP_ASSERT_WITH_CODE(!ret,
   4555			"[EnableAllSmuFeatures] Failed to get enabled smc features!",
   4556			return ret);
   4557
   4558	size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
   4559	size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
   4560				output_title[0],
   4561				output_title[1],
   4562				output_title[2]);
   4563	for (i = 0; i < GNLD_FEATURES_MAX; i++) {
   4564		size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
   4565					ppfeature_name[i],
   4566					1ULL << i,
   4567					(features_enabled & (1ULL << i)) ? "Y" : "N");
   4568	}
   4569
   4570	return size;
   4571}
   4572
   4573static 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	int ret = 0;
   4579
   4580	if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
   4581		return -EINVAL;
   4582
   4583	ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
   4584	if (ret)
   4585		return ret;
   4586
   4587	features_to_disable =
   4588		features_enabled & ~new_ppfeature_masks;
   4589	features_to_enable =
   4590		~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	if (features_to_disable) {
   4596		ret = vega10_enable_smc_features(hwmgr, false, features_to_disable);
   4597		if (ret)
   4598			return ret;
   4599	}
   4600
   4601	if (features_to_enable) {
   4602		ret = vega10_enable_smc_features(hwmgr, true, features_to_enable);
   4603		if (ret)
   4604			return ret;
   4605	}
   4606
   4607	return 0;
   4608}
   4609
   4610static int vega10_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr)
   4611{
   4612	struct amdgpu_device *adev = hwmgr->adev;
   4613
   4614	return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
   4615		PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
   4616		>> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
   4617}
   4618
   4619static int vega10_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
   4620{
   4621	struct amdgpu_device *adev = hwmgr->adev;
   4622
   4623	return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
   4624		PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
   4625		>> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
   4626}
   4627
   4628static int vega10_emit_clock_levels(struct pp_hwmgr *hwmgr,
   4629				    enum pp_clock_type type, char *buf, int *offset)
   4630{
   4631	struct vega10_hwmgr *data = hwmgr->backend;
   4632	struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
   4633	struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
   4634	struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
   4635	struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
   4636	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	PPTable_t *pptable = &(data->smc_state_table.pp_table);
   4639
   4640	uint32_t i, now, count = 0;
   4641	int ret = 0;
   4642
   4643	switch (type) {
   4644	case PP_SCLK:
   4645		if (data->registry_data.sclk_dpm_key_disabled)
   4646			return -EOPNOTSUPP;
   4647
   4648		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now);
   4649		if (unlikely(ret != 0))
   4650			return ret;
   4651
   4652		if (hwmgr->pp_one_vf &&
   4653		    (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK))
   4654			count = 5;
   4655		else
   4656			count = sclk_table->count;
   4657		for (i = 0; i < count; i++)
   4658			*offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
   4659					i, sclk_table->dpm_levels[i].value / 100,
   4660					(i == now) ? "*" : "");
   4661		break;
   4662	case PP_MCLK:
   4663		if (data->registry_data.mclk_dpm_key_disabled)
   4664			return -EOPNOTSUPP;
   4665
   4666		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now);
   4667		if (unlikely(ret != 0))
   4668			return ret;
   4669
   4670		for (i = 0; i < mclk_table->count; i++)
   4671			*offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
   4672					i, mclk_table->dpm_levels[i].value / 100,
   4673					(i == now) ? "*" : "");
   4674		break;
   4675	case PP_SOCCLK:
   4676		if (data->registry_data.socclk_dpm_key_disabled)
   4677			return -EOPNOTSUPP;
   4678
   4679		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now);
   4680		if (unlikely(ret != 0))
   4681			return ret;
   4682
   4683		for (i = 0; i < soc_table->count; i++)
   4684			*offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
   4685					i, soc_table->dpm_levels[i].value / 100,
   4686					(i == now) ? "*" : "");
   4687		break;
   4688	case PP_DCEFCLK:
   4689		if (data->registry_data.dcefclk_dpm_key_disabled)
   4690			return -EOPNOTSUPP;
   4691
   4692		ret = smum_send_msg_to_smc_with_parameter(hwmgr,
   4693							  PPSMC_MSG_GetClockFreqMHz,
   4694							  CLK_DCEFCLK, &now);
   4695		if (unlikely(ret != 0))
   4696			return ret;
   4697
   4698		for (i = 0; i < dcef_table->count; i++)
   4699			*offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
   4700					i, dcef_table->dpm_levels[i].value / 100,
   4701					(dcef_table->dpm_levels[i].value / 100 == now) ?
   4702					"*" : "");
   4703		break;
   4704	case PP_PCIE:
   4705		current_gen_speed =
   4706			vega10_get_current_pcie_link_speed_level(hwmgr);
   4707		current_lane_width =
   4708			vega10_get_current_pcie_link_width_level(hwmgr);
   4709		for (i = 0; i < NUM_LINK_LEVELS; i++) {
   4710			gen_speed = pptable->PcieGenSpeed[i];
   4711			lane_width = pptable->PcieLaneCount[i];
   4712
   4713			*offset += sysfs_emit_at(buf, *offset, "%d: %s %s %s\n", i,
   4714					(gen_speed == 0) ? "2.5GT/s," :
   4715					(gen_speed == 1) ? "5.0GT/s," :
   4716					(gen_speed == 2) ? "8.0GT/s," :
   4717					(gen_speed == 3) ? "16.0GT/s," : "",
   4718					(lane_width == 1) ? "x1" :
   4719					(lane_width == 2) ? "x2" :
   4720					(lane_width == 3) ? "x4" :
   4721					(lane_width == 4) ? "x8" :
   4722					(lane_width == 5) ? "x12" :
   4723					(lane_width == 6) ? "x16" : "",
   4724					(current_gen_speed == gen_speed) &&
   4725					(current_lane_width == lane_width) ?
   4726					"*" : "");
   4727		}
   4728		break;
   4729
   4730	case OD_SCLK:
   4731		if (!hwmgr->od_enabled)
   4732			return -EOPNOTSUPP;
   4733
   4734		*offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_SCLK");
   4735		podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
   4736		for (i = 0; i < podn_vdd_dep->count; i++)
   4737			*offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n",
   4738						 i, podn_vdd_dep->entries[i].clk / 100,
   4739						 podn_vdd_dep->entries[i].vddc);
   4740		break;
   4741	case OD_MCLK:
   4742		if (!hwmgr->od_enabled)
   4743			return -EOPNOTSUPP;
   4744
   4745		*offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_MCLK");
   4746		podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
   4747		for (i = 0; i < podn_vdd_dep->count; i++)
   4748			*offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n",
   4749						 i, podn_vdd_dep->entries[i].clk/100,
   4750						 podn_vdd_dep->entries[i].vddc);
   4751		break;
   4752	case OD_RANGE:
   4753		if (!hwmgr->od_enabled)
   4754			return -EOPNOTSUPP;
   4755
   4756		*offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_RANGE");
   4757		*offset += sysfs_emit_at(buf, *offset, "SCLK: %7uMHz %10uMHz\n",
   4758					 data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
   4759				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
   4760		*offset += sysfs_emit_at(buf, *offset, "MCLK: %7uMHz %10uMHz\n",
   4761					 data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
   4762				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
   4763		*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		break;
   4767	default:
   4768		ret = -ENOENT;
   4769		break;
   4770	}
   4771	return ret;
   4772}
   4773
   4774static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
   4775		enum pp_clock_type type, char *buf)
   4776{
   4777	struct vega10_hwmgr *data = hwmgr->backend;
   4778	struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
   4779	struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
   4780	struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
   4781	struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
   4782	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	PPTable_t *pptable = &(data->smc_state_table.pp_table);
   4785
   4786	int i, now, size = 0, count = 0;
   4787
   4788	switch (type) {
   4789	case PP_SCLK:
   4790		if (data->registry_data.sclk_dpm_key_disabled)
   4791			break;
   4792
   4793		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now);
   4794
   4795		if (hwmgr->pp_one_vf &&
   4796		    (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK))
   4797			count = 5;
   4798		else
   4799			count = sclk_table->count;
   4800		for (i = 0; i < count; i++)
   4801			size += sprintf(buf + size, "%d: %uMhz %s\n",
   4802					i, sclk_table->dpm_levels[i].value / 100,
   4803					(i == now) ? "*" : "");
   4804		break;
   4805	case PP_MCLK:
   4806		if (data->registry_data.mclk_dpm_key_disabled)
   4807			break;
   4808
   4809		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now);
   4810
   4811		for (i = 0; i < mclk_table->count; i++)
   4812			size += sprintf(buf + size, "%d: %uMhz %s\n",
   4813					i, mclk_table->dpm_levels[i].value / 100,
   4814					(i == now) ? "*" : "");
   4815		break;
   4816	case PP_SOCCLK:
   4817		if (data->registry_data.socclk_dpm_key_disabled)
   4818			break;
   4819
   4820		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now);
   4821
   4822		for (i = 0; i < soc_table->count; i++)
   4823			size += sprintf(buf + size, "%d: %uMhz %s\n",
   4824					i, soc_table->dpm_levels[i].value / 100,
   4825					(i == now) ? "*" : "");
   4826		break;
   4827	case PP_DCEFCLK:
   4828		if (data->registry_data.dcefclk_dpm_key_disabled)
   4829			break;
   4830
   4831		smum_send_msg_to_smc_with_parameter(hwmgr,
   4832				PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now);
   4833
   4834		for (i = 0; i < dcef_table->count; i++)
   4835			size += sprintf(buf + size, "%d: %uMhz %s\n",
   4836					i, dcef_table->dpm_levels[i].value / 100,
   4837					(dcef_table->dpm_levels[i].value / 100 == now) ?
   4838					"*" : "");
   4839		break;
   4840	case PP_PCIE:
   4841		current_gen_speed =
   4842			vega10_get_current_pcie_link_speed_level(hwmgr);
   4843		current_lane_width =
   4844			vega10_get_current_pcie_link_width_level(hwmgr);
   4845		for (i = 0; i < NUM_LINK_LEVELS; i++) {
   4846			gen_speed = pptable->PcieGenSpeed[i];
   4847			lane_width = pptable->PcieLaneCount[i];
   4848
   4849			size += sprintf(buf + size, "%d: %s %s %s\n", i,
   4850					(gen_speed == 0) ? "2.5GT/s," :
   4851					(gen_speed == 1) ? "5.0GT/s," :
   4852					(gen_speed == 2) ? "8.0GT/s," :
   4853					(gen_speed == 3) ? "16.0GT/s," : "",
   4854					(lane_width == 1) ? "x1" :
   4855					(lane_width == 2) ? "x2" :
   4856					(lane_width == 3) ? "x4" :
   4857					(lane_width == 4) ? "x8" :
   4858					(lane_width == 5) ? "x12" :
   4859					(lane_width == 6) ? "x16" : "",
   4860					(current_gen_speed == gen_speed) &&
   4861					(current_lane_width == lane_width) ?
   4862					"*" : "");
   4863		}
   4864		break;
   4865
   4866	case OD_SCLK:
   4867		if (hwmgr->od_enabled) {
   4868			size += sprintf(buf + size, "%s:\n", "OD_SCLK");
   4869			podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
   4870			for (i = 0; i < podn_vdd_dep->count; i++)
   4871				size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
   4872					i, podn_vdd_dep->entries[i].clk / 100,
   4873						podn_vdd_dep->entries[i].vddc);
   4874		}
   4875		break;
   4876	case OD_MCLK:
   4877		if (hwmgr->od_enabled) {
   4878			size += sprintf(buf + size, "%s:\n", "OD_MCLK");
   4879			podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
   4880			for (i = 0; i < podn_vdd_dep->count; i++)
   4881				size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
   4882					i, podn_vdd_dep->entries[i].clk/100,
   4883						podn_vdd_dep->entries[i].vddc);
   4884		}
   4885		break;
   4886	case OD_RANGE:
   4887		if (hwmgr->od_enabled) {
   4888			size += sprintf(buf + size, "%s:\n", "OD_RANGE");
   4889			size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
   4890				data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
   4891				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
   4892			size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
   4893				data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
   4894				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
   4895			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	return size;
   4904}
   4905
   4906static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
   4907{
   4908	struct vega10_hwmgr *data = hwmgr->backend;
   4909	Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
   4910	int result = 0;
   4911
   4912	if ((data->water_marks_bitmap & WaterMarksExist) &&
   4913			!(data->water_marks_bitmap & WaterMarksLoaded)) {
   4914		result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false);
   4915		PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL);
   4916		data->water_marks_bitmap |= WaterMarksLoaded;
   4917	}
   4918
   4919	if (data->water_marks_bitmap & WaterMarksLoaded) {
   4920		smum_send_msg_to_smc_with_parameter(hwmgr,
   4921			PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display,
   4922			NULL);
   4923	}
   4924
   4925	return result;
   4926}
   4927
   4928static int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
   4929{
   4930	struct vega10_hwmgr *data = hwmgr->backend;
   4931
   4932	if (data->smu_features[GNLD_DPM_UVD].supported) {
   4933		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		data->smu_features[GNLD_DPM_UVD].enabled = enable;
   4939	}
   4940	return 0;
   4941}
   4942
   4943static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
   4944{
   4945	struct vega10_hwmgr *data = hwmgr->backend;
   4946
   4947	data->vce_power_gated = bgate;
   4948	vega10_enable_disable_vce_dpm(hwmgr, !bgate);
   4949}
   4950
   4951static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
   4952{
   4953	struct vega10_hwmgr *data = hwmgr->backend;
   4954
   4955	data->uvd_power_gated = bgate;
   4956	vega10_enable_disable_uvd_dpm(hwmgr, !bgate);
   4957}
   4958
   4959static inline bool vega10_are_power_levels_equal(
   4960				const struct vega10_performance_level *pl1,
   4961				const struct vega10_performance_level *pl2)
   4962{
   4963	return ((pl1->soc_clock == pl2->soc_clock) &&
   4964			(pl1->gfx_clock == pl2->gfx_clock) &&
   4965			(pl1->mem_clock == pl2->mem_clock));
   4966}
   4967
   4968static 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	if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
   4977		return -EINVAL;
   4978
   4979	vega10_psa = cast_const_phw_vega10_power_state(pstate1);
   4980	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	if (vega10_psa->performance_level_count != vega10_psb->performance_level_count) {
   4986		*equal = false;
   4987		return 0;
   4988	}
   4989
   4990	for (i = 0; i < vega10_psa->performance_level_count; i++) {
   4991		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			*equal = false;
   4997			return 0;
   4998		}
   4999	}
   5000
   5001	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
   5002	*equal = ((vega10_psa->uvd_clks.vclk == vega10_psb->uvd_clks.vclk) &&
   5003		  (vega10_psa->uvd_clks.dclk == vega10_psb->uvd_clks.dclk));
   5004	*equal &= ((vega10_psa->vce_clks.evclk == vega10_psb->vce_clks.evclk) &&
   5005		   (vega10_psa->vce_clks.ecclk == vega10_psb->vce_clks.ecclk));
   5006	*equal &= (vega10_psa->sclk_threshold == vega10_psb->sclk_threshold);
   5007
   5008	return 0;
   5009}
   5010
   5011static bool
   5012vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
   5013{
   5014	struct vega10_hwmgr *data = hwmgr->backend;
   5015	bool is_update_required = false;
   5016
   5017	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
   5018		is_update_required = true;
   5019
   5020	if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) {
   5021		if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr)
   5022			is_update_required = true;
   5023	}
   5024
   5025	return is_update_required;
   5026}
   5027
   5028static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
   5029{
   5030	int tmp_result, result = 0;
   5031
   5032	if (!hwmgr->not_vf)
   5033		return 0;
   5034
   5035	if (PP_CAP(PHM_PlatformCaps_ThermalController))
   5036		vega10_disable_thermal_protection(hwmgr);
   5037
   5038	tmp_result = vega10_disable_power_containment(hwmgr);
   5039	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5040			"Failed to disable power containment!", result = tmp_result);
   5041
   5042	tmp_result = vega10_disable_didt_config(hwmgr);
   5043	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5044			"Failed to disable didt config!", result = tmp_result);
   5045
   5046	tmp_result = vega10_avfs_enable(hwmgr, false);
   5047	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5048			"Failed to disable AVFS!", result = tmp_result);
   5049
   5050	tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES);
   5051	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5052			"Failed to stop DPM!", result = tmp_result);
   5053
   5054	tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr);
   5055	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5056			"Failed to disable deep sleep!", result = tmp_result);
   5057
   5058	tmp_result = vega10_disable_ulv(hwmgr);
   5059	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5060			"Failed to disable ulv!", result = tmp_result);
   5061
   5062	tmp_result =  vega10_acg_disable(hwmgr);
   5063	PP_ASSERT_WITH_CODE((tmp_result == 0),
   5064			"Failed to disable acg!", result = tmp_result);
   5065
   5066	vega10_enable_disable_PCC_limit_feature(hwmgr, false);
   5067	return result;
   5068}
   5069
   5070static int vega10_power_off_asic(struct pp_hwmgr *hwmgr)
   5071{
   5072	struct vega10_hwmgr *data = hwmgr->backend;
   5073	int result;
   5074
   5075	result = vega10_disable_dpm_tasks(hwmgr);
   5076	PP_ASSERT_WITH_CODE((0 == result),
   5077			"[disable_dpm_tasks] Failed to disable DPM!",
   5078			);
   5079	data->water_marks_bitmap &= ~(WaterMarksLoaded);
   5080
   5081	return result;
   5082}
   5083
   5084static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
   5085{
   5086	struct vega10_hwmgr *data = hwmgr->backend;
   5087	struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
   5088	struct vega10_single_dpm_table *golden_sclk_table =
   5089			&(data->golden_dpm_table.gfx_table);
   5090	int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
   5091	int golden_value = golden_sclk_table->dpm_levels
   5092			[golden_sclk_table->count - 1].value;
   5093
   5094	value -= golden_value;
   5095	value = DIV_ROUND_UP(value * 100, golden_value);
   5096
   5097	return value;
   5098}
   5099
   5100static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
   5101{
   5102	struct vega10_hwmgr *data = hwmgr->backend;
   5103	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	ps = hwmgr->request_ps;
   5109
   5110	if (ps == NULL)
   5111		return -EINVAL;
   5112
   5113	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   5114
   5115	vega10_ps->performance_levels
   5116	[vega10_ps->performance_level_count - 1].gfx_clock =
   5117			golden_sclk_table->dpm_levels
   5118			[golden_sclk_table->count - 1].value *
   5119			value / 100 +
   5120			golden_sclk_table->dpm_levels
   5121			[golden_sclk_table->count - 1].value;
   5122
   5123	if (vega10_ps->performance_levels
   5124			[vega10_ps->performance_level_count - 1].gfx_clock >
   5125			hwmgr->platform_descriptor.overdriveLimit.engineClock) {
   5126		vega10_ps->performance_levels
   5127		[vega10_ps->performance_level_count - 1].gfx_clock =
   5128				hwmgr->platform_descriptor.overdriveLimit.engineClock;
   5129		pr_warn("max sclk supported by vbios is %d\n",
   5130				hwmgr->platform_descriptor.overdriveLimit.engineClock);
   5131	}
   5132	return 0;
   5133}
   5134
   5135static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)
   5136{
   5137	struct vega10_hwmgr *data = hwmgr->backend;
   5138	struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
   5139	struct vega10_single_dpm_table *golden_mclk_table =
   5140			&(data->golden_dpm_table.mem_table);
   5141	int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
   5142	int golden_value = golden_mclk_table->dpm_levels
   5143			[golden_mclk_table->count - 1].value;
   5144
   5145	value -= golden_value;
   5146	value = DIV_ROUND_UP(value * 100, golden_value);
   5147
   5148	return value;
   5149}
   5150
   5151static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
   5152{
   5153	struct vega10_hwmgr *data = hwmgr->backend;
   5154	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	ps = hwmgr->request_ps;
   5160
   5161	if (ps == NULL)
   5162		return -EINVAL;
   5163
   5164	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   5165
   5166	vega10_ps->performance_levels
   5167	[vega10_ps->performance_level_count - 1].mem_clock =
   5168			golden_mclk_table->dpm_levels
   5169			[golden_mclk_table->count - 1].value *
   5170			value / 100 +
   5171			golden_mclk_table->dpm_levels
   5172			[golden_mclk_table->count - 1].value;
   5173
   5174	if (vega10_ps->performance_levels
   5175			[vega10_ps->performance_level_count - 1].mem_clock >
   5176			hwmgr->platform_descriptor.overdriveLimit.memoryClock) {
   5177		vega10_ps->performance_levels
   5178		[vega10_ps->performance_level_count - 1].mem_clock =
   5179				hwmgr->platform_descriptor.overdriveLimit.memoryClock;
   5180		pr_warn("max mclk supported by vbios is %d\n",
   5181				hwmgr->platform_descriptor.overdriveLimit.memoryClock);
   5182	}
   5183
   5184	return 0;
   5185}
   5186
   5187static 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	smum_send_msg_to_smc_with_parameter(hwmgr,
   5195					PPSMC_MSG_SetSystemVirtualDramAddrHigh,
   5196					virtual_addr_hi,
   5197					NULL);
   5198	smum_send_msg_to_smc_with_parameter(hwmgr,
   5199					PPSMC_MSG_SetSystemVirtualDramAddrLow,
   5200					virtual_addr_low,
   5201					NULL);
   5202	smum_send_msg_to_smc_with_parameter(hwmgr,
   5203					PPSMC_MSG_DramLogSetDramAddrHigh,
   5204					mc_addr_hi,
   5205					NULL);
   5206
   5207	smum_send_msg_to_smc_with_parameter(hwmgr,
   5208					PPSMC_MSG_DramLogSetDramAddrLow,
   5209					mc_addr_low,
   5210					NULL);
   5211
   5212	smum_send_msg_to_smc_with_parameter(hwmgr,
   5213					PPSMC_MSG_DramLogSetDramSize,
   5214					size,
   5215					NULL);
   5216	return 0;
   5217}
   5218
   5219static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
   5220		struct PP_TemperatureRange *thermal_data)
   5221{
   5222	struct vega10_hwmgr *data = hwmgr->backend;
   5223	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
   5224
   5225	memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
   5226
   5227	thermal_data->max = pp_table->TedgeLimit *
   5228		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5229	thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
   5230		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5231	thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
   5232		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5233	thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
   5234		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5235	thermal_data->mem_crit_max = pp_table->ThbmLimit *
   5236		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5237	thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
   5238		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
   5239
   5240	return 0;
   5241}
   5242
   5243static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
   5244{
   5245	struct vega10_hwmgr *data = hwmgr->backend;
   5246	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	if (!buf)
   5262		return -EINVAL;
   5263
   5264	phm_get_sysfs_buf(&buf, &size);
   5265
   5266	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	for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++)
   5270		size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n",
   5271			i, amdgpu_pp_profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
   5272			profile_mode_setting[i][0], profile_mode_setting[i][1],
   5273			profile_mode_setting[i][2], profile_mode_setting[i][3]);
   5274
   5275	size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n", i,
   5276			amdgpu_pp_profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
   5277			data->custom_profile_mode[0], data->custom_profile_mode[1],
   5278			data->custom_profile_mode[2], data->custom_profile_mode[3]);
   5279	return size;
   5280}
   5281
   5282static bool vega10_get_power_profile_mode_quirks(struct pp_hwmgr *hwmgr)
   5283{
   5284	struct amdgpu_device *adev = hwmgr->adev;
   5285
   5286	return (adev->pdev->device == 0x6860);
   5287}
   5288
   5289static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
   5290{
   5291	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	uint32_t power_profile_mode = input[size];
   5297
   5298	if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
   5299		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		if (size == 0) {
   5307			if (data->custom_profile_mode[0] != 0)
   5308				goto out;
   5309			else
   5310				return -EINVAL;
   5311		}
   5312
   5313		data->custom_profile_mode[0] = busy_set_point = input[0];
   5314		data->custom_profile_mode[1] = FPS = input[1];
   5315		data->custom_profile_mode[2] = use_rlc_busy = input[2];
   5316		data->custom_profile_mode[3] = min_active_level = input[3];
   5317		smum_send_msg_to_smc_with_parameter(hwmgr,
   5318					PPSMC_MSG_SetCustomGfxDpmParameters,
   5319					busy_set_point | FPS<<8 |
   5320					use_rlc_busy << 16 | min_active_level<<24,
   5321					NULL);
   5322	}
   5323
   5324out:
   5325	if (vega10_get_power_profile_mode_quirks(hwmgr))
   5326		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
   5327						1 << power_profile_mode,
   5328						NULL);
   5329	else
   5330		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
   5331						(!power_profile_mode) ? 0 : 1 << (power_profile_mode - 1),
   5332						NULL);
   5333
   5334	hwmgr->power_profile_mode = power_profile_mode;
   5335
   5336	return 0;
   5337}
   5338
   5339
   5340static 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	struct vega10_hwmgr *data = hwmgr->backend;
   5346	struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
   5347	struct vega10_single_dpm_table *golden_table;
   5348
   5349	if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) {
   5350		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	if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
   5355		golden_table = &(data->golden_dpm_table.gfx_table);
   5356		if (golden_table->dpm_levels[0].value > clk ||
   5357			hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
   5358			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	} else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
   5364		golden_table = &(data->golden_dpm_table.mem_table);
   5365		if (golden_table->dpm_levels[0].value > clk ||
   5366			hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
   5367			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
   5379static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
   5380{
   5381	struct vega10_hwmgr *data = hwmgr->backend;
   5382	struct pp_power_state *ps = hwmgr->request_ps;
   5383	struct vega10_power_state *vega10_ps;
   5384	struct vega10_single_dpm_table *gfx_dpm_table =
   5385		&data->dpm_table.gfx_table;
   5386	struct vega10_single_dpm_table *soc_dpm_table =
   5387		&data->dpm_table.soc_table;
   5388	struct vega10_single_dpm_table *mem_dpm_table =
   5389		&data->dpm_table.mem_table;
   5390	int max_level;
   5391
   5392	if (!ps)
   5393		return;
   5394
   5395	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   5396	max_level = vega10_ps->performance_level_count - 1;
   5397
   5398	if (vega10_ps->performance_levels[max_level].gfx_clock !=
   5399	    gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value)
   5400		vega10_ps->performance_levels[max_level].gfx_clock =
   5401			gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value;
   5402
   5403	if (vega10_ps->performance_levels[max_level].soc_clock !=
   5404	    soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value)
   5405		vega10_ps->performance_levels[max_level].soc_clock =
   5406			soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value;
   5407
   5408	if (vega10_ps->performance_levels[max_level].mem_clock !=
   5409	    mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value)
   5410		vega10_ps->performance_levels[max_level].mem_clock =
   5411			mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value;
   5412
   5413	if (!hwmgr->ps)
   5414		return;
   5415
   5416	ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1));
   5417	vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
   5418	max_level = vega10_ps->performance_level_count - 1;
   5419
   5420	if (vega10_ps->performance_levels[max_level].gfx_clock !=
   5421	    gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value)
   5422		vega10_ps->performance_levels[max_level].gfx_clock =
   5423			gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value;
   5424
   5425	if (vega10_ps->performance_levels[max_level].soc_clock !=
   5426	    soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value)
   5427		vega10_ps->performance_levels[max_level].soc_clock =
   5428			soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value;
   5429
   5430	if (vega10_ps->performance_levels[max_level].mem_clock !=
   5431	    mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value)
   5432		vega10_ps->performance_levels[max_level].mem_clock =
   5433			mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value;
   5434}
   5435
   5436static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr,
   5437						enum PP_OD_DPM_TABLE_COMMAND type)
   5438{
   5439	struct vega10_hwmgr *data = hwmgr->backend;
   5440	struct phm_ppt_v2_information *table_info = hwmgr->pptable;
   5441	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk;
   5442	struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table;
   5443
   5444	struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk =
   5445							&data->odn_dpm_table.vdd_dep_on_socclk;
   5446	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	if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
   5452		podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
   5453		for (i = 0; i < podn_vdd_dep->count; i++)
   5454			od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
   5455	} else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
   5456		podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
   5457		for (i = 0; i < dpm_table->count; i++) {
   5458			for (j = 0; j < od_vddc_lookup_table->count; j++) {
   5459				if (od_vddc_lookup_table->entries[j].us_vdd >
   5460					podn_vdd_dep->entries[i].vddc)
   5461					break;
   5462			}
   5463			if (j == od_vddc_lookup_table->count) {
   5464				j = od_vddc_lookup_table->count - 1;
   5465				od_vddc_lookup_table->entries[j].us_vdd =
   5466					podn_vdd_dep->entries[i].vddc;
   5467				data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
   5468			}
   5469			podn_vdd_dep->entries[i].vddInd = j;
   5470		}
   5471		dpm_table = &data->dpm_table.soc_table;
   5472		for (i = 0; i < dep_table->count; i++) {
   5473			if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd &&
   5474					dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) {
   5475				data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
   5476				for (; (i < dep_table->count) &&
   5477				       (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) {
   5478					podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk;
   5479					dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk;
   5480				}
   5481				break;
   5482			} else {
   5483				dpm_table->dpm_levels[i].value = dep_table->entries[i].clk;
   5484				podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc;
   5485				podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd;
   5486				podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk;
   5487			}
   5488		}
   5489		if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk <
   5490					podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) {
   5491			data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
   5492			podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk =
   5493				podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk;
   5494			dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value =
   5495				podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk;
   5496		}
   5497		if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd <
   5498					podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) {
   5499			data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
   5500			podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd =
   5501				podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd;
   5502		}
   5503	}
   5504	vega10_odn_update_power_state(hwmgr);
   5505}
   5506
   5507static 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	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	PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
   5521				return -EINVAL);
   5522
   5523	if (!hwmgr->od_enabled) {
   5524		pr_info("OverDrive feature not enabled\n");
   5525		return -EINVAL;
   5526	}
   5527
   5528	if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
   5529		dpm_table = &data->dpm_table.gfx_table;
   5530		podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk;
   5531		data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
   5532	} else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
   5533		dpm_table = &data->dpm_table.mem_table;
   5534		podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk;
   5535		data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
   5536	} else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
   5537		memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table));
   5538		vega10_odn_initial_default_setting(hwmgr);
   5539		vega10_odn_update_power_state(hwmgr);
   5540		/* force to update all clock tables */
   5541		data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK |
   5542					      DPMTABLE_UPDATE_MCLK |
   5543					      DPMTABLE_UPDATE_SOCCLK;
   5544		return 0;
   5545	} else if (PP_OD_COMMIT_DPM_TABLE == type) {
   5546		vega10_check_dpm_table_updated(hwmgr);
   5547		return 0;
   5548	} else {
   5549		return -EINVAL;
   5550	}
   5551
   5552	for (i = 0; i < size; i += 3) {
   5553		if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) {
   5554			pr_info("invalid clock voltage input\n");
   5555			return 0;
   5556		}
   5557		input_level = input[i];
   5558		input_clk = input[i+1] * 100;
   5559		input_vol = input[i+2];
   5560
   5561		if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
   5562			dpm_table->dpm_levels[input_level].value = input_clk;
   5563			podn_vdd_dep_table->entries[input_level].clk = input_clk;
   5564			podn_vdd_dep_table->entries[input_level].vddc = input_vol;
   5565		} else {
   5566			return -EINVAL;
   5567		}
   5568	}
   5569	vega10_odn_update_soc_table(hwmgr, type);
   5570	return 0;
   5571}
   5572
   5573static 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	switch (mp1_state) {
   5580	case PP_MP1_STATE_UNLOAD:
   5581		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	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
   5597static 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	if (level == NULL || hwmgr == NULL || state == NULL)
   5605		return -EINVAL;
   5606
   5607	vega10_ps = cast_const_phw_vega10_power_state(state);
   5608
   5609	i = index > vega10_ps->performance_level_count - 1 ?
   5610			vega10_ps->performance_level_count - 1 : index;
   5611
   5612	level->coreClock = vega10_ps->performance_levels[i].gfx_clock;
   5613	level->memory_clock = vega10_ps->performance_levels[i].mem_clock;
   5614
   5615	return 0;
   5616}
   5617
   5618static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable)
   5619{
   5620	struct vega10_hwmgr *data = hwmgr->backend;
   5621	uint32_t feature_mask = 0;
   5622
   5623	if (disable) {
   5624		feature_mask |= data->smu_features[GNLD_ULV].enabled ?
   5625			data->smu_features[GNLD_ULV].smu_feature_bitmap : 0;
   5626		feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ?
   5627			data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0;
   5628		feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ?
   5629			data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0;
   5630		feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ?
   5631			data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0;
   5632		feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ?
   5633			data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0;
   5634	} else {
   5635		feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ?
   5636			data->smu_features[GNLD_ULV].smu_feature_bitmap : 0;
   5637		feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ?
   5638			data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0;
   5639		feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ?
   5640			data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0;
   5641		feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ?
   5642			data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0;
   5643		feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ?
   5644			data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0;
   5645	}
   5646
   5647	if (feature_mask)
   5648		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	if (disable) {
   5654		data->smu_features[GNLD_ULV].enabled = false;
   5655		data->smu_features[GNLD_DS_GFXCLK].enabled = false;
   5656		data->smu_features[GNLD_DS_SOCCLK].enabled = false;
   5657		data->smu_features[GNLD_DS_LCLK].enabled = false;
   5658		data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
   5659	} else {
   5660		data->smu_features[GNLD_ULV].enabled = true;
   5661		data->smu_features[GNLD_DS_GFXCLK].enabled = true;
   5662		data->smu_features[GNLD_DS_SOCCLK].enabled = true;
   5663		data->smu_features[GNLD_DS_LCLK].enabled = true;
   5664		data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
   5665	}
   5666
   5667	return 0;
   5668
   5669}
   5670
   5671static 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
   5743int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
   5744{
   5745	struct amdgpu_device *adev = hwmgr->adev;
   5746
   5747	hwmgr->hwmgr_func = &vega10_hwmgr_funcs;
   5748	hwmgr->pptable_func = &vega10_pptable_funcs;
   5749	if (amdgpu_passthrough(adev))
   5750		return vega10_baco_set_cap(hwmgr);
   5751
   5752	return 0;
   5753}