File Index
Files and directories
Sign in
FILE

smu_v13_0_7_ppt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c C
   1/*
   2 * Copyright 2021 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#define SWSMU_CODE_LAYER_L2
  25
  26#include <linux/firmware.h>
  27#include <linux/pci.h>
  28#include <linux/i2c.h>
  29#include "amdgpu.h"
  30#include "amdgpu_smu.h"
  31#include "atomfirmware.h"
  32#include "amdgpu_atomfirmware.h"
  33#include "amdgpu_atombios.h"
  34#include "smu_v13_0.h"
  35#include "smu13_driver_if_v13_0_7.h"
  36#include "soc15_common.h"
  37#include "atom.h"
  38#include "smu_v13_0_7_ppt.h"
  39#include "smu_v13_0_7_pptable.h"
  40#include "smu_v13_0_7_ppsmc.h"
  41#include "nbio/nbio_4_3_0_offset.h"
  42#include "nbio/nbio_4_3_0_sh_mask.h"
  43#include "mp/mp_13_0_0_offset.h"
  44#include "mp/mp_13_0_0_sh_mask.h"
  45
  46#include "asic_reg/mp/mp_13_0_0_sh_mask.h"
  47#include "smu_cmn.h"
  48#include "amdgpu_ras.h"
  49
  50/*
  51 * DO NOT use these for err/warn/info/debug messages.
  52 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
  53 * They are more MGPU friendly.
  54 */
  55#undef pr_err
  56#undef pr_warn
  57#undef pr_info
  58#undef pr_debug
  59
  60#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
  61
  62static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
  63					      int od_feature_bit,
  64					      int32_t *min, int32_t *max);
  65
  66#define FEATURE_MASK(feature) (1ULL << feature)
  67#define SMC_DPM_FEATURE ( \
  68	FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
  69	FEATURE_MASK(FEATURE_DPM_UCLK_BIT)	 | \
  70	FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
  71	FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
  72	FEATURE_MASK(FEATURE_DPM_FCLK_BIT)	 | \
  73	FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT))
  74
  75#define smnMP1_FIRMWARE_FLAGS_SMU_13_0_7   0x3b10028
  76
  77#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE	0x4000
  78
  79#define PP_OD_FEATURE_GFXCLK_FMIN			0
  80#define PP_OD_FEATURE_GFXCLK_FMAX			1
  81#define PP_OD_FEATURE_UCLK_FMIN				2
  82#define PP_OD_FEATURE_UCLK_FMAX				3
  83#define PP_OD_FEATURE_GFX_VF_CURVE			4
  84#define PP_OD_FEATURE_FAN_CURVE_TEMP			5
  85#define PP_OD_FEATURE_FAN_CURVE_PWM			6
  86#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT		7
  87#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET		8
  88#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE		9
  89#define PP_OD_FEATURE_FAN_MINIMUM_PWM			10
  90#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE		11
  91#define PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP		12
  92
  93#define LINK_SPEED_MAX					3
  94
  95static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] = {
  96	MSG_MAP(TestMessage,			PPSMC_MSG_TestMessage,                 1),
  97	MSG_MAP(GetSmuVersion,			PPSMC_MSG_GetSmuVersion,               1),
  98	MSG_MAP(GetDriverIfVersion,		PPSMC_MSG_GetDriverIfVersion,          1),
  99	MSG_MAP(SetAllowedFeaturesMaskLow,	PPSMC_MSG_SetAllowedFeaturesMaskLow,   0),
 100	MSG_MAP(SetAllowedFeaturesMaskHigh,	PPSMC_MSG_SetAllowedFeaturesMaskHigh,  0),
 101	MSG_MAP(EnableAllSmuFeatures,		PPSMC_MSG_EnableAllSmuFeatures,        0),
 102	MSG_MAP(DisableAllSmuFeatures,		PPSMC_MSG_DisableAllSmuFeatures,       0),
 103	MSG_MAP(EnableSmuFeaturesLow,		PPSMC_MSG_EnableSmuFeaturesLow,        1),
 104	MSG_MAP(EnableSmuFeaturesHigh,		PPSMC_MSG_EnableSmuFeaturesHigh,       1),
 105	MSG_MAP(DisableSmuFeaturesLow,		PPSMC_MSG_DisableSmuFeaturesLow,       1),
 106	MSG_MAP(DisableSmuFeaturesHigh,		PPSMC_MSG_DisableSmuFeaturesHigh,      1),
 107	MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetRunningSmuFeaturesLow,    1),
 108	MSG_MAP(GetEnabledSmuFeaturesHigh,	PPSMC_MSG_GetRunningSmuFeaturesHigh,   1),
 109	MSG_MAP(SetWorkloadMask,		PPSMC_MSG_SetWorkloadMask,             1),
 110	MSG_MAP(SetPptLimit,			PPSMC_MSG_SetPptLimit,                 0),
 111	MSG_MAP(SetDriverDramAddrHigh,		PPSMC_MSG_SetDriverDramAddrHigh,       1),
 112	MSG_MAP(SetDriverDramAddrLow,		PPSMC_MSG_SetDriverDramAddrLow,        1),
 113	MSG_MAP(SetToolsDramAddrHigh,		PPSMC_MSG_SetToolsDramAddrHigh,        0),
 114	MSG_MAP(SetToolsDramAddrLow,		PPSMC_MSG_SetToolsDramAddrLow,         0),
 115	MSG_MAP(TransferTableSmu2Dram,		PPSMC_MSG_TransferTableSmu2Dram,       1),
 116	MSG_MAP(TransferTableDram2Smu,		PPSMC_MSG_TransferTableDram2Smu,       0),
 117	MSG_MAP(UseDefaultPPTable,		PPSMC_MSG_UseDefaultPPTable,           0),
 118	MSG_MAP(RunDcBtc,			PPSMC_MSG_RunDcBtc,                    0),
 119	MSG_MAP(EnterBaco,			PPSMC_MSG_EnterBaco,                   0),
 120	MSG_MAP(ExitBaco,           PPSMC_MSG_ExitBaco,        			   0),
 121	MSG_MAP(SetSoftMinByFreq,		PPSMC_MSG_SetSoftMinByFreq,            1),
 122	MSG_MAP(SetSoftMaxByFreq,		PPSMC_MSG_SetSoftMaxByFreq,            1),
 123	MSG_MAP(SetHardMinByFreq,		PPSMC_MSG_SetHardMinByFreq,            1),
 124	MSG_MAP(SetHardMaxByFreq,		PPSMC_MSG_SetHardMaxByFreq,            0),
 125	MSG_MAP(GetMinDpmFreq,			PPSMC_MSG_GetMinDpmFreq,               1),
 126	MSG_MAP(GetMaxDpmFreq,			PPSMC_MSG_GetMaxDpmFreq,               1),
 127	MSG_MAP(GetDpmFreqByIndex,		PPSMC_MSG_GetDpmFreqByIndex,           1),
 128	MSG_MAP(PowerUpVcn,				PPSMC_MSG_PowerUpVcn,                  0),
 129	MSG_MAP(PowerDownVcn,			PPSMC_MSG_PowerDownVcn,                0),
 130	MSG_MAP(PowerUpJpeg,			PPSMC_MSG_PowerUpJpeg,                 0),
 131	MSG_MAP(PowerDownJpeg,			PPSMC_MSG_PowerDownJpeg,               0),
 132	MSG_MAP(GetDcModeMaxDpmFreq,		PPSMC_MSG_GetDcModeMaxDpmFreq,         1),
 133	MSG_MAP(OverridePcieParameters,		PPSMC_MSG_OverridePcieParameters,      0),
 134	MSG_MAP(ReenableAcDcInterrupt,		PPSMC_MSG_ReenableAcDcInterrupt,       0),
 135	MSG_MAP(AllowIHHostInterrupt,		PPSMC_MSG_AllowIHHostInterrupt,       0),
 136	MSG_MAP(DramLogSetDramAddrHigh,		PPSMC_MSG_DramLogSetDramAddrHigh,      0),
 137	MSG_MAP(DramLogSetDramAddrLow,		PPSMC_MSG_DramLogSetDramAddrLow,       0),
 138	MSG_MAP(DramLogSetDramSize,		PPSMC_MSG_DramLogSetDramSize,          0),
 139	MSG_MAP(AllowGfxOff,			PPSMC_MSG_AllowGfxOff,                 0),
 140	MSG_MAP(DisallowGfxOff,			PPSMC_MSG_DisallowGfxOff,              0),
 141	MSG_MAP(Mode1Reset,             PPSMC_MSG_Mode1Reset,                  0),
 142	MSG_MAP(PrepareMp1ForUnload,		PPSMC_MSG_PrepareMp1ForUnload,         0),
 143	MSG_MAP(SetMGpuFanBoostLimitRpm,	PPSMC_MSG_SetMGpuFanBoostLimitRpm,     0),
 144	MSG_MAP(DFCstateControl,		PPSMC_MSG_SetExternalClientDfCstateAllow, 0),
 145	MSG_MAP(ArmD3,				PPSMC_MSG_ArmD3,                       0),
 146	MSG_MAP(AllowGpo,			PPSMC_MSG_SetGpoAllow,           0),
 147	MSG_MAP(GetPptLimit,			PPSMC_MSG_GetPptLimit,                 0),
 148	MSG_MAP(NotifyPowerSource,		PPSMC_MSG_NotifyPowerSource,           0),
 149	MSG_MAP(EnableUCLKShadow,		PPSMC_MSG_EnableUCLKShadow,            0),
 150};
 151
 152static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
 153	CLK_MAP(GFXCLK,		PPCLK_GFXCLK),
 154	CLK_MAP(SCLK,		PPCLK_GFXCLK),
 155	CLK_MAP(SOCCLK,		PPCLK_SOCCLK),
 156	CLK_MAP(FCLK,		PPCLK_FCLK),
 157	CLK_MAP(UCLK,		PPCLK_UCLK),
 158	CLK_MAP(MCLK,		PPCLK_UCLK),
 159	CLK_MAP(VCLK,		PPCLK_VCLK_0),
 160	CLK_MAP(VCLK1,		PPCLK_VCLK_1),
 161	CLK_MAP(DCLK,		PPCLK_DCLK_0),
 162	CLK_MAP(DCLK1,		PPCLK_DCLK_1),
 163	CLK_MAP(DCEFCLK,	PPCLK_DCFCLK),
 164};
 165
 166static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] = {
 167	FEA_MAP(FW_DATA_READ),
 168	FEA_MAP(DPM_GFXCLK),
 169	FEA_MAP(DPM_GFX_POWER_OPTIMIZER),
 170	FEA_MAP(DPM_UCLK),
 171	FEA_MAP(DPM_FCLK),
 172	FEA_MAP(DPM_SOCCLK),
 173	FEA_MAP(DPM_MP0CLK),
 174	FEA_MAP(DPM_LINK),
 175	FEA_MAP(DPM_DCN),
 176	FEA_MAP(VMEMP_SCALING),
 177	FEA_MAP(VDDIO_MEM_SCALING),
 178	FEA_MAP(DS_GFXCLK),
 179	FEA_MAP(DS_SOCCLK),
 180	FEA_MAP(DS_FCLK),
 181	FEA_MAP(DS_LCLK),
 182	FEA_MAP(DS_DCFCLK),
 183	FEA_MAP(DS_UCLK),
 184	FEA_MAP(GFX_ULV),
 185	FEA_MAP(FW_DSTATE),
 186	FEA_MAP(GFXOFF),
 187	FEA_MAP(BACO),
 188	FEA_MAP(MM_DPM),
 189	FEA_MAP(SOC_MPCLK_DS),
 190	FEA_MAP(BACO_MPCLK_DS),
 191	FEA_MAP(THROTTLERS),
 192	FEA_MAP(SMARTSHIFT),
 193	FEA_MAP(GTHR),
 194	FEA_MAP(ACDC),
 195	FEA_MAP(VR0HOT),
 196	FEA_MAP(FW_CTF),
 197	FEA_MAP(FAN_CONTROL),
 198	FEA_MAP(GFX_DCS),
 199	FEA_MAP(GFX_READ_MARGIN),
 200	FEA_MAP(LED_DISPLAY),
 201	FEA_MAP(GFXCLK_SPREAD_SPECTRUM),
 202	FEA_MAP(OUT_OF_BAND_MONITOR),
 203	FEA_MAP(OPTIMIZED_VMIN),
 204	FEA_MAP(GFX_IMU),
 205	FEA_MAP(BOOT_TIME_CAL),
 206	FEA_MAP(GFX_PCC_DFLL),
 207	FEA_MAP(SOC_CG),
 208	FEA_MAP(DF_CSTATE),
 209	FEA_MAP(GFX_EDC),
 210	FEA_MAP(BOOT_POWER_OPT),
 211	FEA_MAP(CLOCK_POWER_DOWN_BYPASS),
 212	FEA_MAP(DS_VCN),
 213	FEA_MAP(BACO_CG),
 214	FEA_MAP(MEM_TEMP_READ),
 215	FEA_MAP(ATHUB_MMHUB_PG),
 216	FEA_MAP(SOC_PCC),
 217	[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
 218	[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
 219	[SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
 220};
 221
 222static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
 223	TAB_MAP(PPTABLE),
 224	TAB_MAP(WATERMARKS),
 225	TAB_MAP(AVFS_PSM_DEBUG),
 226	TAB_MAP(PMSTATUSLOG),
 227	TAB_MAP(SMU_METRICS),
 228	TAB_MAP(DRIVER_SMU_CONFIG),
 229	TAB_MAP(ACTIVITY_MONITOR_COEFF),
 230	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
 231	TAB_MAP(OVERDRIVE),
 232	TAB_MAP(WIFIBAND),
 233};
 234
 235static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
 236	PWR_MAP(AC),
 237	PWR_MAP(DC),
 238};
 239
 240static struct cmn2asic_mapping smu_v13_0_7_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
 241	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,	WORKLOAD_PPLIB_DEFAULT_BIT),
 242	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
 243	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,		WORKLOAD_PPLIB_POWER_SAVING_BIT),
 244	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
 245	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
 246	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
 247	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
 248	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D,		WORKLOAD_PPLIB_WINDOW_3D_BIT),
 249};
 250
 251static const uint8_t smu_v13_0_7_throttler_map[] = {
 252	[THROTTLER_PPT0_BIT]		= (SMU_THROTTLER_PPT0_BIT),
 253	[THROTTLER_PPT1_BIT]		= (SMU_THROTTLER_PPT1_BIT),
 254	[THROTTLER_PPT2_BIT]		= (SMU_THROTTLER_PPT2_BIT),
 255	[THROTTLER_PPT3_BIT]		= (SMU_THROTTLER_PPT3_BIT),
 256	[THROTTLER_TDC_GFX_BIT]		= (SMU_THROTTLER_TDC_GFX_BIT),
 257	[THROTTLER_TDC_SOC_BIT]		= (SMU_THROTTLER_TDC_SOC_BIT),
 258	[THROTTLER_TEMP_EDGE_BIT]	= (SMU_THROTTLER_TEMP_EDGE_BIT),
 259	[THROTTLER_TEMP_HOTSPOT_BIT]	= (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
 260	[THROTTLER_TEMP_MEM_BIT]	= (SMU_THROTTLER_TEMP_MEM_BIT),
 261	[THROTTLER_TEMP_VR_GFX_BIT]	= (SMU_THROTTLER_TEMP_VR_GFX_BIT),
 262	[THROTTLER_TEMP_VR_SOC_BIT]	= (SMU_THROTTLER_TEMP_VR_SOC_BIT),
 263	[THROTTLER_TEMP_VR_MEM0_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
 264	[THROTTLER_TEMP_VR_MEM1_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
 265	[THROTTLER_TEMP_LIQUID0_BIT]	= (SMU_THROTTLER_TEMP_LIQUID0_BIT),
 266	[THROTTLER_TEMP_LIQUID1_BIT]	= (SMU_THROTTLER_TEMP_LIQUID1_BIT),
 267	[THROTTLER_GFX_APCC_PLUS_BIT]	= (SMU_THROTTLER_APCC_BIT),
 268	[THROTTLER_FIT_BIT]		= (SMU_THROTTLER_FIT_BIT),
 269};
 270
 271static int
 272smu_v13_0_7_get_allowed_feature_mask(struct smu_context *smu,
 273				  uint32_t *feature_mask, uint32_t num)
 274{
 275	struct amdgpu_device *adev = smu->adev;
 276
 277	if (num > 2)
 278		return -EINVAL;
 279
 280	memset(feature_mask, 0, sizeof(uint32_t) * num);
 281
 282	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
 283
 284	if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
 285		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
 286		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
 287		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT);
 288	}
 289
 290	if (adev->pm.pp_feature & PP_GFXOFF_MASK)
 291		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
 292
 293	if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
 294		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
 295		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
 296		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
 297		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
 298	}
 299
 300	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
 301
 302	if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
 303		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
 304
 305	if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
 306		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
 307
 308	if (adev->pm.pp_feature & PP_ULV_MASK)
 309		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
 310
 311	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
 312	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT);
 313	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
 314	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
 315	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_FCLK_BIT);
 316	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
 317	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
 318	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VR0HOT_BIT);
 319	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_CTF_BIT);
 320	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
 321	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
 322	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT);
 323	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
 324	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
 325	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
 326	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
 327	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_PCC_DFLL_BIT);
 328	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_CG_BIT);
 329	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_BIT);
 330
 331	if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
 332		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
 333
 334	if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
 335	    (adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
 336		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
 337
 338	return 0;
 339}
 340
 341static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
 342{
 343	struct smu_table_context *table_context = &smu->smu_table;
 344	struct smu_13_0_7_powerplay_table *powerplay_table =
 345		table_context->power_play_table;
 346	struct smu_baco_context *smu_baco = &smu->smu_baco;
 347	PPTable_t *smc_pptable = table_context->driver_pptable;
 348	BoardTable_t *BoardTable = &smc_pptable->BoardTable;
 349	const OverDriveLimits_t * const overdrive_upperlimits =
 350				&smc_pptable->SkuTable.OverDriveLimitsBasicMax;
 351	const OverDriveLimits_t * const overdrive_lowerlimits =
 352				&smc_pptable->SkuTable.OverDriveLimitsMin;
 353
 354	if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
 355		smu->dc_controlled_by_gpio = true;
 356
 357	if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO) {
 358		smu_baco->platform_support = true;
 359
 360		if ((powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
 361					&& (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
 362			smu_baco->maco_support = true;
 363	}
 364
 365	if (!overdrive_lowerlimits->FeatureCtrlMask ||
 366	    !overdrive_upperlimits->FeatureCtrlMask)
 367		smu->od_enabled = false;
 368
 369	table_context->thermal_controller_type =
 370		powerplay_table->thermal_controller_type;
 371
 372	/*
 373	 * Instead of having its own buffer space and get overdrive_table copied,
 374	 * smu->od_settings just points to the actual overdrive_table
 375	 */
 376	smu->od_settings = &powerplay_table->overdrive_table;
 377
 378	return 0;
 379}
 380
 381static int smu_v13_0_7_store_powerplay_table(struct smu_context *smu)
 382{
 383	struct smu_table_context *table_context = &smu->smu_table;
 384	struct smu_13_0_7_powerplay_table *powerplay_table =
 385		table_context->power_play_table;
 386	struct amdgpu_device *adev = smu->adev;
 387
 388	if (adev->pdev->device == 0x51)
 389		powerplay_table->smc_pptable.SkuTable.DebugOverrides |= 0x00000080;
 390
 391	memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
 392	       sizeof(PPTable_t));
 393
 394	return 0;
 395}
 396
 397static int smu_v13_0_7_check_fw_status(struct smu_context *smu)
 398{
 399	struct amdgpu_device *adev = smu->adev;
 400	uint32_t mp1_fw_flags;
 401
 402	mp1_fw_flags = RREG32_PCIE(MP1_Public |
 403				   (smnMP1_FIRMWARE_FLAGS_SMU_13_0_7 & 0xffffffff));
 404
 405	if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
 406			MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
 407		return 0;
 408
 409	return -EIO;
 410}
 411
 412#ifndef atom_smc_dpm_info_table_13_0_7
 413struct atom_smc_dpm_info_table_13_0_7 {
 414	struct atom_common_table_header table_header;
 415	BoardTable_t BoardTable;
 416};
 417#endif
 418
 419static int smu_v13_0_7_append_powerplay_table(struct smu_context *smu)
 420{
 421	struct smu_table_context *table_context = &smu->smu_table;
 422
 423	PPTable_t *smc_pptable = table_context->driver_pptable;
 424
 425	struct atom_smc_dpm_info_table_13_0_7 *smc_dpm_table;
 426
 427	BoardTable_t *BoardTable = &smc_pptable->BoardTable;
 428
 429	int index, ret;
 430
 431	index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 432	smc_dpm_info);
 433
 434	ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
 435			(uint8_t **)&smc_dpm_table);
 436	if (ret)
 437		return ret;
 438
 439	memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
 440
 441	return 0;
 442}
 443
 444static int smu_v13_0_7_get_pptable_from_pmfw(struct smu_context *smu,
 445					     void **table,
 446					     uint32_t *size)
 447{
 448	struct smu_table_context *smu_table = &smu->smu_table;
 449	void *combo_pptable = smu_table->combo_pptable;
 450	int ret = 0;
 451
 452	ret = smu_cmn_get_combo_pptable(smu);
 453	if (ret)
 454		return ret;
 455
 456	*table = combo_pptable;
 457	*size = sizeof(struct smu_13_0_7_powerplay_table);
 458
 459	return 0;
 460}
 461
 462static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
 463{
 464	struct smu_table_context *smu_table = &smu->smu_table;
 465	struct amdgpu_device *adev = smu->adev;
 466	int ret = 0;
 467
 468	/*
 469	 * With SCPM enabled, the pptable used will be signed. It cannot
 470	 * be used directly by driver. To get the raw pptable, we need to
 471	 * rely on the combo pptable(and its revelant SMU message).
 472	 */
 473	ret = smu_v13_0_7_get_pptable_from_pmfw(smu,
 474						&smu_table->power_play_table,
 475						&smu_table->power_play_table_size);
 476	if (ret)
 477		return ret;
 478
 479	ret = smu_v13_0_7_store_powerplay_table(smu);
 480	if (ret)
 481		return ret;
 482
 483	/*
 484	 * With SCPM enabled, the operation below will be handled
 485	 * by PSP. Driver involvment is unnecessary and useless.
 486	 */
 487	if (!adev->scpm_enabled) {
 488		ret = smu_v13_0_7_append_powerplay_table(smu);
 489		if (ret)
 490			return ret;
 491	}
 492
 493	ret = smu_v13_0_7_check_powerplay_table(smu);
 494	if (ret)
 495		return ret;
 496
 497	return ret;
 498}
 499
 500static int smu_v13_0_7_tables_init(struct smu_context *smu)
 501{
 502	struct smu_table_context *smu_table = &smu->smu_table;
 503	struct smu_table *tables = smu_table->tables;
 504
 505	SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
 506		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 507
 508	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
 509		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 510	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
 511		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 512	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
 513		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 514	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
 515		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 516	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
 517		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 518	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
 519		       sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
 520		       AMDGPU_GEM_DOMAIN_VRAM);
 521	SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
 522			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 523	SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND,
 524		       sizeof(WifiBandEntryTable_t), PAGE_SIZE,
 525		       AMDGPU_GEM_DOMAIN_VRAM);
 526
 527	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
 528	if (!smu_table->metrics_table)
 529		goto err0_out;
 530	smu_table->metrics_time = 0;
 531
 532	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
 533	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
 534	if (!smu_table->gpu_metrics_table)
 535		goto err1_out;
 536
 537	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
 538	if (!smu_table->watermarks_table)
 539		goto err2_out;
 540
 541	return 0;
 542
 543err2_out:
 544	kfree(smu_table->gpu_metrics_table);
 545err1_out:
 546	kfree(smu_table->metrics_table);
 547err0_out:
 548	return -ENOMEM;
 549}
 550
 551static int smu_v13_0_7_allocate_dpm_context(struct smu_context *smu)
 552{
 553	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
 554
 555	smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
 556				       GFP_KERNEL);
 557	if (!smu_dpm->dpm_context)
 558		return -ENOMEM;
 559
 560	smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
 561
 562	return 0;
 563}
 564
 565static int smu_v13_0_7_init_smc_tables(struct smu_context *smu)
 566{
 567	int ret = 0;
 568
 569	ret = smu_v13_0_7_tables_init(smu);
 570	if (ret)
 571		return ret;
 572
 573	ret = smu_v13_0_7_allocate_dpm_context(smu);
 574	if (ret)
 575		return ret;
 576
 577	return smu_v13_0_init_smc_tables(smu);
 578}
 579
 580static int smu_v13_0_7_set_default_dpm_table(struct smu_context *smu)
 581{
 582	struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
 583	PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
 584	SkuTable_t *skutable = &driver_ppt->SkuTable;
 585	struct smu_13_0_dpm_table *dpm_table;
 586	int ret = 0;
 587
 588	/* socclk dpm table setup */
 589	dpm_table = &dpm_context->dpm_tables.soc_table;
 590	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
 591		ret = smu_v13_0_set_single_dpm_table(smu,
 592						     SMU_SOCCLK,
 593						     dpm_table);
 594		if (ret)
 595			return ret;
 596	} else {
 597		dpm_table->count = 1;
 598		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
 599		dpm_table->dpm_levels[0].enabled = true;
 600		dpm_table->min = dpm_table->dpm_levels[0].value;
 601		dpm_table->max = dpm_table->dpm_levels[0].value;
 602	}
 603
 604	/* gfxclk dpm table setup */
 605	dpm_table = &dpm_context->dpm_tables.gfx_table;
 606	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
 607		ret = smu_v13_0_set_single_dpm_table(smu,
 608						     SMU_GFXCLK,
 609						     dpm_table);
 610		if (ret)
 611			return ret;
 612
 613		if (skutable->DriverReportedClocks.GameClockAc &&
 614			(dpm_table->dpm_levels[dpm_table->count - 1].value >
 615			skutable->DriverReportedClocks.GameClockAc)) {
 616			dpm_table->dpm_levels[dpm_table->count - 1].value =
 617				skutable->DriverReportedClocks.GameClockAc;
 618			dpm_table->max = skutable->DriverReportedClocks.GameClockAc;
 619		}
 620	} else {
 621		dpm_table->count = 1;
 622		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
 623		dpm_table->dpm_levels[0].enabled = true;
 624		dpm_table->min = dpm_table->dpm_levels[0].value;
 625		dpm_table->max = dpm_table->dpm_levels[0].value;
 626	}
 627
 628	/* uclk dpm table setup */
 629	dpm_table = &dpm_context->dpm_tables.uclk_table;
 630	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
 631		ret = smu_v13_0_set_single_dpm_table(smu,
 632						     SMU_UCLK,
 633						     dpm_table);
 634		if (ret)
 635			return ret;
 636	} else {
 637		dpm_table->count = 1;
 638		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
 639		dpm_table->dpm_levels[0].enabled = true;
 640		dpm_table->min = dpm_table->dpm_levels[0].value;
 641		dpm_table->max = dpm_table->dpm_levels[0].value;
 642	}
 643
 644	/* fclk dpm table setup */
 645	dpm_table = &dpm_context->dpm_tables.fclk_table;
 646	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
 647		ret = smu_v13_0_set_single_dpm_table(smu,
 648						     SMU_FCLK,
 649						     dpm_table);
 650		if (ret)
 651			return ret;
 652	} else {
 653		dpm_table->count = 1;
 654		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
 655		dpm_table->dpm_levels[0].enabled = true;
 656		dpm_table->min = dpm_table->dpm_levels[0].value;
 657		dpm_table->max = dpm_table->dpm_levels[0].value;
 658	}
 659
 660	/* vclk dpm table setup */
 661	dpm_table = &dpm_context->dpm_tables.vclk_table;
 662	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) {
 663		ret = smu_v13_0_set_single_dpm_table(smu,
 664						     SMU_VCLK,
 665						     dpm_table);
 666		if (ret)
 667			return ret;
 668	} else {
 669		dpm_table->count = 1;
 670		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
 671		dpm_table->dpm_levels[0].enabled = true;
 672		dpm_table->min = dpm_table->dpm_levels[0].value;
 673		dpm_table->max = dpm_table->dpm_levels[0].value;
 674	}
 675
 676	/* dclk dpm table setup */
 677	dpm_table = &dpm_context->dpm_tables.dclk_table;
 678	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) {
 679		ret = smu_v13_0_set_single_dpm_table(smu,
 680						     SMU_DCLK,
 681						     dpm_table);
 682		if (ret)
 683			return ret;
 684	} else {
 685		dpm_table->count = 1;
 686		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
 687		dpm_table->dpm_levels[0].enabled = true;
 688		dpm_table->min = dpm_table->dpm_levels[0].value;
 689		dpm_table->max = dpm_table->dpm_levels[0].value;
 690	}
 691
 692	/* dcefclk dpm table setup */
 693	dpm_table = &dpm_context->dpm_tables.dcef_table;
 694	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCN_BIT)) {
 695		ret = smu_v13_0_set_single_dpm_table(smu,
 696						     SMU_DCEFCLK,
 697						     dpm_table);
 698		if (ret)
 699			return ret;
 700	} else {
 701		dpm_table->count = 1;
 702		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
 703		dpm_table->dpm_levels[0].enabled = true;
 704		dpm_table->min = dpm_table->dpm_levels[0].value;
 705		dpm_table->max = dpm_table->dpm_levels[0].value;
 706	}
 707
 708	return 0;
 709}
 710
 711static bool smu_v13_0_7_is_dpm_running(struct smu_context *smu)
 712{
 713	int ret = 0;
 714	uint64_t feature_enabled;
 715
 716	ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
 717	if (ret)
 718		return false;
 719
 720	return !!(feature_enabled & SMC_DPM_FEATURE);
 721}
 722
 723static uint32_t smu_v13_0_7_get_throttler_status(SmuMetrics_t *metrics)
 724{
 725	uint32_t throttler_status = 0;
 726	int i;
 727
 728	for (i = 0; i < THROTTLER_COUNT; i++)
 729		throttler_status |=
 730			(metrics->ThrottlingPercentage[i] ? 1U << i : 0);
 731
 732	return throttler_status;
 733}
 734
 735#define SMU_13_0_7_BUSY_THRESHOLD	15
 736static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
 737					    MetricsMember_t member,
 738					    uint32_t *value)
 739{
 740	struct smu_table_context *smu_table = &smu->smu_table;
 741	SmuMetrics_t *metrics =
 742		&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
 743	int ret = 0;
 744
 745	ret = smu_cmn_get_metrics_table(smu,
 746					NULL,
 747					false);
 748	if (ret)
 749		return ret;
 750
 751	switch (member) {
 752	case METRICS_CURR_GFXCLK:
 753		*value = metrics->CurrClock[PPCLK_GFXCLK];
 754		break;
 755	case METRICS_CURR_SOCCLK:
 756		*value = metrics->CurrClock[PPCLK_SOCCLK];
 757		break;
 758	case METRICS_CURR_UCLK:
 759		*value = metrics->CurrClock[PPCLK_UCLK];
 760		break;
 761	case METRICS_CURR_VCLK:
 762		*value = metrics->CurrClock[PPCLK_VCLK_0];
 763		break;
 764	case METRICS_CURR_VCLK1:
 765		*value = metrics->CurrClock[PPCLK_VCLK_1];
 766		break;
 767	case METRICS_CURR_DCLK:
 768		*value = metrics->CurrClock[PPCLK_DCLK_0];
 769		break;
 770	case METRICS_CURR_DCLK1:
 771		*value = metrics->CurrClock[PPCLK_DCLK_1];
 772		break;
 773	case METRICS_CURR_FCLK:
 774		*value = metrics->CurrClock[PPCLK_FCLK];
 775		break;
 776	case METRICS_CURR_DCEFCLK:
 777		*value = metrics->CurrClock[PPCLK_DCFCLK];
 778		break;
 779	case METRICS_AVERAGE_GFXCLK:
 780		*value = metrics->AverageGfxclkFrequencyPreDs;
 781		break;
 782	case METRICS_AVERAGE_FCLK:
 783		if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
 784			*value = metrics->AverageFclkFrequencyPostDs;
 785		else
 786			*value = metrics->AverageFclkFrequencyPreDs;
 787		break;
 788	case METRICS_AVERAGE_UCLK:
 789		if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
 790			*value = metrics->AverageMemclkFrequencyPostDs;
 791		else
 792			*value = metrics->AverageMemclkFrequencyPreDs;
 793		break;
 794	case METRICS_AVERAGE_VCNACTIVITY:
 795		*value = max(metrics->Vcn0ActivityPercentage,
 796			     metrics->Vcn1ActivityPercentage);
 797		break;
 798	case METRICS_AVERAGE_VCLK:
 799		*value = metrics->AverageVclk0Frequency;
 800		break;
 801	case METRICS_AVERAGE_DCLK:
 802		*value = metrics->AverageDclk0Frequency;
 803		break;
 804	case METRICS_AVERAGE_VCLK1:
 805		*value = metrics->AverageVclk1Frequency;
 806		break;
 807	case METRICS_AVERAGE_DCLK1:
 808		*value = metrics->AverageDclk1Frequency;
 809		break;
 810	case METRICS_AVERAGE_GFXACTIVITY:
 811		*value = metrics->AverageGfxActivity;
 812		break;
 813	case METRICS_AVERAGE_MEMACTIVITY:
 814		*value = metrics->AverageUclkActivity;
 815		break;
 816	case METRICS_AVERAGE_SOCKETPOWER:
 817		*value = metrics->AverageSocketPower << 8;
 818		break;
 819	case METRICS_TEMPERATURE_EDGE:
 820		*value = metrics->AvgTemperature[TEMP_EDGE] *
 821			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 822		break;
 823	case METRICS_TEMPERATURE_HOTSPOT:
 824		*value = metrics->AvgTemperature[TEMP_HOTSPOT] *
 825			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 826		break;
 827	case METRICS_TEMPERATURE_MEM:
 828		*value = metrics->AvgTemperature[TEMP_MEM] *
 829			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 830		break;
 831	case METRICS_TEMPERATURE_VRGFX:
 832		*value = metrics->AvgTemperature[TEMP_VR_GFX] *
 833			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 834		break;
 835	case METRICS_TEMPERATURE_VRSOC:
 836		*value = metrics->AvgTemperature[TEMP_VR_SOC] *
 837			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 838		break;
 839	case METRICS_THROTTLER_STATUS:
 840		*value = smu_v13_0_7_get_throttler_status(metrics);
 841		break;
 842	case METRICS_CURR_FANSPEED:
 843		*value = metrics->AvgFanRpm;
 844		break;
 845	case METRICS_CURR_FANPWM:
 846		*value = metrics->AvgFanPwm;
 847		break;
 848	case METRICS_VOLTAGE_VDDGFX:
 849		*value = metrics->AvgVoltage[SVI_PLANE_GFX];
 850		break;
 851	case METRICS_PCIE_RATE:
 852		*value = metrics->PcieRate;
 853		break;
 854	case METRICS_PCIE_WIDTH:
 855		*value = metrics->PcieWidth;
 856		break;
 857	default:
 858		*value = UINT_MAX;
 859		break;
 860	}
 861
 862	return ret;
 863}
 864
 865static int smu_v13_0_7_get_dpm_ultimate_freq(struct smu_context *smu,
 866					     enum smu_clk_type clk_type,
 867					     uint32_t *min,
 868					     uint32_t *max)
 869{
 870	struct smu_13_0_dpm_context *dpm_context =
 871		smu->smu_dpm.dpm_context;
 872	struct smu_13_0_dpm_table *dpm_table;
 873
 874	switch (clk_type) {
 875	case SMU_MCLK:
 876	case SMU_UCLK:
 877		/* uclk dpm table */
 878		dpm_table = &dpm_context->dpm_tables.uclk_table;
 879		break;
 880	case SMU_GFXCLK:
 881	case SMU_SCLK:
 882		/* gfxclk dpm table */
 883		dpm_table = &dpm_context->dpm_tables.gfx_table;
 884		break;
 885	case SMU_SOCCLK:
 886		/* socclk dpm table */
 887		dpm_table = &dpm_context->dpm_tables.soc_table;
 888		break;
 889	case SMU_FCLK:
 890		/* fclk dpm table */
 891		dpm_table = &dpm_context->dpm_tables.fclk_table;
 892		break;
 893	case SMU_VCLK:
 894	case SMU_VCLK1:
 895		/* vclk dpm table */
 896		dpm_table = &dpm_context->dpm_tables.vclk_table;
 897		break;
 898	case SMU_DCLK:
 899	case SMU_DCLK1:
 900		/* dclk dpm table */
 901		dpm_table = &dpm_context->dpm_tables.dclk_table;
 902		break;
 903	default:
 904		dev_err(smu->adev->dev, "Unsupported clock type!\n");
 905		return -EINVAL;
 906	}
 907
 908	if (min)
 909		*min = dpm_table->min;
 910	if (max)
 911		*max = dpm_table->max;
 912
 913	return 0;
 914}
 915
 916static int smu_v13_0_7_read_sensor(struct smu_context *smu,
 917				   enum amd_pp_sensors sensor,
 918				   void *data,
 919				   uint32_t *size)
 920{
 921	struct smu_table_context *table_context = &smu->smu_table;
 922	PPTable_t *smc_pptable = table_context->driver_pptable;
 923	int ret = 0;
 924
 925	switch (sensor) {
 926	case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
 927		*(uint16_t *)data = smc_pptable->SkuTable.FanMaximumRpm;
 928		*size = 4;
 929		break;
 930	case AMDGPU_PP_SENSOR_MEM_LOAD:
 931		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 932						       METRICS_AVERAGE_MEMACTIVITY,
 933						       (uint32_t *)data);
 934		*size = 4;
 935		break;
 936	case AMDGPU_PP_SENSOR_GPU_LOAD:
 937		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 938						       METRICS_AVERAGE_GFXACTIVITY,
 939						       (uint32_t *)data);
 940		*size = 4;
 941		break;
 942	case AMDGPU_PP_SENSOR_VCN_LOAD:
 943		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 944						       METRICS_AVERAGE_VCNACTIVITY,
 945						       (uint32_t *)data);
 946		*size = 4;
 947		break;
 948	case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
 949		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 950						       METRICS_AVERAGE_SOCKETPOWER,
 951						       (uint32_t *)data);
 952		*size = 4;
 953		break;
 954	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
 955		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 956						       METRICS_TEMPERATURE_HOTSPOT,
 957						       (uint32_t *)data);
 958		*size = 4;
 959		break;
 960	case AMDGPU_PP_SENSOR_EDGE_TEMP:
 961		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 962						       METRICS_TEMPERATURE_EDGE,
 963						       (uint32_t *)data);
 964		*size = 4;
 965		break;
 966	case AMDGPU_PP_SENSOR_MEM_TEMP:
 967		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 968						       METRICS_TEMPERATURE_MEM,
 969						       (uint32_t *)data);
 970		*size = 4;
 971		break;
 972	case AMDGPU_PP_SENSOR_GFX_MCLK:
 973		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 974						       METRICS_CURR_UCLK,
 975						       (uint32_t *)data);
 976		*(uint32_t *)data *= 100;
 977		*size = 4;
 978		break;
 979	case AMDGPU_PP_SENSOR_GFX_SCLK:
 980		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 981						       METRICS_AVERAGE_GFXCLK,
 982						       (uint32_t *)data);
 983		*(uint32_t *)data *= 100;
 984		*size = 4;
 985		break;
 986	case AMDGPU_PP_SENSOR_VDDGFX:
 987		ret = smu_v13_0_7_get_smu_metrics_data(smu,
 988						       METRICS_VOLTAGE_VDDGFX,
 989						       (uint32_t *)data);
 990		*size = 4;
 991		break;
 992	case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
 993	default:
 994		ret = -EOPNOTSUPP;
 995		break;
 996	}
 997
 998	return ret;
 999}
1000
1001static int smu_v13_0_7_get_current_clk_freq_by_table(struct smu_context *smu,
1002						     enum smu_clk_type clk_type,
1003						     uint32_t *value)
1004{
1005	MetricsMember_t member_type;
1006	int clk_id = 0;
1007
1008	clk_id = smu_cmn_to_asic_specific_index(smu,
1009						CMN2ASIC_MAPPING_CLK,
1010						clk_type);
1011	if (clk_id < 0)
1012		return -EINVAL;
1013
1014	switch (clk_id) {
1015	case PPCLK_GFXCLK:
1016		member_type = METRICS_AVERAGE_GFXCLK;
1017		break;
1018	case PPCLK_UCLK:
1019		member_type = METRICS_CURR_UCLK;
1020		break;
1021	case PPCLK_FCLK:
1022		member_type = METRICS_CURR_FCLK;
1023		break;
1024	case PPCLK_SOCCLK:
1025		member_type = METRICS_CURR_SOCCLK;
1026		break;
1027	case PPCLK_VCLK_0:
1028		member_type = METRICS_CURR_VCLK;
1029		break;
1030	case PPCLK_DCLK_0:
1031		member_type = METRICS_CURR_DCLK;
1032		break;
1033	case PPCLK_VCLK_1:
1034		member_type = METRICS_CURR_VCLK1;
1035		break;
1036	case PPCLK_DCLK_1:
1037		member_type = METRICS_CURR_DCLK1;
1038		break;
1039	case PPCLK_DCFCLK:
1040		member_type = METRICS_CURR_DCEFCLK;
1041		break;
1042	default:
1043		return -EINVAL;
1044	}
1045
1046	return smu_v13_0_7_get_smu_metrics_data(smu,
1047						member_type,
1048						value);
1049}
1050
1051static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
1052						int od_feature_bit)
1053{
1054	PPTable_t *pptable = smu->smu_table.driver_pptable;
1055	const OverDriveLimits_t * const overdrive_upperlimits =
1056				&pptable->SkuTable.OverDriveLimitsBasicMax;
1057	int32_t min_value, max_value;
1058	bool feature_enabled;
1059
1060	switch (od_feature_bit) {
1061	case PP_OD_FEATURE_FAN_CURVE_BIT:
1062		feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
1063		if (feature_enabled) {
1064			smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_TEMP,
1065							  &min_value, &max_value);
1066			if (!min_value && !max_value) {
1067				feature_enabled = false;
1068				goto out;
1069			}
1070
1071			smu_v13_0_7_get_od_setting_limits(smu, PP_OD_FEATURE_FAN_CURVE_PWM,
1072							  &min_value, &max_value);
1073			if (!min_value && !max_value) {
1074				feature_enabled = false;
1075				goto out;
1076			}
1077		}
1078		break;
1079	default:
1080		feature_enabled = !!(overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit));
1081		break;
1082	}
1083
1084out:
1085	return feature_enabled;
1086}
1087
1088static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
1089					      int od_feature_bit,
1090					      int32_t *min,
1091					      int32_t *max)
1092{
1093	PPTable_t *pptable = smu->smu_table.driver_pptable;
1094	const OverDriveLimits_t * const overdrive_upperlimits =
1095				&pptable->SkuTable.OverDriveLimitsBasicMax;
1096	const OverDriveLimits_t * const overdrive_lowerlimits =
1097				&pptable->SkuTable.OverDriveLimitsMin;
1098	int32_t od_min_setting, od_max_setting;
1099
1100	switch (od_feature_bit) {
1101	case PP_OD_FEATURE_GFXCLK_FMIN:
1102		od_min_setting = overdrive_lowerlimits->GfxclkFmin;
1103		od_max_setting = overdrive_upperlimits->GfxclkFmin;
1104		break;
1105	case PP_OD_FEATURE_GFXCLK_FMAX:
1106		od_min_setting = overdrive_lowerlimits->GfxclkFmax;
1107		od_max_setting = overdrive_upperlimits->GfxclkFmax;
1108		break;
1109	case PP_OD_FEATURE_UCLK_FMIN:
1110		od_min_setting = overdrive_lowerlimits->UclkFmin;
1111		od_max_setting = overdrive_upperlimits->UclkFmin;
1112		break;
1113	case PP_OD_FEATURE_UCLK_FMAX:
1114		od_min_setting = overdrive_lowerlimits->UclkFmax;
1115		od_max_setting = overdrive_upperlimits->UclkFmax;
1116		break;
1117	case PP_OD_FEATURE_GFX_VF_CURVE:
1118		od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary;
1119		od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary;
1120		break;
1121	case PP_OD_FEATURE_FAN_CURVE_TEMP:
1122		od_min_setting = overdrive_lowerlimits->FanLinearTempPoints;
1123		od_max_setting = overdrive_upperlimits->FanLinearTempPoints;
1124		break;
1125	case PP_OD_FEATURE_FAN_CURVE_PWM:
1126		od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints;
1127		od_max_setting = overdrive_upperlimits->FanLinearPwmPoints;
1128		break;
1129	case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT:
1130		od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold;
1131		od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold;
1132		break;
1133	case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET:
1134		od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold;
1135		od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold;
1136		break;
1137	case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE:
1138		od_min_setting = overdrive_lowerlimits->FanTargetTemperature;
1139		od_max_setting = overdrive_upperlimits->FanTargetTemperature;
1140		break;
1141	case PP_OD_FEATURE_FAN_MINIMUM_PWM:
1142		od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
1143		od_max_setting = overdrive_upperlimits->FanMinimumPwm;
1144		break;
1145	case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
1146		od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
1147		od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
1148		break;
1149	case PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP:
1150		od_min_setting = overdrive_lowerlimits->FanZeroRpmStopTemp;
1151		od_max_setting = overdrive_upperlimits->FanZeroRpmStopTemp;
1152		break;
1153	default:
1154		od_min_setting = od_max_setting = INT_MAX;
1155		break;
1156	}
1157
1158	if (min)
1159		*min = od_min_setting;
1160	if (max)
1161		*max = od_max_setting;
1162}
1163
1164static void smu_v13_0_7_dump_od_table(struct smu_context *smu,
1165				      OverDriveTableExternal_t *od_table)
1166{
1167	struct amdgpu_device *adev = smu->adev;
1168
1169	dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin,
1170						     od_table->OverDriveTable.GfxclkFmax);
1171	dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
1172						   od_table->OverDriveTable.UclkFmax);
1173}
1174
1175static int smu_v13_0_7_get_overdrive_table(struct smu_context *smu,
1176					   OverDriveTableExternal_t *od_table)
1177{
1178	int ret = 0;
1179
1180	ret = smu_cmn_update_table(smu,
1181				   SMU_TABLE_OVERDRIVE,
1182				   0,
1183				   (void *)od_table,
1184				   false);
1185	if (ret)
1186		dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
1187
1188	return ret;
1189}
1190
1191static int smu_v13_0_7_upload_overdrive_table(struct smu_context *smu,
1192					      OverDriveTableExternal_t *od_table)
1193{
1194	int ret = 0;
1195
1196	ret = smu_cmn_update_table(smu,
1197				   SMU_TABLE_OVERDRIVE,
1198				   0,
1199				   (void *)od_table,
1200				   true);
1201	if (ret)
1202		dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
1203
1204	return ret;
1205}
1206
1207static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
1208					enum smu_clk_type clk_type,
1209					char *buf)
1210{
1211	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1212	struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1213	OverDriveTableExternal_t *od_table =
1214		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
1215	struct smu_13_0_dpm_table *single_dpm_table;
1216	struct smu_13_0_pcie_table *pcie_table;
1217	uint32_t gen_speed, lane_width;
1218	int i, curr_freq, size = 0, start_offset = 0;
1219	int32_t min_value, max_value;
1220	int ret = 0;
1221
1222	smu_cmn_get_sysfs_buf(&buf, &size);
1223	start_offset = size;
1224
1225	if (amdgpu_ras_intr_triggered()) {
1226		size += sysfs_emit_at(buf, size, "unavailable\n");
1227		return size - start_offset;
1228	}
1229
1230	switch (clk_type) {
1231	case SMU_SCLK:
1232		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
1233		break;
1234	case SMU_MCLK:
1235		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
1236		break;
1237	case SMU_SOCCLK:
1238		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
1239		break;
1240	case SMU_FCLK:
1241		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
1242		break;
1243	case SMU_VCLK:
1244	case SMU_VCLK1:
1245		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
1246		break;
1247	case SMU_DCLK:
1248	case SMU_DCLK1:
1249		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
1250		break;
1251	case SMU_DCEFCLK:
1252		single_dpm_table = &(dpm_context->dpm_tables.dcef_table);
1253		break;
1254	default:
1255		break;
1256	}
1257
1258	switch (clk_type) {
1259	case SMU_SCLK:
1260	case SMU_MCLK:
1261	case SMU_SOCCLK:
1262	case SMU_FCLK:
1263	case SMU_VCLK:
1264	case SMU_VCLK1:
1265	case SMU_DCLK:
1266	case SMU_DCLK1:
1267	case SMU_DCEFCLK:
1268		ret = smu_v13_0_7_get_current_clk_freq_by_table(smu, clk_type, &curr_freq);
1269		if (ret) {
1270			dev_err(smu->adev->dev, "Failed to get current clock freq!");
1271			return ret;
1272		}
1273
1274		if (single_dpm_table->is_fine_grained) {
1275			/*
1276			 * For fine grained dpms, there are only two dpm levels:
1277			 *   - level 0 -> min clock freq
1278			 *   - level 1 -> max clock freq
1279			 * And the current clock frequency can be any value between them.
1280			 * So, if the current clock frequency is not at level 0 or level 1,
1281			 * we will fake it as three dpm levels:
1282			 *   - level 0 -> min clock freq
1283			 *   - level 1 -> current actual clock freq
1284			 *   - level 2 -> max clock freq
1285			 */
1286			if ((single_dpm_table->dpm_levels[0].value != curr_freq) &&
1287			     (single_dpm_table->dpm_levels[1].value != curr_freq)) {
1288				size += sysfs_emit_at(buf, size, "0: %uMhz\n",
1289						single_dpm_table->dpm_levels[0].value);
1290				size += sysfs_emit_at(buf, size, "1: %uMhz *\n",
1291						curr_freq);
1292				size += sysfs_emit_at(buf, size, "2: %uMhz\n",
1293						single_dpm_table->dpm_levels[1].value);
1294			} else {
1295				size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
1296						single_dpm_table->dpm_levels[0].value,
1297						single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : "");
1298				size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
1299						single_dpm_table->dpm_levels[1].value,
1300						single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : "");
1301			}
1302		} else {
1303			for (i = 0; i < single_dpm_table->count; i++)
1304				size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
1305						i, single_dpm_table->dpm_levels[i].value,
1306						single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : "");
1307		}
1308		break;
1309	case SMU_PCIE:
1310		ret = smu_v13_0_7_get_smu_metrics_data(smu,
1311						       METRICS_PCIE_RATE,
1312						       &gen_speed);
1313		if (ret)
1314			return ret;
1315
1316		ret = smu_v13_0_7_get_smu_metrics_data(smu,
1317						       METRICS_PCIE_WIDTH,
1318						       &lane_width);
1319		if (ret)
1320			return ret;
1321
1322		pcie_table = &(dpm_context->dpm_tables.pcie_table);
1323		for (i = 0; i < pcie_table->num_of_link_levels; i++)
1324			size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
1325					(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
1326					(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
1327					(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
1328					(pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
1329					(pcie_table->pcie_lane[i] == 1) ? "x1" :
1330					(pcie_table->pcie_lane[i] == 2) ? "x2" :
1331					(pcie_table->pcie_lane[i] == 3) ? "x4" :
1332					(pcie_table->pcie_lane[i] == 4) ? "x8" :
1333					(pcie_table->pcie_lane[i] == 5) ? "x12" :
1334					(pcie_table->pcie_lane[i] == 6) ? "x16" : "",
1335					pcie_table->clk_freq[i],
1336					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
1337					(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
1338					"*" : "");
1339		break;
1340
1341	case SMU_OD_SCLK:
1342		if (!smu_v13_0_7_is_od_feature_supported(smu,
1343							 PP_OD_FEATURE_GFXCLK_BIT))
1344			break;
1345
1346		size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
1347		size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
1348					od_table->OverDriveTable.GfxclkFmin,
1349					od_table->OverDriveTable.GfxclkFmax);
1350		break;
1351
1352	case SMU_OD_MCLK:
1353		if (!smu_v13_0_7_is_od_feature_supported(smu,
1354							 PP_OD_FEATURE_UCLK_BIT))
1355			break;
1356
1357		size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
1358		size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
1359					od_table->OverDriveTable.UclkFmin,
1360					od_table->OverDriveTable.UclkFmax);
1361		break;
1362
1363	case SMU_OD_VDDGFX_OFFSET:
1364		if (!smu_v13_0_7_is_od_feature_supported(smu,
1365							 PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1366			break;
1367
1368		size += sysfs_emit_at(buf, size, "OD_VDDGFX_OFFSET:\n");
1369		size += sysfs_emit_at(buf, size, "%dmV\n",
1370				      od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]);
1371		break;
1372
1373	case SMU_OD_FAN_CURVE:
1374		if (!smu_v13_0_7_is_od_feature_supported(smu,
1375							 PP_OD_FEATURE_FAN_CURVE_BIT))
1376			break;
1377
1378		size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n");
1379		for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++)
1380			size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n",
1381						i,
1382						(int)od_table->OverDriveTable.FanLinearTempPoints[i],
1383						(int)od_table->OverDriveTable.FanLinearPwmPoints[i]);
1384
1385		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1386		smu_v13_0_7_get_od_setting_limits(smu,
1387						  PP_OD_FEATURE_FAN_CURVE_TEMP,
1388						  &min_value,
1389						  &max_value);
1390		size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n",
1391				      min_value, max_value);
1392
1393		smu_v13_0_7_get_od_setting_limits(smu,
1394						  PP_OD_FEATURE_FAN_CURVE_PWM,
1395						  &min_value,
1396						  &max_value);
1397		size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n",
1398				      min_value, max_value);
1399
1400		break;
1401
1402	case SMU_OD_ACOUSTIC_LIMIT:
1403		if (!smu_v13_0_7_is_od_feature_supported(smu,
1404							 PP_OD_FEATURE_FAN_CURVE_BIT))
1405			break;
1406
1407		size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n");
1408		size += sysfs_emit_at(buf, size, "%d\n",
1409					(int)od_table->OverDriveTable.AcousticLimitRpmThreshold);
1410
1411		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1412		smu_v13_0_7_get_od_setting_limits(smu,
1413						  PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
1414						  &min_value,
1415						  &max_value);
1416		size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n",
1417				      min_value, max_value);
1418		break;
1419
1420	case SMU_OD_ACOUSTIC_TARGET:
1421		if (!smu_v13_0_7_is_od_feature_supported(smu,
1422							 PP_OD_FEATURE_FAN_CURVE_BIT))
1423			break;
1424
1425		size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n");
1426		size += sysfs_emit_at(buf, size, "%d\n",
1427					(int)od_table->OverDriveTable.AcousticTargetRpmThreshold);
1428
1429		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1430		smu_v13_0_7_get_od_setting_limits(smu,
1431						  PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
1432						  &min_value,
1433						  &max_value);
1434		size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n",
1435				      min_value, max_value);
1436		break;
1437
1438	case SMU_OD_FAN_TARGET_TEMPERATURE:
1439		if (!smu_v13_0_7_is_od_feature_supported(smu,
1440							 PP_OD_FEATURE_FAN_CURVE_BIT))
1441			break;
1442
1443		size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n");
1444		size += sysfs_emit_at(buf, size, "%d\n",
1445					(int)od_table->OverDriveTable.FanTargetTemperature);
1446
1447		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1448		smu_v13_0_7_get_od_setting_limits(smu,
1449						  PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
1450						  &min_value,
1451						  &max_value);
1452		size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n",
1453				      min_value, max_value);
1454		break;
1455
1456	case SMU_OD_FAN_MINIMUM_PWM:
1457		if (!smu_v13_0_7_is_od_feature_supported(smu,
1458							 PP_OD_FEATURE_FAN_CURVE_BIT))
1459			break;
1460
1461		size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n");
1462		size += sysfs_emit_at(buf, size, "%d\n",
1463					(int)od_table->OverDriveTable.FanMinimumPwm);
1464
1465		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1466		smu_v13_0_7_get_od_setting_limits(smu,
1467						  PP_OD_FEATURE_FAN_MINIMUM_PWM,
1468						  &min_value,
1469						  &max_value);
1470		size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n",
1471				      min_value, max_value);
1472		break;
1473
1474	case SMU_OD_FAN_ZERO_RPM_ENABLE:
1475		if (!smu_v13_0_7_is_od_feature_supported(smu,
1476							 PP_OD_FEATURE_ZERO_FAN_BIT))
1477			break;
1478
1479		size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
1480		size += sysfs_emit_at(buf, size, "%d\n",
1481					(int)od_table->OverDriveTable.FanZeroRpmEnable);
1482
1483		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1484		smu_v13_0_7_get_od_setting_limits(smu,
1485						  PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
1486						  &min_value,
1487						  &max_value);
1488		size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
1489				      min_value, max_value);
1490		break;
1491
1492	case SMU_OD_FAN_ZERO_RPM_STOP_TEMP:
1493		if (!smu_v13_0_7_is_od_feature_supported(smu,
1494							 PP_OD_FEATURE_ZERO_FAN_BIT))
1495			break;
1496
1497		size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_STOP_TEMPERATURE:\n");
1498		size += sysfs_emit_at(buf, size, "%d\n",
1499					(int)od_table->OverDriveTable.FanZeroRpmStopTemp);
1500
1501		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1502		smu_v13_0_7_get_od_setting_limits(smu,
1503						  PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
1504						  &min_value,
1505						  &max_value);
1506		size += sysfs_emit_at(buf, size, "ZERO_RPM_STOP_TEMPERATURE: %u %u\n",
1507				      min_value, max_value);
1508		break;
1509
1510	case SMU_OD_RANGE:
1511		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
1512		    !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
1513		    !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1514			break;
1515
1516		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1517
1518		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
1519			smu_v13_0_7_get_od_setting_limits(smu,
1520							  PP_OD_FEATURE_GFXCLK_FMIN,
1521							  &min_value,
1522							  NULL);
1523			smu_v13_0_7_get_od_setting_limits(smu,
1524							  PP_OD_FEATURE_GFXCLK_FMAX,
1525							  NULL,
1526							  &max_value);
1527			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
1528					      min_value, max_value);
1529		}
1530
1531		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
1532			smu_v13_0_7_get_od_setting_limits(smu,
1533							  PP_OD_FEATURE_UCLK_FMIN,
1534							  &min_value,
1535							  NULL);
1536			smu_v13_0_7_get_od_setting_limits(smu,
1537							  PP_OD_FEATURE_UCLK_FMAX,
1538							  NULL,
1539							  &max_value);
1540			size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
1541					      min_value, max_value);
1542		}
1543
1544		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
1545			smu_v13_0_7_get_od_setting_limits(smu,
1546							  PP_OD_FEATURE_GFX_VF_CURVE,
1547							  &min_value,
1548							  &max_value);
1549			size += sysfs_emit_at(buf, size, "VDDGFX_OFFSET: %7dmv %10dmv\n",
1550					      min_value, max_value);
1551		}
1552		break;
1553
1554	default:
1555		break;
1556	}
1557
1558	return size - start_offset;
1559}
1560
1561static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long input)
1562{
1563	struct smu_table_context *table_context = &smu->smu_table;
1564	OverDriveTableExternal_t *boot_overdrive_table =
1565		(OverDriveTableExternal_t *)table_context->boot_overdrive_table;
1566	OverDriveTableExternal_t *od_table =
1567		(OverDriveTableExternal_t *)table_context->overdrive_table;
1568	struct amdgpu_device *adev = smu->adev;
1569	int i;
1570
1571	switch (input) {
1572	case PP_OD_EDIT_FAN_CURVE:
1573		for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) {
1574			od_table->OverDriveTable.FanLinearTempPoints[i] =
1575					boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i];
1576			od_table->OverDriveTable.FanLinearPwmPoints[i] =
1577					boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
1578		}
1579		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1580		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1581		break;
1582	case PP_OD_EDIT_ACOUSTIC_LIMIT:
1583		od_table->OverDriveTable.AcousticLimitRpmThreshold =
1584					boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
1585		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1586		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1587		break;
1588	case PP_OD_EDIT_ACOUSTIC_TARGET:
1589		od_table->OverDriveTable.AcousticTargetRpmThreshold =
1590					boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
1591		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1592		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1593		break;
1594	case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
1595		od_table->OverDriveTable.FanTargetTemperature =
1596					boot_overdrive_table->OverDriveTable.FanTargetTemperature;
1597		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1598		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1599		break;
1600	case PP_OD_EDIT_FAN_MINIMUM_PWM:
1601		od_table->OverDriveTable.FanMinimumPwm =
1602					boot_overdrive_table->OverDriveTable.FanMinimumPwm;
1603		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1604		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1605		break;
1606	case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
1607		od_table->OverDriveTable.FanZeroRpmEnable =
1608					boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
1609		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
1610		break;
1611	case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
1612		od_table->OverDriveTable.FanZeroRpmStopTemp =
1613					boot_overdrive_table->OverDriveTable.FanZeroRpmStopTemp;
1614		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
1615		break;
1616	default:
1617		dev_info(adev->dev, "Invalid table index: %ld\n", input);
1618		return -EINVAL;
1619	}
1620
1621	return 0;
1622}
1623
1624static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
1625					 enum PP_OD_DPM_TABLE_COMMAND type,
1626					 long input[],
1627					 uint32_t size)
1628{
1629	struct smu_table_context *table_context = &smu->smu_table;
1630	OverDriveTableExternal_t *od_table =
1631		(OverDriveTableExternal_t *)table_context->overdrive_table;
1632	struct amdgpu_device *adev = smu->adev;
1633	uint32_t offset_of_voltageoffset;
1634	int32_t minimum, maximum;
1635	uint32_t feature_ctrlmask;
1636	int i, ret = 0;
1637
1638	switch (type) {
1639	case PP_OD_EDIT_SCLK_VDDC_TABLE:
1640		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
1641			dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
1642			return -ENOTSUPP;
1643		}
1644
1645		for (i = 0; i < size; i += 2) {
1646			if (i + 2 > size) {
1647				dev_info(adev->dev, "invalid number of input parameters %d\n", size);
1648				return -EINVAL;
1649			}
1650
1651			switch (input[i]) {
1652			case 0:
1653				smu_v13_0_7_get_od_setting_limits(smu,
1654								  PP_OD_FEATURE_GFXCLK_FMIN,
1655								  &minimum,
1656								  &maximum);
1657				if (input[i + 1] < minimum ||
1658				    input[i + 1] > maximum) {
1659					dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n",
1660						input[i + 1], minimum, maximum);
1661					return -EINVAL;
1662				}
1663
1664				od_table->OverDriveTable.GfxclkFmin = input[i + 1];
1665				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
1666				break;
1667
1668			case 1:
1669				smu_v13_0_7_get_od_setting_limits(smu,
1670								  PP_OD_FEATURE_GFXCLK_FMAX,
1671								  &minimum,
1672								  &maximum);
1673				if (input[i + 1] < minimum ||
1674				    input[i + 1] > maximum) {
1675					dev_info(adev->dev, "GfxclkFmax (%ld) must be within [%u, %u]!\n",
1676						input[i + 1], minimum, maximum);
1677					return -EINVAL;
1678				}
1679
1680				od_table->OverDriveTable.GfxclkFmax = input[i + 1];
1681				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
1682				break;
1683
1684			default:
1685				dev_info(adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
1686				dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
1687				return -EINVAL;
1688			}
1689		}
1690
1691		if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) {
1692			dev_err(adev->dev,
1693				"Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n",
1694				(uint32_t)od_table->OverDriveTable.GfxclkFmin,
1695				(uint32_t)od_table->OverDriveTable.GfxclkFmax);
1696			return -EINVAL;
1697		}
1698		break;
1699
1700	case PP_OD_EDIT_MCLK_VDDC_TABLE:
1701		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
1702			dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
1703			return -ENOTSUPP;
1704		}
1705
1706		for (i = 0; i < size; i += 2) {
1707			if (i + 2 > size) {
1708				dev_info(adev->dev, "invalid number of input parameters %d\n", size);
1709				return -EINVAL;
1710			}
1711
1712			switch (input[i]) {
1713			case 0:
1714				smu_v13_0_7_get_od_setting_limits(smu,
1715								  PP_OD_FEATURE_UCLK_FMIN,
1716								  &minimum,
1717								  &maximum);
1718				if (input[i + 1] < minimum ||
1719				    input[i + 1] > maximum) {
1720					dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
1721						input[i + 1], minimum, maximum);
1722					return -EINVAL;
1723				}
1724
1725				od_table->OverDriveTable.UclkFmin = input[i + 1];
1726				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
1727				break;
1728
1729			case 1:
1730				smu_v13_0_7_get_od_setting_limits(smu,
1731								  PP_OD_FEATURE_UCLK_FMAX,
1732								  &minimum,
1733								  &maximum);
1734				if (input[i + 1] < minimum ||
1735				    input[i + 1] > maximum) {
1736					dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
1737						input[i + 1], minimum, maximum);
1738					return -EINVAL;
1739				}
1740
1741				od_table->OverDriveTable.UclkFmax = input[i + 1];
1742				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
1743				break;
1744
1745			default:
1746				dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
1747				dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
1748				return -EINVAL;
1749			}
1750		}
1751
1752		if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
1753			dev_err(adev->dev,
1754				"Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
1755				(uint32_t)od_table->OverDriveTable.UclkFmin,
1756				(uint32_t)od_table->OverDriveTable.UclkFmax);
1757			return -EINVAL;
1758		}
1759		break;
1760
1761	case PP_OD_EDIT_VDDGFX_OFFSET:
1762		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
1763			dev_warn(adev->dev, "Gfx offset setting not supported!\n");
1764			return -ENOTSUPP;
1765		}
1766
1767		smu_v13_0_7_get_od_setting_limits(smu,
1768						  PP_OD_FEATURE_GFX_VF_CURVE,
1769						  &minimum,
1770						  &maximum);
1771		if (input[0] < minimum ||
1772		    input[0] > maximum) {
1773			dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
1774				 input[0], minimum, maximum);
1775			return -EINVAL;
1776		}
1777
1778		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
1779			od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = input[0];
1780		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT);
1781		break;
1782
1783	case PP_OD_EDIT_FAN_CURVE:
1784		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
1785			dev_warn(adev->dev, "Fan curve setting not supported!\n");
1786			return -ENOTSUPP;
1787		}
1788
1789		if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 ||
1790		    input[0] < 0)
1791			return -EINVAL;
1792
1793		smu_v13_0_7_get_od_setting_limits(smu,
1794						  PP_OD_FEATURE_FAN_CURVE_TEMP,
1795						  &minimum,
1796						  &maximum);
1797		if (input[1] < minimum ||
1798		    input[1] > maximum) {
1799			dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n",
1800				 input[1], minimum, maximum);
1801			return -EINVAL;
1802		}
1803
1804		smu_v13_0_7_get_od_setting_limits(smu,
1805						  PP_OD_FEATURE_FAN_CURVE_PWM,
1806						  &minimum,
1807						  &maximum);
1808		if (input[2] < minimum ||
1809		    input[2] > maximum) {
1810			dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n",
1811				 input[2], minimum, maximum);
1812			return -EINVAL;
1813		}
1814
1815		od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1];
1816		od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2];
1817		od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR;
1818		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1819		break;
1820
1821	case PP_OD_EDIT_ACOUSTIC_LIMIT:
1822		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
1823			dev_warn(adev->dev, "Fan curve setting not supported!\n");
1824			return -ENOTSUPP;
1825		}
1826
1827		smu_v13_0_7_get_od_setting_limits(smu,
1828						  PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
1829						  &minimum,
1830						  &maximum);
1831		if (input[0] < minimum ||
1832		    input[0] > maximum) {
1833			dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n",
1834				 input[0], minimum, maximum);
1835			return -EINVAL;
1836		}
1837
1838		od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0];
1839		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1840		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1841		break;
1842
1843	case PP_OD_EDIT_ACOUSTIC_TARGET:
1844		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
1845			dev_warn(adev->dev, "Fan curve setting not supported!\n");
1846			return -ENOTSUPP;
1847		}
1848
1849		smu_v13_0_7_get_od_setting_limits(smu,
1850						  PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
1851						  &minimum,
1852						  &maximum);
1853		if (input[0] < minimum ||
1854		    input[0] > maximum) {
1855			dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n",
1856				 input[0], minimum, maximum);
1857			return -EINVAL;
1858		}
1859
1860		od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0];
1861		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1862		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1863		break;
1864
1865	case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
1866		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
1867			dev_warn(adev->dev, "Fan curve setting not supported!\n");
1868			return -ENOTSUPP;
1869		}
1870
1871		smu_v13_0_7_get_od_setting_limits(smu,
1872						  PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
1873						  &minimum,
1874						  &maximum);
1875		if (input[0] < minimum ||
1876		    input[0] > maximum) {
1877			dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n",
1878				 input[0], minimum, maximum);
1879			return -EINVAL;
1880		}
1881
1882		od_table->OverDriveTable.FanTargetTemperature = input[0];
1883		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1884		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1885		break;
1886
1887	case PP_OD_EDIT_FAN_MINIMUM_PWM:
1888		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
1889			dev_warn(adev->dev, "Fan curve setting not supported!\n");
1890			return -ENOTSUPP;
1891		}
1892
1893		smu_v13_0_7_get_od_setting_limits(smu,
1894						  PP_OD_FEATURE_FAN_MINIMUM_PWM,
1895						  &minimum,
1896						  &maximum);
1897		if (input[0] < minimum ||
1898		    input[0] > maximum) {
1899			dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n",
1900				 input[0], minimum, maximum);
1901			return -EINVAL;
1902		}
1903
1904		od_table->OverDriveTable.FanMinimumPwm = input[0];
1905		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
1906		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
1907		break;
1908
1909	case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
1910		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
1911			dev_warn(adev->dev, "Zero RPM setting not supported!\n");
1912			return -ENOTSUPP;
1913		}
1914
1915		smu_v13_0_7_get_od_setting_limits(smu,
1916						  PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
1917						  &minimum,
1918						  &maximum);
1919		if (input[0] < minimum ||
1920		    input[0] > maximum) {
1921			dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
1922				 input[0], minimum, maximum);
1923			return -EINVAL;
1924		}
1925
1926		od_table->OverDriveTable.FanZeroRpmEnable = input[0];
1927		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
1928		break;
1929
1930	case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
1931		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
1932			dev_warn(adev->dev, "Zero RPM setting not supported!\n");
1933			return -ENOTSUPP;
1934		}
1935
1936		smu_v13_0_7_get_od_setting_limits(smu,
1937						  PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
1938						  &minimum,
1939						  &maximum);
1940		if (input[0] < minimum ||
1941		    input[0] > maximum) {
1942			dev_info(adev->dev, "zero RPM stop temperature setting(%ld) must be within [%d, %d]!\n",
1943				 input[0], minimum, maximum);
1944			return -EINVAL;
1945		}
1946
1947		od_table->OverDriveTable.FanZeroRpmStopTemp = input[0];
1948		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
1949		break;
1950
1951	case PP_OD_RESTORE_DEFAULT_TABLE:
1952		if (size == 1) {
1953			ret = smu_v13_0_7_od_restore_table_single(smu, input[0]);
1954			if (ret)
1955				return ret;
1956		} else {
1957			feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
1958			memcpy(od_table,
1959					table_context->boot_overdrive_table,
1960					sizeof(OverDriveTableExternal_t));
1961			od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
1962		}
1963		fallthrough;
1964
1965	case PP_OD_COMMIT_DPM_TABLE:
1966		/*
1967		 * The member below instructs PMFW the settings focused in
1968		 * this single operation.
1969		 * `uint32_t FeatureCtrlMask;`
1970		 * It does not contain actual informations about user's custom
1971		 * settings. Thus we do not cache it.
1972		 */
1973		offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
1974		if (memcmp((u8 *)od_table + offset_of_voltageoffset,
1975			   table_context->user_overdrive_table + offset_of_voltageoffset,
1976			   sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
1977			smu_v13_0_7_dump_od_table(smu, od_table);
1978
1979			ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
1980			if (ret) {
1981				dev_err(adev->dev, "Failed to upload overdrive table!\n");
1982				return ret;
1983			}
1984
1985			od_table->OverDriveTable.FeatureCtrlMask = 0;
1986			memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
1987			       (u8 *)od_table + offset_of_voltageoffset,
1988			       sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
1989
1990			if (!memcmp(table_context->user_overdrive_table,
1991				    table_context->boot_overdrive_table,
1992				    sizeof(OverDriveTableExternal_t)))
1993				smu->user_dpm_profile.user_od = false;
1994			else
1995				smu->user_dpm_profile.user_od = true;
1996		}
1997		break;
1998
1999	default:
2000		return -ENOSYS;
2001	}
2002
2003	return ret;
2004}
2005
2006static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
2007					enum smu_clk_type clk_type,
2008					uint32_t mask)
2009{
2010	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
2011	struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
2012	struct smu_13_0_dpm_table *single_dpm_table;
2013	uint32_t soft_min_level, soft_max_level;
2014	uint32_t min_freq, max_freq;
2015	int ret = 0;
2016
2017	soft_min_level = mask ? (ffs(mask) - 1) : 0;
2018	soft_max_level = mask ? (fls(mask) - 1) : 0;
2019
2020	switch (clk_type) {
2021	case SMU_GFXCLK:
2022	case SMU_SCLK:
2023		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
2024		break;
2025	case SMU_MCLK:
2026	case SMU_UCLK:
2027		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
2028		break;
2029	case SMU_SOCCLK:
2030		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
2031		break;
2032	case SMU_FCLK:
2033		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
2034		break;
2035	case SMU_VCLK:
2036	case SMU_VCLK1:
2037		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
2038		break;
2039	case SMU_DCLK:
2040	case SMU_DCLK1:
2041		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
2042		break;
2043	default:
2044		break;
2045	}
2046
2047	switch (clk_type) {
2048	case SMU_GFXCLK:
2049	case SMU_SCLK:
2050	case SMU_MCLK:
2051	case SMU_UCLK:
2052	case SMU_SOCCLK:
2053	case SMU_FCLK:
2054	case SMU_VCLK:
2055	case SMU_VCLK1:
2056	case SMU_DCLK:
2057	case SMU_DCLK1:
2058		if (single_dpm_table->is_fine_grained) {
2059			/* There is only 2 levels for fine grained DPM */
2060			soft_max_level = (soft_max_level >= 1 ? 1 : 0);
2061			soft_min_level = (soft_min_level >= 1 ? 1 : 0);
2062		} else {
2063			if ((soft_max_level >= single_dpm_table->count) ||
2064			    (soft_min_level >= single_dpm_table->count))
2065				return -EINVAL;
2066		}
2067
2068		min_freq = single_dpm_table->dpm_levels[soft_min_level].value;
2069		max_freq = single_dpm_table->dpm_levels[soft_max_level].value;
2070
2071		ret = smu_v13_0_set_soft_freq_limited_range(smu,
2072							    clk_type,
2073							    min_freq,
2074							    max_freq,
2075							    false);
2076		break;
2077	case SMU_DCEFCLK:
2078	case SMU_PCIE:
2079	default:
2080		break;
2081	}
2082
2083	return ret;
2084}
2085
2086static const struct smu_temperature_range smu13_thermal_policy[] = {
2087	{-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
2088	{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
2089};
2090
2091static int smu_v13_0_7_get_thermal_temperature_range(struct smu_context *smu,
2092						     struct smu_temperature_range *range)
2093{
2094	struct smu_table_context *table_context = &smu->smu_table;
2095	struct smu_13_0_7_powerplay_table *powerplay_table =
2096		table_context->power_play_table;
2097	PPTable_t *pptable = smu->smu_table.driver_pptable;
2098
2099	if (!range)
2100		return -EINVAL;
2101
2102	memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
2103
2104	range->max = pptable->SkuTable.TemperatureLimit[TEMP_EDGE] *
2105		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2106	range->edge_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) *
2107		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2108	range->hotspot_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] *
2109		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2110	range->hotspot_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) *
2111		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2112	range->mem_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_MEM] *
2113		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2114	range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
2115		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2116	range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
2117	range->software_shutdown_temp_offset = pptable->SkuTable.FanAbnormalTempLimitOffset;
2118
2119	return 0;
2120}
2121
2122static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
2123					   void **table)
2124{
2125	struct smu_table_context *smu_table = &smu->smu_table;
2126	struct gpu_metrics_v1_3 *gpu_metrics =
2127		(struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
2128	SmuMetricsExternal_t metrics_ext;
2129	SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
2130	int ret = 0;
2131
2132	ret = smu_cmn_get_metrics_table(smu,
2133					&metrics_ext,
2134					true);
2135	if (ret)
2136		return ret;
2137
2138	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
2139
2140	gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE];
2141	gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT];
2142	gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM];
2143	gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX];
2144	gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC];
2145	gpu_metrics->temperature_vrmem = max(metrics->AvgTemperature[TEMP_VR_MEM0],
2146					     metrics->AvgTemperature[TEMP_VR_MEM1]);
2147
2148	gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
2149	gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
2150	gpu_metrics->average_mm_activity = max(metrics->Vcn0ActivityPercentage,
2151					       metrics->Vcn1ActivityPercentage);
2152
2153	gpu_metrics->average_socket_power = metrics->AverageSocketPower;
2154	gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ?
2155		metrics->EnergyAccumulator : UINT_MAX;
2156
2157	if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
2158		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
2159	else
2160		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
2161
2162	if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
2163		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
2164	else
2165		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
2166
2167	gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
2168	gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
2169	gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
2170	gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
2171
2172	gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
2173	gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
2174	gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
2175	gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
2176	gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
2177	gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
2178	gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
2179
2180	gpu_metrics->throttle_status =
2181			smu_v13_0_7_get_throttler_status(metrics);
2182	gpu_metrics->indep_throttle_status =
2183			smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
2184							   smu_v13_0_7_throttler_map);
2185
2186	gpu_metrics->current_fan_speed = metrics->AvgFanRpm;
2187
2188	gpu_metrics->pcie_link_width = metrics->PcieWidth;
2189	if ((metrics->PcieRate - 1) > LINK_SPEED_MAX)
2190		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(1);
2191	else
2192		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(metrics->PcieRate);
2193
2194	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
2195
2196	gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_GFX];
2197	gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_SOC];
2198	gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VMEMP];
2199
2200	*table = (void *)gpu_metrics;
2201
2202	return sizeof(struct gpu_metrics_v1_3);
2203}
2204
2205static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu)
2206{
2207	struct amdgpu_device *adev = smu->adev;
2208
2209	if (smu_v13_0_7_is_od_feature_supported(smu,
2210						PP_OD_FEATURE_FAN_CURVE_BIT))
2211		adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE |
2212					    OD_OPS_SUPPORT_FAN_CURVE_SET |
2213					    OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE |
2214					    OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET |
2215					    OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE |
2216					    OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET |
2217					    OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
2218					    OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
2219					    OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
2220					    OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
2221					    OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
2222					    OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET |
2223					    OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_RETRIEVE |
2224					    OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_SET;
2225}
2226
2227static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
2228{
2229	OverDriveTableExternal_t *od_table =
2230		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
2231	OverDriveTableExternal_t *boot_od_table =
2232		(OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
2233	OverDriveTableExternal_t *user_od_table =
2234		(OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
2235	OverDriveTableExternal_t user_od_table_bak;
2236	int ret = 0;
2237	int i;
2238
2239	ret = smu_v13_0_7_get_overdrive_table(smu, boot_od_table);
2240	if (ret)
2241		return ret;
2242
2243	smu_v13_0_7_dump_od_table(smu, boot_od_table);
2244
2245	memcpy(od_table,
2246	       boot_od_table,
2247	       sizeof(OverDriveTableExternal_t));
2248
2249	/*
2250	 * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
2251	 * but we have to preserve user defined values in "user_od_table".
2252	 */
2253	if (!smu->adev->in_suspend) {
2254		memcpy(user_od_table,
2255		       boot_od_table,
2256		       sizeof(OverDriveTableExternal_t));
2257		smu->user_dpm_profile.user_od = false;
2258	} else if (smu->user_dpm_profile.user_od) {
2259		memcpy(&user_od_table_bak,
2260		       user_od_table,
2261		       sizeof(OverDriveTableExternal_t));
2262		memcpy(user_od_table,
2263		       boot_od_table,
2264		       sizeof(OverDriveTableExternal_t));
2265		user_od_table->OverDriveTable.GfxclkFmin =
2266				user_od_table_bak.OverDriveTable.GfxclkFmin;
2267		user_od_table->OverDriveTable.GfxclkFmax =
2268				user_od_table_bak.OverDriveTable.GfxclkFmax;
2269		user_od_table->OverDriveTable.UclkFmin =
2270				user_od_table_bak.OverDriveTable.UclkFmin;
2271		user_od_table->OverDriveTable.UclkFmax =
2272				user_od_table_bak.OverDriveTable.UclkFmax;
2273		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
2274			user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
2275				user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
2276		for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) {
2277			user_od_table->OverDriveTable.FanLinearTempPoints[i] =
2278				user_od_table_bak.OverDriveTable.FanLinearTempPoints[i];
2279			user_od_table->OverDriveTable.FanLinearPwmPoints[i] =
2280				user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i];
2281		}
2282		user_od_table->OverDriveTable.AcousticLimitRpmThreshold =
2283			user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold;
2284		user_od_table->OverDriveTable.AcousticTargetRpmThreshold =
2285			user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold;
2286		user_od_table->OverDriveTable.FanTargetTemperature =
2287			user_od_table_bak.OverDriveTable.FanTargetTemperature;
2288		user_od_table->OverDriveTable.FanMinimumPwm =
2289			user_od_table_bak.OverDriveTable.FanMinimumPwm;
2290		user_od_table->OverDriveTable.FanZeroRpmEnable =
2291			user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
2292		user_od_table->OverDriveTable.FanZeroRpmStopTemp =
2293			user_od_table_bak.OverDriveTable.FanZeroRpmStopTemp;
2294	}
2295
2296	smu_v13_0_7_set_supported_od_feature_mask(smu);
2297
2298	return 0;
2299}
2300
2301static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu)
2302{
2303	struct smu_table_context *table_context = &smu->smu_table;
2304	OverDriveTableExternal_t *od_table = table_context->overdrive_table;
2305	OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
2306	int res;
2307
2308	user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) |
2309							BIT(PP_OD_FEATURE_UCLK_BIT) |
2310							BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) |
2311							BIT(PP_OD_FEATURE_FAN_CURVE_BIT) |
2312							BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
2313	res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table);
2314	user_od_table->OverDriveTable.FeatureCtrlMask = 0;
2315	if (res == 0)
2316		memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
2317
2318	return res;
2319}
2320
2321static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
2322{
2323	struct smu_13_0_dpm_context *dpm_context =
2324				smu->smu_dpm.dpm_context;
2325	struct smu_13_0_dpm_table *gfx_table =
2326				&dpm_context->dpm_tables.gfx_table;
2327	struct smu_13_0_dpm_table *mem_table =
2328				&dpm_context->dpm_tables.uclk_table;
2329	struct smu_13_0_dpm_table *soc_table =
2330				&dpm_context->dpm_tables.soc_table;
2331	struct smu_13_0_dpm_table *vclk_table =
2332				&dpm_context->dpm_tables.vclk_table;
2333	struct smu_13_0_dpm_table *dclk_table =
2334				&dpm_context->dpm_tables.dclk_table;
2335	struct smu_13_0_dpm_table *fclk_table =
2336				&dpm_context->dpm_tables.fclk_table;
2337	struct smu_umd_pstate_table *pstate_table =
2338				&smu->pstate_table;
2339	struct smu_table_context *table_context = &smu->smu_table;
2340	PPTable_t *pptable = table_context->driver_pptable;
2341	DriverReportedClocks_t driver_clocks =
2342		pptable->SkuTable.DriverReportedClocks;
2343
2344	pstate_table->gfxclk_pstate.min = gfx_table->min;
2345	if (driver_clocks.GameClockAc &&
2346		(driver_clocks.GameClockAc < gfx_table->max))
2347		pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc;
2348	else
2349		pstate_table->gfxclk_pstate.peak = gfx_table->max;
2350
2351	pstate_table->uclk_pstate.min = mem_table->min;
2352	pstate_table->uclk_pstate.peak = mem_table->max;
2353
2354	pstate_table->socclk_pstate.min = soc_table->min;
2355	pstate_table->socclk_pstate.peak = soc_table->max;
2356
2357	pstate_table->vclk_pstate.min = vclk_table->min;
2358	pstate_table->vclk_pstate.peak = vclk_table->max;
2359
2360	pstate_table->dclk_pstate.min = dclk_table->min;
2361	pstate_table->dclk_pstate.peak = dclk_table->max;
2362
2363	pstate_table->fclk_pstate.min = fclk_table->min;
2364	pstate_table->fclk_pstate.peak = fclk_table->max;
2365
2366	if (driver_clocks.BaseClockAc &&
2367		driver_clocks.BaseClockAc < gfx_table->max)
2368		pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc;
2369	else
2370		pstate_table->gfxclk_pstate.standard = gfx_table->max;
2371	pstate_table->uclk_pstate.standard = mem_table->max;
2372	pstate_table->socclk_pstate.standard = soc_table->min;
2373	pstate_table->vclk_pstate.standard = vclk_table->min;
2374	pstate_table->dclk_pstate.standard = dclk_table->min;
2375	pstate_table->fclk_pstate.standard = fclk_table->min;
2376
2377	return 0;
2378}
2379
2380static int smu_v13_0_7_get_fan_speed_pwm(struct smu_context *smu,
2381					 uint32_t *speed)
2382{
2383	int ret;
2384
2385	if (!speed)
2386		return -EINVAL;
2387
2388	ret = smu_v13_0_7_get_smu_metrics_data(smu,
2389					       METRICS_CURR_FANPWM,
2390					       speed);
2391	if (ret) {
2392		dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!");
2393		return ret;
2394	}
2395
2396	/* Convert the PMFW output which is in percent to pwm(255) based */
2397	*speed = min(*speed * 255 / 100, (uint32_t)255);
2398
2399	return 0;
2400}
2401
2402static int smu_v13_0_7_get_fan_speed_rpm(struct smu_context *smu,
2403					 uint32_t *speed)
2404{
2405	if (!speed)
2406		return -EINVAL;
2407
2408	return smu_v13_0_7_get_smu_metrics_data(smu,
2409						METRICS_CURR_FANSPEED,
2410						speed);
2411}
2412
2413static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
2414{
2415	struct smu_table_context *table_context = &smu->smu_table;
2416	PPTable_t *pptable = table_context->driver_pptable;
2417	SkuTable_t *skutable = &pptable->SkuTable;
2418
2419	/*
2420	 * Skip the MGpuFanBoost setting for those ASICs
2421	 * which do not support it
2422	 */
2423	if (skutable->MGpuAcousticLimitRpmThreshold == 0)
2424		return 0;
2425
2426	return smu_cmn_send_smc_msg_with_param(smu,
2427					       SMU_MSG_SetMGpuFanBoostLimitRpm,
2428					       0,
2429					       NULL);
2430}
2431
2432static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
2433						uint32_t *current_power_limit,
2434						uint32_t *default_power_limit,
2435						uint32_t *max_power_limit,
2436						uint32_t *min_power_limit)
2437{
2438	struct smu_table_context *table_context = &smu->smu_table;
2439	struct smu_13_0_7_powerplay_table *powerplay_table =
2440		(struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
2441	PPTable_t *pptable = table_context->driver_pptable;
2442	SkuTable_t *skutable = &pptable->SkuTable;
2443	uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
2444	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
2445
2446	if (smu_v13_0_get_current_power_limit(smu, &power_limit))
2447		power_limit = smu->adev->pm.ac_power ?
2448			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
2449			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
2450
2451	if (current_power_limit)
2452		*current_power_limit = power_limit;
2453	if (default_power_limit)
2454		*default_power_limit = power_limit;
2455
2456	if (powerplay_table) {
2457		if (smu->od_enabled &&
2458				(smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT))) {
2459			od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
2460			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
2461		} else if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
2462			od_percent_upper = 0;
2463			od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
2464		}
2465	}
2466
2467	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
2468					od_percent_upper, od_percent_lower, power_limit);
2469
2470	if (max_power_limit) {
2471		*max_power_limit = msg_limit * (100 + od_percent_upper);
2472		*max_power_limit /= 100;
2473	}
2474
2475	if (min_power_limit) {
2476		*min_power_limit = power_limit * (100 - od_percent_lower);
2477		*min_power_limit /= 100;
2478	}
2479
2480	return 0;
2481}
2482
2483static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf)
2484{
2485	DpmActivityMonitorCoeffIntExternal_t *activity_monitor_external;
2486	uint32_t i, j, size = 0;
2487	int16_t workload_type = 0;
2488	int result = 0;
2489
2490	if (!buf)
2491		return -EINVAL;
2492
2493	activity_monitor_external = kcalloc(PP_SMC_POWER_PROFILE_COUNT,
2494					    sizeof(*activity_monitor_external),
2495					    GFP_KERNEL);
2496	if (!activity_monitor_external)
2497		return -ENOMEM;
2498
2499	size += sysfs_emit_at(buf, size, "                              ");
2500	for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++)
2501		size += sysfs_emit_at(buf, size, "%d %-14s%s", i, amdgpu_pp_profile_name[i],
2502			(i == smu->power_profile_mode) ? "* " : "  ");
2503
2504	size += sysfs_emit_at(buf, size, "\n");
2505
2506	for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) {
2507		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
2508		workload_type = smu_cmn_to_asic_specific_index(smu,
2509							       CMN2ASIC_MAPPING_WORKLOAD,
2510							       i);
2511		if (workload_type == -ENOTSUPP)
2512			continue;
2513		else if (workload_type < 0) {
2514			result = -EINVAL;
2515			goto out;
2516		}
2517
2518		result = smu_cmn_update_table(smu,
2519					  SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
2520					  (void *)(&activity_monitor_external[i]), false);
2521		if (result) {
2522			dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2523			goto out;
2524		}
2525	}
2526
2527#define PRINT_DPM_MONITOR(field)									\
2528do {													\
2529	size += sysfs_emit_at(buf, size, "%-30s", #field);						\
2530	for (j = 0; j <= PP_SMC_POWER_PROFILE_WINDOW3D; j++)						\
2531		size += sysfs_emit_at(buf, size, "%-18d", activity_monitor_external[j].DpmActivityMonitorCoeffInt.field);		\
2532	size += sysfs_emit_at(buf, size, "\n");								\
2533} while (0)
2534
2535	PRINT_DPM_MONITOR(Gfx_ActiveHystLimit);
2536	PRINT_DPM_MONITOR(Gfx_IdleHystLimit);
2537	PRINT_DPM_MONITOR(Gfx_FPS);
2538	PRINT_DPM_MONITOR(Gfx_MinActiveFreqType);
2539	PRINT_DPM_MONITOR(Gfx_BoosterFreqType);
2540	PRINT_DPM_MONITOR(Gfx_MinActiveFreq);
2541	PRINT_DPM_MONITOR(Gfx_BoosterFreq);
2542	PRINT_DPM_MONITOR(Fclk_ActiveHystLimit);
2543	PRINT_DPM_MONITOR(Fclk_IdleHystLimit);
2544	PRINT_DPM_MONITOR(Fclk_FPS);
2545	PRINT_DPM_MONITOR(Fclk_MinActiveFreqType);
2546	PRINT_DPM_MONITOR(Fclk_BoosterFreqType);
2547	PRINT_DPM_MONITOR(Fclk_MinActiveFreq);
2548	PRINT_DPM_MONITOR(Fclk_BoosterFreq);
2549#undef PRINT_DPM_MONITOR
2550
2551	result = size;
2552out:
2553	kfree(activity_monitor_external);
2554	return result;
2555}
2556
2557#define SMU_13_0_7_CUSTOM_PARAMS_COUNT 8
2558#define SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT 2
2559#define SMU_13_0_7_CUSTOM_PARAMS_SIZE (SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT * SMU_13_0_7_CUSTOM_PARAMS_COUNT * sizeof(long))
2560
2561static int smu_v13_0_7_set_power_profile_mode_coeff(struct smu_context *smu,
2562						    long *input)
2563{
2564
2565	DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
2566	DpmActivityMonitorCoeffInt_t *activity_monitor =
2567		&(activity_monitor_external.DpmActivityMonitorCoeffInt);
2568	int ret, idx;
2569
2570	ret = smu_cmn_update_table(smu,
2571				   SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2572				   (void *)(&activity_monitor_external), false);
2573	if (ret) {
2574		dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2575		return ret;
2576	}
2577
2578	idx = 0 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2579	if (input[idx]) {
2580		/* Gfxclk */
2581		activity_monitor->Gfx_ActiveHystLimit = input[idx + 1];
2582		activity_monitor->Gfx_IdleHystLimit = input[idx + 2];
2583		activity_monitor->Gfx_FPS = input[idx + 3];
2584		activity_monitor->Gfx_MinActiveFreqType = input[idx + 4];
2585		activity_monitor->Gfx_BoosterFreqType = input[idx + 5];
2586		activity_monitor->Gfx_MinActiveFreq = input[idx + 6];
2587		activity_monitor->Gfx_BoosterFreq = input[idx + 7];
2588	}
2589	idx = 1 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2590	if (input[idx]) {
2591		/* Fclk */
2592		activity_monitor->Fclk_ActiveHystLimit = input[idx + 1];
2593		activity_monitor->Fclk_IdleHystLimit = input[idx + 2];
2594		activity_monitor->Fclk_FPS = input[idx + 3];
2595		activity_monitor->Fclk_MinActiveFreqType = input[idx + 4];
2596		activity_monitor->Fclk_BoosterFreqType = input[idx + 5];
2597		activity_monitor->Fclk_MinActiveFreq = input[idx + 6];
2598		activity_monitor->Fclk_BoosterFreq = input[idx + 7];
2599	}
2600
2601	ret = smu_cmn_update_table(smu,
2602				   SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2603				   (void *)(&activity_monitor_external), true);
2604	if (ret) {
2605		dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2606		return ret;
2607	}
2608
2609	return ret;
2610}
2611
2612static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
2613					      u32 workload_mask,
2614					      long *custom_params,
2615					      u32 custom_params_max_idx)
2616{
2617	u32 backend_workload_mask = 0;
2618	int ret, idx = -1, i;
2619
2620	smu_cmn_get_backend_workload_mask(smu, workload_mask,
2621					  &backend_workload_mask);
2622
2623	if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
2624		if (!smu->custom_profile_params) {
2625			smu->custom_profile_params =
2626				kzalloc(SMU_13_0_7_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
2627			if (!smu->custom_profile_params)
2628				return -ENOMEM;
2629		}
2630		if (custom_params && custom_params_max_idx) {
2631			if (custom_params_max_idx != SMU_13_0_7_CUSTOM_PARAMS_COUNT)
2632				return -EINVAL;
2633			if (custom_params[0] >= SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT)
2634				return -EINVAL;
2635			idx = custom_params[0] * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2636			smu->custom_profile_params[idx] = 1;
2637			for (i = 1; i < custom_params_max_idx; i++)
2638				smu->custom_profile_params[idx + i] = custom_params[i];
2639		}
2640		ret = smu_v13_0_7_set_power_profile_mode_coeff(smu,
2641							       smu->custom_profile_params);
2642		if (ret) {
2643			if (idx != -1)
2644				smu->custom_profile_params[idx] = 0;
2645			return ret;
2646		}
2647	} else if (smu->custom_profile_params) {
2648		memset(smu->custom_profile_params, 0, SMU_13_0_7_CUSTOM_PARAMS_SIZE);
2649	}
2650
2651	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
2652					      backend_workload_mask, NULL);
2653
2654	if (ret) {
2655		dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
2656			workload_mask);
2657		if (idx != -1)
2658			smu->custom_profile_params[idx] = 0;
2659		return ret;
2660	}
2661
2662	return ret;
2663}
2664
2665static int smu_v13_0_7_set_mp1_state(struct smu_context *smu,
2666				     enum pp_mp1_state mp1_state)
2667{
2668	int ret;
2669
2670	switch (mp1_state) {
2671	case PP_MP1_STATE_UNLOAD:
2672		ret = smu_cmn_set_mp1_state(smu, mp1_state);
2673		break;
2674	default:
2675		/* Ignore others */
2676		ret = 0;
2677	}
2678
2679	return ret;
2680}
2681
2682static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu)
2683{
2684	struct amdgpu_device *adev = smu->adev;
2685
2686	/* SRIOV does not support SMU mode1 reset */
2687	if (amdgpu_sriov_vf(adev))
2688		return false;
2689
2690	return true;
2691}
2692
2693static int smu_v13_0_7_set_df_cstate(struct smu_context *smu,
2694				     enum pp_df_cstate state)
2695{
2696	return smu_cmn_send_smc_msg_with_param(smu,
2697					       SMU_MSG_DFCstateControl,
2698					       state,
2699					       NULL);
2700}
2701
2702static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu)
2703{
2704	return smu->smc_fw_version > 0x00524600;
2705}
2706
2707static int smu_v13_0_7_set_power_limit(struct smu_context *smu,
2708				       enum smu_ppt_limit_type limit_type,
2709				       uint32_t limit)
2710{
2711	PPTable_t *pptable = smu->smu_table.driver_pptable;
2712	SkuTable_t *skutable = &pptable->SkuTable;
2713	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
2714	struct smu_table_context *table_context = &smu->smu_table;
2715	OverDriveTableExternal_t *od_table =
2716		(OverDriveTableExternal_t *)table_context->overdrive_table;
2717	int ret = 0;
2718
2719	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
2720		return -EINVAL;
2721
2722	if (limit <= msg_limit) {
2723		if (smu->current_power_limit > msg_limit) {
2724			od_table->OverDriveTable.Ppt = 0;
2725			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
2726
2727			ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
2728			if (ret) {
2729				dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
2730				return ret;
2731			}
2732		}
2733		return smu_v13_0_set_power_limit(smu, limit_type, limit);
2734	} else if (smu->od_enabled) {
2735		ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit);
2736		if (ret)
2737			return ret;
2738
2739		od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
2740		od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
2741
2742		ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
2743		if (ret) {
2744		  dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
2745		  return ret;
2746		}
2747
2748		smu->current_power_limit = limit;
2749	} else {
2750		return -EINVAL;
2751	}
2752
2753	return 0;
2754}
2755
2756static int smu_v13_0_7_update_pcie_parameters(struct smu_context *smu,
2757				     uint8_t pcie_gen_cap,
2758				     uint8_t pcie_width_cap)
2759{
2760	struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
2761	struct smu_13_0_pcie_table *pcie_table =
2762				&dpm_context->dpm_tables.pcie_table;
2763	int num_of_levels;
2764	int link_level;
2765	uint32_t smu_pcie_arg;
2766	struct smu_table_context *table_context = &smu->smu_table;
2767	PPTable_t *pptable = table_context->driver_pptable;
2768	SkuTable_t *skutable = &pptable->SkuTable;
2769	int ret = 0;
2770	int i;
2771
2772	pcie_table->num_of_link_levels = 0;
2773	for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) {
2774		if (!skutable->PcieGenSpeed[link_level] &&
2775		    !skutable->PcieLaneCount[link_level] &&
2776		    !skutable->LclkFreq[link_level])
2777			continue;
2778
2779		pcie_table->pcie_gen[pcie_table->num_of_link_levels] =
2780					skutable->PcieGenSpeed[link_level];
2781		pcie_table->pcie_lane[pcie_table->num_of_link_levels] =
2782					skutable->PcieLaneCount[link_level];
2783		pcie_table->clk_freq[pcie_table->num_of_link_levels] =
2784					skutable->LclkFreq[link_level];
2785		pcie_table->num_of_link_levels++;
2786	}
2787
2788	num_of_levels = pcie_table->num_of_link_levels;
2789	if (!num_of_levels)
2790		return 0;
2791
2792	if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
2793		if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
2794			pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
2795
2796		if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
2797			pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
2798
2799		/* Force all levels to use the same settings */
2800		for (i = 0; i < num_of_levels; i++) {
2801			pcie_table->pcie_gen[i] = pcie_gen_cap;
2802			pcie_table->pcie_lane[i] = pcie_width_cap;
2803			smu_pcie_arg = i << 16;
2804			smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
2805			smu_pcie_arg |= pcie_table->pcie_lane[i];
2806
2807			ret = smu_cmn_send_smc_msg_with_param(smu,
2808								SMU_MSG_OverridePcieParameters,
2809								smu_pcie_arg,
2810								NULL);
2811			if (ret)
2812				break;
2813		}
2814	} else {
2815		for (i = 0; i < num_of_levels; i++) {
2816			if (pcie_table->pcie_gen[i] > pcie_gen_cap ||
2817				pcie_table->pcie_lane[i] > pcie_width_cap) {
2818				pcie_table->pcie_gen[i] = pcie_table->pcie_gen[i] > pcie_gen_cap ?
2819										  pcie_gen_cap : pcie_table->pcie_gen[i];
2820				pcie_table->pcie_lane[i] = pcie_table->pcie_lane[i] > pcie_width_cap ?
2821										   pcie_width_cap : pcie_table->pcie_lane[i];
2822				smu_pcie_arg = i << 16;
2823				smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
2824				smu_pcie_arg |= pcie_table->pcie_lane[i];
2825
2826				ret = smu_cmn_send_smc_msg_with_param(smu,
2827									SMU_MSG_OverridePcieParameters,
2828									smu_pcie_arg,
2829									NULL);
2830				if (ret)
2831					break;
2832			}
2833		}
2834	}
2835
2836	return ret;
2837}
2838
2839static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
2840	.get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
2841	.set_default_dpm_table = smu_v13_0_7_set_default_dpm_table,
2842	.is_dpm_running = smu_v13_0_7_is_dpm_running,
2843	.init_microcode = smu_v13_0_init_microcode,
2844	.load_microcode = smu_v13_0_load_microcode,
2845	.fini_microcode = smu_v13_0_fini_microcode,
2846	.init_smc_tables = smu_v13_0_7_init_smc_tables,
2847	.fini_smc_tables = smu_v13_0_fini_smc_tables,
2848	.init_power = smu_v13_0_init_power,
2849	.fini_power = smu_v13_0_fini_power,
2850	.check_fw_status = smu_v13_0_7_check_fw_status,
2851	.setup_pptable = smu_v13_0_7_setup_pptable,
2852	.check_fw_version = smu_v13_0_check_fw_version,
2853	.write_pptable = smu_cmn_write_pptable,
2854	.set_driver_table_location = smu_v13_0_set_driver_table_location,
2855	.system_features_control = smu_v13_0_system_features_control,
2856	.set_allowed_mask = smu_v13_0_set_allowed_mask,
2857	.get_enabled_mask = smu_cmn_get_enabled_mask,
2858	.dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
2859	.dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
2860	.init_pptable_microcode = smu_v13_0_init_pptable_microcode,
2861	.populate_umd_state_clk = smu_v13_0_7_populate_umd_state_clk,
2862	.get_dpm_ultimate_freq = smu_v13_0_7_get_dpm_ultimate_freq,
2863	.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
2864	.read_sensor = smu_v13_0_7_read_sensor,
2865	.feature_is_enabled = smu_cmn_feature_is_enabled,
2866	.print_clk_levels = smu_v13_0_7_print_clk_levels,
2867	.force_clk_levels = smu_v13_0_7_force_clk_levels,
2868	.update_pcie_parameters = smu_v13_0_7_update_pcie_parameters,
2869	.get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range,
2870	.register_irq_handler = smu_v13_0_register_irq_handler,
2871	.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
2872	.disable_thermal_alert = smu_v13_0_disable_thermal_alert,
2873	.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
2874	.get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
2875	.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
2876	.set_default_od_settings = smu_v13_0_7_set_default_od_settings,
2877	.restore_user_od_settings = smu_v13_0_7_restore_user_od_settings,
2878	.od_edit_dpm_table = smu_v13_0_7_od_edit_dpm_table,
2879	.set_performance_level = smu_v13_0_set_performance_level,
2880	.gfx_off_control = smu_v13_0_gfx_off_control,
2881	.get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
2882	.get_fan_speed_rpm = smu_v13_0_7_get_fan_speed_rpm,
2883	.set_fan_speed_pwm = smu_v13_0_set_fan_speed_pwm,
2884	.set_fan_speed_rpm = smu_v13_0_set_fan_speed_rpm,
2885	.get_fan_control_mode = smu_v13_0_get_fan_control_mode,
2886	.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
2887	.enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
2888	.get_power_limit = smu_v13_0_7_get_power_limit,
2889	.set_power_limit = smu_v13_0_7_set_power_limit,
2890	.set_power_source = smu_v13_0_set_power_source,
2891	.get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
2892	.set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
2893	.set_tool_table_location = smu_v13_0_set_tool_table_location,
2894	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2895	.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
2896	.get_bamaco_support = smu_v13_0_get_bamaco_support,
2897	.baco_enter = smu_v13_0_baco_enter,
2898	.baco_exit = smu_v13_0_baco_exit,
2899	.mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported,
2900	.mode1_reset = smu_v13_0_mode1_reset,
2901	.set_mp1_state = smu_v13_0_7_set_mp1_state,
2902	.set_df_cstate = smu_v13_0_7_set_df_cstate,
2903	.gpo_control = smu_v13_0_gpo_control,
2904	.is_asic_wbrf_supported = smu_v13_0_7_wbrf_support_check,
2905	.enable_uclk_shadow = smu_v13_0_enable_uclk_shadow,
2906	.set_wbrf_exclusion_ranges = smu_v13_0_set_wbrf_exclusion_ranges,
2907	.interrupt_work = smu_v13_0_interrupt_work,
2908};
2909
2910void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
2911{
2912	smu->ppt_funcs = &smu_v13_0_7_ppt_funcs;
2913	smu->message_map = smu_v13_0_7_message_map;
2914	smu->clock_map = smu_v13_0_7_clk_map;
2915	smu->feature_map = smu_v13_0_7_feature_mask_map;
2916	smu->table_map = smu_v13_0_7_table_map;
2917	smu->pwr_src_map = smu_v13_0_7_pwr_src_map;
2918	smu->workload_map = smu_v13_0_7_workload_map;
2919	smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
2920	smu_v13_0_set_smu_mailbox_registers(smu);
2921}
~/ Read-only file preview.