File Index
Files and directories
Sign in
FILE

vega10_hwmgr.c

File preview with syntax highlighting.

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