11bb76ff1Sjsg /*
21bb76ff1Sjsg  * Copyright 2021 Advanced Micro Devices, Inc.
31bb76ff1Sjsg  *
41bb76ff1Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
51bb76ff1Sjsg  * copy of this software and associated documentation files (the "Software"),
61bb76ff1Sjsg  * to deal in the Software without restriction, including without limitation
71bb76ff1Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81bb76ff1Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
91bb76ff1Sjsg  * Software is furnished to do so, subject to the following conditions:
101bb76ff1Sjsg  *
111bb76ff1Sjsg  * The above copyright notice and this permission notice shall be included in
121bb76ff1Sjsg  * all copies or substantial portions of the Software.
131bb76ff1Sjsg  *
141bb76ff1Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151bb76ff1Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
161bb76ff1Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
171bb76ff1Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
181bb76ff1Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191bb76ff1Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201bb76ff1Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
211bb76ff1Sjsg  *
221bb76ff1Sjsg  */
231bb76ff1Sjsg 
241bb76ff1Sjsg #define SWSMU_CODE_LAYER_L2
251bb76ff1Sjsg 
261bb76ff1Sjsg #include <linux/firmware.h>
271bb76ff1Sjsg #include <linux/pci.h>
281bb76ff1Sjsg #include <linux/i2c.h>
291bb76ff1Sjsg #include "amdgpu.h"
301bb76ff1Sjsg #include "amdgpu_smu.h"
311bb76ff1Sjsg #include "atomfirmware.h"
321bb76ff1Sjsg #include "amdgpu_atomfirmware.h"
331bb76ff1Sjsg #include "amdgpu_atombios.h"
341bb76ff1Sjsg #include "smu_v13_0.h"
351bb76ff1Sjsg #include "smu13_driver_if_v13_0_7.h"
361bb76ff1Sjsg #include "soc15_common.h"
371bb76ff1Sjsg #include "atom.h"
381bb76ff1Sjsg #include "smu_v13_0_7_ppt.h"
391bb76ff1Sjsg #include "smu_v13_0_7_pptable.h"
401bb76ff1Sjsg #include "smu_v13_0_7_ppsmc.h"
411bb76ff1Sjsg #include "nbio/nbio_4_3_0_offset.h"
421bb76ff1Sjsg #include "nbio/nbio_4_3_0_sh_mask.h"
431bb76ff1Sjsg #include "mp/mp_13_0_0_offset.h"
441bb76ff1Sjsg #include "mp/mp_13_0_0_sh_mask.h"
451bb76ff1Sjsg 
461bb76ff1Sjsg #include "asic_reg/mp/mp_13_0_0_sh_mask.h"
471bb76ff1Sjsg #include "smu_cmn.h"
481bb76ff1Sjsg #include "amdgpu_ras.h"
491bb76ff1Sjsg 
501bb76ff1Sjsg /*
511bb76ff1Sjsg  * DO NOT use these for err/warn/info/debug messages.
521bb76ff1Sjsg  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
531bb76ff1Sjsg  * They are more MGPU friendly.
541bb76ff1Sjsg  */
551bb76ff1Sjsg #undef pr_err
561bb76ff1Sjsg #undef pr_warn
571bb76ff1Sjsg #undef pr_info
581bb76ff1Sjsg #undef pr_debug
591bb76ff1Sjsg 
601bb76ff1Sjsg #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
611bb76ff1Sjsg 
621bb76ff1Sjsg #define FEATURE_MASK(feature) (1ULL << feature)
631bb76ff1Sjsg #define SMC_DPM_FEATURE ( \
641bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
651bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_UCLK_BIT)	 | \
661bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
671bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
681bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_FCLK_BIT)	 | \
691bb76ff1Sjsg 	FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT))
701bb76ff1Sjsg 
711bb76ff1Sjsg #define smnMP1_FIRMWARE_FLAGS_SMU_13_0_7   0x3b10028
721bb76ff1Sjsg 
731bb76ff1Sjsg #define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE	0x4000
741bb76ff1Sjsg 
75*f005ef32Sjsg #define PP_OD_FEATURE_GFXCLK_FMIN			0
76*f005ef32Sjsg #define PP_OD_FEATURE_GFXCLK_FMAX			1
77*f005ef32Sjsg #define PP_OD_FEATURE_UCLK_FMIN				2
78*f005ef32Sjsg #define PP_OD_FEATURE_UCLK_FMAX				3
79*f005ef32Sjsg #define PP_OD_FEATURE_GFX_VF_CURVE			4
80*f005ef32Sjsg 
81*f005ef32Sjsg #define LINK_SPEED_MAX					3
82*f005ef32Sjsg 
831bb76ff1Sjsg static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] = {
841bb76ff1Sjsg 	MSG_MAP(TestMessage,			PPSMC_MSG_TestMessage,                 1),
851bb76ff1Sjsg 	MSG_MAP(GetSmuVersion,			PPSMC_MSG_GetSmuVersion,               1),
861bb76ff1Sjsg 	MSG_MAP(GetDriverIfVersion,		PPSMC_MSG_GetDriverIfVersion,          1),
871bb76ff1Sjsg 	MSG_MAP(SetAllowedFeaturesMaskLow,	PPSMC_MSG_SetAllowedFeaturesMaskLow,   0),
881bb76ff1Sjsg 	MSG_MAP(SetAllowedFeaturesMaskHigh,	PPSMC_MSG_SetAllowedFeaturesMaskHigh,  0),
891bb76ff1Sjsg 	MSG_MAP(EnableAllSmuFeatures,		PPSMC_MSG_EnableAllSmuFeatures,        0),
901bb76ff1Sjsg 	MSG_MAP(DisableAllSmuFeatures,		PPSMC_MSG_DisableAllSmuFeatures,       0),
911bb76ff1Sjsg 	MSG_MAP(EnableSmuFeaturesLow,		PPSMC_MSG_EnableSmuFeaturesLow,        1),
921bb76ff1Sjsg 	MSG_MAP(EnableSmuFeaturesHigh,		PPSMC_MSG_EnableSmuFeaturesHigh,       1),
931bb76ff1Sjsg 	MSG_MAP(DisableSmuFeaturesLow,		PPSMC_MSG_DisableSmuFeaturesLow,       1),
941bb76ff1Sjsg 	MSG_MAP(DisableSmuFeaturesHigh,		PPSMC_MSG_DisableSmuFeaturesHigh,      1),
951bb76ff1Sjsg 	MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetRunningSmuFeaturesLow,    1),
961bb76ff1Sjsg 	MSG_MAP(GetEnabledSmuFeaturesHigh,	PPSMC_MSG_GetRunningSmuFeaturesHigh,   1),
971bb76ff1Sjsg 	MSG_MAP(SetWorkloadMask,		PPSMC_MSG_SetWorkloadMask,             1),
981bb76ff1Sjsg 	MSG_MAP(SetPptLimit,			PPSMC_MSG_SetPptLimit,                 0),
991bb76ff1Sjsg 	MSG_MAP(SetDriverDramAddrHigh,		PPSMC_MSG_SetDriverDramAddrHigh,       1),
1001bb76ff1Sjsg 	MSG_MAP(SetDriverDramAddrLow,		PPSMC_MSG_SetDriverDramAddrLow,        1),
1011bb76ff1Sjsg 	MSG_MAP(SetToolsDramAddrHigh,		PPSMC_MSG_SetToolsDramAddrHigh,        0),
1021bb76ff1Sjsg 	MSG_MAP(SetToolsDramAddrLow,		PPSMC_MSG_SetToolsDramAddrLow,         0),
1031bb76ff1Sjsg 	MSG_MAP(TransferTableSmu2Dram,		PPSMC_MSG_TransferTableSmu2Dram,       1),
1041bb76ff1Sjsg 	MSG_MAP(TransferTableDram2Smu,		PPSMC_MSG_TransferTableDram2Smu,       0),
1051bb76ff1Sjsg 	MSG_MAP(UseDefaultPPTable,		PPSMC_MSG_UseDefaultPPTable,           0),
1061bb76ff1Sjsg 	MSG_MAP(RunDcBtc,			PPSMC_MSG_RunDcBtc,                    0),
1071bb76ff1Sjsg 	MSG_MAP(EnterBaco,			PPSMC_MSG_EnterBaco,                   0),
1081bb76ff1Sjsg 	MSG_MAP(ExitBaco,           PPSMC_MSG_ExitBaco,        			   0),
1091bb76ff1Sjsg 	MSG_MAP(SetSoftMinByFreq,		PPSMC_MSG_SetSoftMinByFreq,            1),
1101bb76ff1Sjsg 	MSG_MAP(SetSoftMaxByFreq,		PPSMC_MSG_SetSoftMaxByFreq,            1),
1111bb76ff1Sjsg 	MSG_MAP(SetHardMinByFreq,		PPSMC_MSG_SetHardMinByFreq,            1),
1121bb76ff1Sjsg 	MSG_MAP(SetHardMaxByFreq,		PPSMC_MSG_SetHardMaxByFreq,            0),
1131bb76ff1Sjsg 	MSG_MAP(GetMinDpmFreq,			PPSMC_MSG_GetMinDpmFreq,               1),
1141bb76ff1Sjsg 	MSG_MAP(GetMaxDpmFreq,			PPSMC_MSG_GetMaxDpmFreq,               1),
1151bb76ff1Sjsg 	MSG_MAP(GetDpmFreqByIndex,		PPSMC_MSG_GetDpmFreqByIndex,           1),
1161bb76ff1Sjsg 	MSG_MAP(PowerUpVcn,				PPSMC_MSG_PowerUpVcn,                  0),
1171bb76ff1Sjsg 	MSG_MAP(PowerDownVcn,			PPSMC_MSG_PowerDownVcn,                0),
1181bb76ff1Sjsg 	MSG_MAP(PowerUpJpeg,			PPSMC_MSG_PowerUpJpeg,                 0),
1191bb76ff1Sjsg 	MSG_MAP(PowerDownJpeg,			PPSMC_MSG_PowerDownJpeg,               0),
1201bb76ff1Sjsg 	MSG_MAP(GetDcModeMaxDpmFreq,		PPSMC_MSG_GetDcModeMaxDpmFreq,         1),
1211bb76ff1Sjsg 	MSG_MAP(OverridePcieParameters,		PPSMC_MSG_OverridePcieParameters,      0),
1221bb76ff1Sjsg 	MSG_MAP(ReenableAcDcInterrupt,		PPSMC_MSG_ReenableAcDcInterrupt,       0),
1231bb76ff1Sjsg 	MSG_MAP(AllowIHHostInterrupt,		PPSMC_MSG_AllowIHHostInterrupt,       0),
1241bb76ff1Sjsg 	MSG_MAP(DramLogSetDramAddrHigh,		PPSMC_MSG_DramLogSetDramAddrHigh,      0),
1251bb76ff1Sjsg 	MSG_MAP(DramLogSetDramAddrLow,		PPSMC_MSG_DramLogSetDramAddrLow,       0),
1261bb76ff1Sjsg 	MSG_MAP(DramLogSetDramSize,		PPSMC_MSG_DramLogSetDramSize,          0),
1271bb76ff1Sjsg 	MSG_MAP(AllowGfxOff,			PPSMC_MSG_AllowGfxOff,                 0),
1281bb76ff1Sjsg 	MSG_MAP(DisallowGfxOff,			PPSMC_MSG_DisallowGfxOff,              0),
1291bb76ff1Sjsg 	MSG_MAP(Mode1Reset,             PPSMC_MSG_Mode1Reset,                  0),
1301bb76ff1Sjsg 	MSG_MAP(PrepareMp1ForUnload,		PPSMC_MSG_PrepareMp1ForUnload,         0),
1311bb76ff1Sjsg 	MSG_MAP(SetMGpuFanBoostLimitRpm,	PPSMC_MSG_SetMGpuFanBoostLimitRpm,     0),
1321bb76ff1Sjsg 	MSG_MAP(DFCstateControl,		PPSMC_MSG_SetExternalClientDfCstateAllow, 0),
1331bb76ff1Sjsg 	MSG_MAP(ArmD3,				PPSMC_MSG_ArmD3,                       0),
13489fd5816Sjsg 	MSG_MAP(AllowGpo,			PPSMC_MSG_SetGpoAllow,           0),
135a09bc963Sjsg 	MSG_MAP(GetPptLimit,			PPSMC_MSG_GetPptLimit,                 0),
136ce6ef823Sjsg 	MSG_MAP(NotifyPowerSource,		PPSMC_MSG_NotifyPowerSource,           0),
1371bb76ff1Sjsg };
1381bb76ff1Sjsg 
1391bb76ff1Sjsg static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
1401bb76ff1Sjsg 	CLK_MAP(GFXCLK,		PPCLK_GFXCLK),
1411bb76ff1Sjsg 	CLK_MAP(SCLK,		PPCLK_GFXCLK),
1421bb76ff1Sjsg 	CLK_MAP(SOCCLK,		PPCLK_SOCCLK),
1431bb76ff1Sjsg 	CLK_MAP(FCLK,		PPCLK_FCLK),
1441bb76ff1Sjsg 	CLK_MAP(UCLK,		PPCLK_UCLK),
1451bb76ff1Sjsg 	CLK_MAP(MCLK,		PPCLK_UCLK),
1461bb76ff1Sjsg 	CLK_MAP(VCLK,		PPCLK_VCLK_0),
1471bb76ff1Sjsg 	CLK_MAP(VCLK1,		PPCLK_VCLK_1),
1481bb76ff1Sjsg 	CLK_MAP(DCLK,		PPCLK_DCLK_0),
1491bb76ff1Sjsg 	CLK_MAP(DCLK1,		PPCLK_DCLK_1),
1501bb76ff1Sjsg };
1511bb76ff1Sjsg 
1521bb76ff1Sjsg static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] = {
1531bb76ff1Sjsg 	FEA_MAP(FW_DATA_READ),
1541bb76ff1Sjsg 	FEA_MAP(DPM_GFXCLK),
1551bb76ff1Sjsg 	FEA_MAP(DPM_GFX_POWER_OPTIMIZER),
1561bb76ff1Sjsg 	FEA_MAP(DPM_UCLK),
1571bb76ff1Sjsg 	FEA_MAP(DPM_FCLK),
1581bb76ff1Sjsg 	FEA_MAP(DPM_SOCCLK),
1591bb76ff1Sjsg 	FEA_MAP(DPM_MP0CLK),
1601bb76ff1Sjsg 	FEA_MAP(DPM_LINK),
1611bb76ff1Sjsg 	FEA_MAP(DPM_DCN),
1621bb76ff1Sjsg 	FEA_MAP(VMEMP_SCALING),
1631bb76ff1Sjsg 	FEA_MAP(VDDIO_MEM_SCALING),
1641bb76ff1Sjsg 	FEA_MAP(DS_GFXCLK),
1651bb76ff1Sjsg 	FEA_MAP(DS_SOCCLK),
1661bb76ff1Sjsg 	FEA_MAP(DS_FCLK),
1671bb76ff1Sjsg 	FEA_MAP(DS_LCLK),
1681bb76ff1Sjsg 	FEA_MAP(DS_DCFCLK),
1691bb76ff1Sjsg 	FEA_MAP(DS_UCLK),
1701bb76ff1Sjsg 	FEA_MAP(GFX_ULV),
1711bb76ff1Sjsg 	FEA_MAP(FW_DSTATE),
1721bb76ff1Sjsg 	FEA_MAP(GFXOFF),
1731bb76ff1Sjsg 	FEA_MAP(BACO),
1741bb76ff1Sjsg 	FEA_MAP(MM_DPM),
1751bb76ff1Sjsg 	FEA_MAP(SOC_MPCLK_DS),
1761bb76ff1Sjsg 	FEA_MAP(BACO_MPCLK_DS),
1771bb76ff1Sjsg 	FEA_MAP(THROTTLERS),
1781bb76ff1Sjsg 	FEA_MAP(SMARTSHIFT),
1791bb76ff1Sjsg 	FEA_MAP(GTHR),
1801bb76ff1Sjsg 	FEA_MAP(ACDC),
1811bb76ff1Sjsg 	FEA_MAP(VR0HOT),
1821bb76ff1Sjsg 	FEA_MAP(FW_CTF),
1831bb76ff1Sjsg 	FEA_MAP(FAN_CONTROL),
1841bb76ff1Sjsg 	FEA_MAP(GFX_DCS),
1851bb76ff1Sjsg 	FEA_MAP(GFX_READ_MARGIN),
1861bb76ff1Sjsg 	FEA_MAP(LED_DISPLAY),
1871bb76ff1Sjsg 	FEA_MAP(GFXCLK_SPREAD_SPECTRUM),
1881bb76ff1Sjsg 	FEA_MAP(OUT_OF_BAND_MONITOR),
1891bb76ff1Sjsg 	FEA_MAP(OPTIMIZED_VMIN),
1901bb76ff1Sjsg 	FEA_MAP(GFX_IMU),
1911bb76ff1Sjsg 	FEA_MAP(BOOT_TIME_CAL),
1921bb76ff1Sjsg 	FEA_MAP(GFX_PCC_DFLL),
1931bb76ff1Sjsg 	FEA_MAP(SOC_CG),
1941bb76ff1Sjsg 	FEA_MAP(DF_CSTATE),
1951bb76ff1Sjsg 	FEA_MAP(GFX_EDC),
1961bb76ff1Sjsg 	FEA_MAP(BOOT_POWER_OPT),
1971bb76ff1Sjsg 	FEA_MAP(CLOCK_POWER_DOWN_BYPASS),
1981bb76ff1Sjsg 	FEA_MAP(DS_VCN),
1991bb76ff1Sjsg 	FEA_MAP(BACO_CG),
2001bb76ff1Sjsg 	FEA_MAP(MEM_TEMP_READ),
2011bb76ff1Sjsg 	FEA_MAP(ATHUB_MMHUB_PG),
2021bb76ff1Sjsg 	FEA_MAP(SOC_PCC),
203d849e855Sjsg 	[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
204d849e855Sjsg 	[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
205a9d3730bSjsg 	[SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
2061bb76ff1Sjsg };
2071bb76ff1Sjsg 
2081bb76ff1Sjsg static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
2091bb76ff1Sjsg 	TAB_MAP(PPTABLE),
2101bb76ff1Sjsg 	TAB_MAP(WATERMARKS),
2111bb76ff1Sjsg 	TAB_MAP(AVFS_PSM_DEBUG),
2121bb76ff1Sjsg 	TAB_MAP(PMSTATUSLOG),
2131bb76ff1Sjsg 	TAB_MAP(SMU_METRICS),
2141bb76ff1Sjsg 	TAB_MAP(DRIVER_SMU_CONFIG),
2151bb76ff1Sjsg 	TAB_MAP(ACTIVITY_MONITOR_COEFF),
2161bb76ff1Sjsg 	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
217*f005ef32Sjsg 	TAB_MAP(OVERDRIVE),
2181bb76ff1Sjsg };
2191bb76ff1Sjsg 
2201bb76ff1Sjsg static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
2211bb76ff1Sjsg 	PWR_MAP(AC),
2221bb76ff1Sjsg 	PWR_MAP(DC),
2231bb76ff1Sjsg };
2241bb76ff1Sjsg 
2251bb76ff1Sjsg static struct cmn2asic_mapping smu_v13_0_7_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
2261bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,	WORKLOAD_PPLIB_DEFAULT_BIT),
2271bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
2281bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,		WORKLOAD_PPLIB_POWER_SAVING_BIT),
2291bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
2301bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
2311bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
2321bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
2331bb76ff1Sjsg 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D,		WORKLOAD_PPLIB_WINDOW_3D_BIT),
2341bb76ff1Sjsg };
2351bb76ff1Sjsg 
2361bb76ff1Sjsg static const uint8_t smu_v13_0_7_throttler_map[] = {
2371bb76ff1Sjsg 	[THROTTLER_PPT0_BIT]		= (SMU_THROTTLER_PPT0_BIT),
2381bb76ff1Sjsg 	[THROTTLER_PPT1_BIT]		= (SMU_THROTTLER_PPT1_BIT),
2391bb76ff1Sjsg 	[THROTTLER_PPT2_BIT]		= (SMU_THROTTLER_PPT2_BIT),
2401bb76ff1Sjsg 	[THROTTLER_PPT3_BIT]		= (SMU_THROTTLER_PPT3_BIT),
2411bb76ff1Sjsg 	[THROTTLER_TDC_GFX_BIT]		= (SMU_THROTTLER_TDC_GFX_BIT),
2421bb76ff1Sjsg 	[THROTTLER_TDC_SOC_BIT]		= (SMU_THROTTLER_TDC_SOC_BIT),
2431bb76ff1Sjsg 	[THROTTLER_TEMP_EDGE_BIT]	= (SMU_THROTTLER_TEMP_EDGE_BIT),
2441bb76ff1Sjsg 	[THROTTLER_TEMP_HOTSPOT_BIT]	= (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
2451bb76ff1Sjsg 	[THROTTLER_TEMP_MEM_BIT]	= (SMU_THROTTLER_TEMP_MEM_BIT),
2461bb76ff1Sjsg 	[THROTTLER_TEMP_VR_GFX_BIT]	= (SMU_THROTTLER_TEMP_VR_GFX_BIT),
2471bb76ff1Sjsg 	[THROTTLER_TEMP_VR_SOC_BIT]	= (SMU_THROTTLER_TEMP_VR_SOC_BIT),
2481bb76ff1Sjsg 	[THROTTLER_TEMP_VR_MEM0_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
2491bb76ff1Sjsg 	[THROTTLER_TEMP_VR_MEM1_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
2501bb76ff1Sjsg 	[THROTTLER_TEMP_LIQUID0_BIT]	= (SMU_THROTTLER_TEMP_LIQUID0_BIT),
2511bb76ff1Sjsg 	[THROTTLER_TEMP_LIQUID1_BIT]	= (SMU_THROTTLER_TEMP_LIQUID1_BIT),
2521bb76ff1Sjsg 	[THROTTLER_GFX_APCC_PLUS_BIT]	= (SMU_THROTTLER_APCC_BIT),
2531bb76ff1Sjsg 	[THROTTLER_FIT_BIT]		= (SMU_THROTTLER_FIT_BIT),
2541bb76ff1Sjsg };
2551bb76ff1Sjsg 
2561bb76ff1Sjsg static int
smu_v13_0_7_get_allowed_feature_mask(struct smu_context * smu,uint32_t * feature_mask,uint32_t num)2571bb76ff1Sjsg smu_v13_0_7_get_allowed_feature_mask(struct smu_context *smu,
2581bb76ff1Sjsg 				  uint32_t *feature_mask, uint32_t num)
2591bb76ff1Sjsg {
2601bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
2611bb76ff1Sjsg 
2621bb76ff1Sjsg 	if (num > 2)
2631bb76ff1Sjsg 		return -EINVAL;
2641bb76ff1Sjsg 
2651bb76ff1Sjsg 	memset(feature_mask, 0, sizeof(uint32_t) * num);
2661bb76ff1Sjsg 
2671bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
2681bb76ff1Sjsg 
2691bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
2701bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
2711bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
2721bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT);
2731bb76ff1Sjsg 	}
2741bb76ff1Sjsg 
2751bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_GFXOFF_MASK)
2761bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
2771bb76ff1Sjsg 
2781bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
2791bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
2801bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
2811bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
2821bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
2831bb76ff1Sjsg 	}
2841bb76ff1Sjsg 
2851bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
2861bb76ff1Sjsg 
2871bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
2881bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
2891bb76ff1Sjsg 
2901bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
2911bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
2921bb76ff1Sjsg 
2931bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_ULV_MASK)
2941bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
2951bb76ff1Sjsg 
2961bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
2971bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT);
2981bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
2991bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
3001bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_FCLK_BIT);
3011bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
3021bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
3031bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VR0HOT_BIT);
3041bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_CTF_BIT);
3051bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
3061bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
3071bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT);
3081bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
3091bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
3101bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
3111bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
3121bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_PCC_DFLL_BIT);
3131bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_CG_BIT);
3141bb76ff1Sjsg 	*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_BIT);
3151bb76ff1Sjsg 
3161bb76ff1Sjsg 	if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
3171bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
3181bb76ff1Sjsg 
3191bb76ff1Sjsg 	if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
3201bb76ff1Sjsg 	    (adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
3211bb76ff1Sjsg 		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
3221bb76ff1Sjsg 
3231bb76ff1Sjsg 	return 0;
3241bb76ff1Sjsg }
3251bb76ff1Sjsg 
smu_v13_0_7_check_powerplay_table(struct smu_context * smu)3261bb76ff1Sjsg static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
3271bb76ff1Sjsg {
3281bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
3291bb76ff1Sjsg 	struct smu_13_0_7_powerplay_table *powerplay_table =
3301bb76ff1Sjsg 		table_context->power_play_table;
3311bb76ff1Sjsg 	struct smu_baco_context *smu_baco = &smu->smu_baco;
3321bb76ff1Sjsg 	PPTable_t *smc_pptable = table_context->driver_pptable;
3331bb76ff1Sjsg 	BoardTable_t *BoardTable = &smc_pptable->BoardTable;
334*f005ef32Sjsg #if 0
335*f005ef32Sjsg 	const OverDriveLimits_t * const overdrive_upperlimits =
336*f005ef32Sjsg 				&smc_pptable->SkuTable.OverDriveLimitsBasicMax;
337*f005ef32Sjsg 	const OverDriveLimits_t * const overdrive_lowerlimits =
338*f005ef32Sjsg 				&smc_pptable->SkuTable.OverDriveLimitsMin;
339*f005ef32Sjsg #endif
3401bb76ff1Sjsg 
3411bb76ff1Sjsg 	if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
3421bb76ff1Sjsg 		smu->dc_controlled_by_gpio = true;
3431bb76ff1Sjsg 
34474d01597Sjsg 	if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO) {
3451bb76ff1Sjsg 		smu_baco->platform_support = true;
3461bb76ff1Sjsg 
34774d01597Sjsg 		if ((powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
34874d01597Sjsg 					&& (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
3491bb76ff1Sjsg 			smu_baco->maco_support = true;
35074d01597Sjsg 	}
3511bb76ff1Sjsg 
352*f005ef32Sjsg #if 0
353*f005ef32Sjsg 	if (!overdrive_lowerlimits->FeatureCtrlMask ||
354*f005ef32Sjsg 	    !overdrive_upperlimits->FeatureCtrlMask)
355*f005ef32Sjsg 		smu->od_enabled = false;
3561bb76ff1Sjsg 
3571bb76ff1Sjsg 	/*
3581bb76ff1Sjsg 	 * Instead of having its own buffer space and get overdrive_table copied,
3591bb76ff1Sjsg 	 * smu->od_settings just points to the actual overdrive_table
3601bb76ff1Sjsg 	 */
3611bb76ff1Sjsg 	smu->od_settings = &powerplay_table->overdrive_table;
362*f005ef32Sjsg #else
363*f005ef32Sjsg 	smu->od_enabled = false;
364*f005ef32Sjsg #endif
365*f005ef32Sjsg 
366*f005ef32Sjsg 	table_context->thermal_controller_type =
367*f005ef32Sjsg 		powerplay_table->thermal_controller_type;
3681bb76ff1Sjsg 
3691bb76ff1Sjsg 	return 0;
3701bb76ff1Sjsg }
3711bb76ff1Sjsg 
smu_v13_0_7_store_powerplay_table(struct smu_context * smu)3721bb76ff1Sjsg static int smu_v13_0_7_store_powerplay_table(struct smu_context *smu)
3731bb76ff1Sjsg {
3741bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
3751bb76ff1Sjsg 	struct smu_13_0_7_powerplay_table *powerplay_table =
3761bb76ff1Sjsg 		table_context->power_play_table;
3771bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
3781bb76ff1Sjsg 
3791bb76ff1Sjsg 	if (adev->pdev->device == 0x51)
3801bb76ff1Sjsg 		powerplay_table->smc_pptable.SkuTable.DebugOverrides |= 0x00000080;
3811bb76ff1Sjsg 
3821bb76ff1Sjsg 	memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
3831bb76ff1Sjsg 	       sizeof(PPTable_t));
3841bb76ff1Sjsg 
3851bb76ff1Sjsg 	return 0;
3861bb76ff1Sjsg }
3871bb76ff1Sjsg 
smu_v13_0_7_check_fw_status(struct smu_context * smu)3881bb76ff1Sjsg static int smu_v13_0_7_check_fw_status(struct smu_context *smu)
3891bb76ff1Sjsg {
3901bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
3911bb76ff1Sjsg 	uint32_t mp1_fw_flags;
3921bb76ff1Sjsg 
3931bb76ff1Sjsg 	mp1_fw_flags = RREG32_PCIE(MP1_Public |
3941bb76ff1Sjsg 				   (smnMP1_FIRMWARE_FLAGS_SMU_13_0_7 & 0xffffffff));
3951bb76ff1Sjsg 
3961bb76ff1Sjsg 	if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
3971bb76ff1Sjsg 			MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
3981bb76ff1Sjsg 		return 0;
3991bb76ff1Sjsg 
4001bb76ff1Sjsg 	return -EIO;
4011bb76ff1Sjsg }
4021bb76ff1Sjsg 
4031bb76ff1Sjsg #ifndef atom_smc_dpm_info_table_13_0_7
404*f005ef32Sjsg struct atom_smc_dpm_info_table_13_0_7 {
4051bb76ff1Sjsg 	struct atom_common_table_header table_header;
4061bb76ff1Sjsg 	BoardTable_t BoardTable;
4071bb76ff1Sjsg };
4081bb76ff1Sjsg #endif
4091bb76ff1Sjsg 
smu_v13_0_7_append_powerplay_table(struct smu_context * smu)4101bb76ff1Sjsg static int smu_v13_0_7_append_powerplay_table(struct smu_context *smu)
4111bb76ff1Sjsg {
4121bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
4131bb76ff1Sjsg 
4141bb76ff1Sjsg 	PPTable_t *smc_pptable = table_context->driver_pptable;
4151bb76ff1Sjsg 
4161bb76ff1Sjsg 	struct atom_smc_dpm_info_table_13_0_7 *smc_dpm_table;
4171bb76ff1Sjsg 
4181bb76ff1Sjsg 	BoardTable_t *BoardTable = &smc_pptable->BoardTable;
4191bb76ff1Sjsg 
4201bb76ff1Sjsg 	int index, ret;
4211bb76ff1Sjsg 
4221bb76ff1Sjsg 	index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
4231bb76ff1Sjsg 	smc_dpm_info);
4241bb76ff1Sjsg 
4251bb76ff1Sjsg 	ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
4261bb76ff1Sjsg 			(uint8_t **)&smc_dpm_table);
4271bb76ff1Sjsg 	if (ret)
4281bb76ff1Sjsg 		return ret;
4291bb76ff1Sjsg 
4301bb76ff1Sjsg 	memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
4311bb76ff1Sjsg 
4321bb76ff1Sjsg 	return 0;
4331bb76ff1Sjsg }
4341bb76ff1Sjsg 
smu_v13_0_7_get_pptable_from_pmfw(struct smu_context * smu,void ** table,uint32_t * size)4351bb76ff1Sjsg static int smu_v13_0_7_get_pptable_from_pmfw(struct smu_context *smu,
4361bb76ff1Sjsg 					     void **table,
4371bb76ff1Sjsg 					     uint32_t *size)
4381bb76ff1Sjsg {
4391bb76ff1Sjsg 	struct smu_table_context *smu_table = &smu->smu_table;
4401bb76ff1Sjsg 	void *combo_pptable = smu_table->combo_pptable;
4411bb76ff1Sjsg 	int ret = 0;
4421bb76ff1Sjsg 
4431bb76ff1Sjsg 	ret = smu_cmn_get_combo_pptable(smu);
4441bb76ff1Sjsg 	if (ret)
4451bb76ff1Sjsg 		return ret;
4461bb76ff1Sjsg 
4471bb76ff1Sjsg 	*table = combo_pptable;
4481bb76ff1Sjsg 	*size = sizeof(struct smu_13_0_7_powerplay_table);
4491bb76ff1Sjsg 
4501bb76ff1Sjsg 	return 0;
4511bb76ff1Sjsg }
4521bb76ff1Sjsg 
smu_v13_0_7_setup_pptable(struct smu_context * smu)4531bb76ff1Sjsg static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
4541bb76ff1Sjsg {
4551bb76ff1Sjsg 	struct smu_table_context *smu_table = &smu->smu_table;
4561bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
4571bb76ff1Sjsg 	int ret = 0;
4581bb76ff1Sjsg 
4591bb76ff1Sjsg 	/*
4601bb76ff1Sjsg 	 * With SCPM enabled, the pptable used will be signed. It cannot
4611bb76ff1Sjsg 	 * be used directly by driver. To get the raw pptable, we need to
4621bb76ff1Sjsg 	 * rely on the combo pptable(and its revelant SMU message).
4631bb76ff1Sjsg 	 */
4641bb76ff1Sjsg 	ret = smu_v13_0_7_get_pptable_from_pmfw(smu,
4651bb76ff1Sjsg 						&smu_table->power_play_table,
4661bb76ff1Sjsg 						&smu_table->power_play_table_size);
4671bb76ff1Sjsg 	if (ret)
4681bb76ff1Sjsg 		return ret;
4691bb76ff1Sjsg 
4701bb76ff1Sjsg 	ret = smu_v13_0_7_store_powerplay_table(smu);
4711bb76ff1Sjsg 	if (ret)
4721bb76ff1Sjsg 		return ret;
4731bb76ff1Sjsg 
4741bb76ff1Sjsg 	/*
4751bb76ff1Sjsg 	 * With SCPM enabled, the operation below will be handled
4761bb76ff1Sjsg 	 * by PSP. Driver involvment is unnecessary and useless.
4771bb76ff1Sjsg 	 */
4781bb76ff1Sjsg 	if (!adev->scpm_enabled) {
4791bb76ff1Sjsg 		ret = smu_v13_0_7_append_powerplay_table(smu);
4801bb76ff1Sjsg 		if (ret)
4811bb76ff1Sjsg 			return ret;
4821bb76ff1Sjsg 	}
4831bb76ff1Sjsg 
4841bb76ff1Sjsg 	ret = smu_v13_0_7_check_powerplay_table(smu);
4851bb76ff1Sjsg 	if (ret)
4861bb76ff1Sjsg 		return ret;
4871bb76ff1Sjsg 
4881bb76ff1Sjsg 	return ret;
4891bb76ff1Sjsg }
4901bb76ff1Sjsg 
smu_v13_0_7_tables_init(struct smu_context * smu)4911bb76ff1Sjsg static int smu_v13_0_7_tables_init(struct smu_context *smu)
4921bb76ff1Sjsg {
4931bb76ff1Sjsg 	struct smu_table_context *smu_table = &smu->smu_table;
4941bb76ff1Sjsg 	struct smu_table *tables = smu_table->tables;
4951bb76ff1Sjsg 
4961bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
4971bb76ff1Sjsg 		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
4981bb76ff1Sjsg 
4991bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
5001bb76ff1Sjsg 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5011bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
5021bb76ff1Sjsg 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5031bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
5041bb76ff1Sjsg 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
505*f005ef32Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
5061bb76ff1Sjsg 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5071bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
5081bb76ff1Sjsg 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5091bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
5101bb76ff1Sjsg 		       sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
5111bb76ff1Sjsg 		       AMDGPU_GEM_DOMAIN_VRAM);
5121bb76ff1Sjsg 	SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
5131bb76ff1Sjsg 			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5141bb76ff1Sjsg 
5151bb76ff1Sjsg 	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
5161bb76ff1Sjsg 	if (!smu_table->metrics_table)
5171bb76ff1Sjsg 		goto err0_out;
5181bb76ff1Sjsg 	smu_table->metrics_time = 0;
5191bb76ff1Sjsg 
5201bb76ff1Sjsg 	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
5211bb76ff1Sjsg 	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
5221bb76ff1Sjsg 	if (!smu_table->gpu_metrics_table)
5231bb76ff1Sjsg 		goto err1_out;
5241bb76ff1Sjsg 
5251bb76ff1Sjsg 	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
5261bb76ff1Sjsg 	if (!smu_table->watermarks_table)
5271bb76ff1Sjsg 		goto err2_out;
5281bb76ff1Sjsg 
5291bb76ff1Sjsg 	return 0;
5301bb76ff1Sjsg 
5311bb76ff1Sjsg err2_out:
5321bb76ff1Sjsg 	kfree(smu_table->gpu_metrics_table);
5331bb76ff1Sjsg err1_out:
5341bb76ff1Sjsg 	kfree(smu_table->metrics_table);
5351bb76ff1Sjsg err0_out:
5361bb76ff1Sjsg 	return -ENOMEM;
5371bb76ff1Sjsg }
5381bb76ff1Sjsg 
smu_v13_0_7_allocate_dpm_context(struct smu_context * smu)5391bb76ff1Sjsg static int smu_v13_0_7_allocate_dpm_context(struct smu_context *smu)
5401bb76ff1Sjsg {
5411bb76ff1Sjsg 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
5421bb76ff1Sjsg 
5431bb76ff1Sjsg 	smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
5441bb76ff1Sjsg 				       GFP_KERNEL);
5451bb76ff1Sjsg 	if (!smu_dpm->dpm_context)
5461bb76ff1Sjsg 		return -ENOMEM;
5471bb76ff1Sjsg 
5481bb76ff1Sjsg 	smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
5491bb76ff1Sjsg 
5501bb76ff1Sjsg 	return 0;
5511bb76ff1Sjsg }
5521bb76ff1Sjsg 
smu_v13_0_7_init_smc_tables(struct smu_context * smu)5531bb76ff1Sjsg static int smu_v13_0_7_init_smc_tables(struct smu_context *smu)
5541bb76ff1Sjsg {
5551bb76ff1Sjsg 	int ret = 0;
5561bb76ff1Sjsg 
5571bb76ff1Sjsg 	ret = smu_v13_0_7_tables_init(smu);
5581bb76ff1Sjsg 	if (ret)
5591bb76ff1Sjsg 		return ret;
5601bb76ff1Sjsg 
5611bb76ff1Sjsg 	ret = smu_v13_0_7_allocate_dpm_context(smu);
5621bb76ff1Sjsg 	if (ret)
5631bb76ff1Sjsg 		return ret;
5641bb76ff1Sjsg 
5651bb76ff1Sjsg 	return smu_v13_0_init_smc_tables(smu);
5661bb76ff1Sjsg }
5671bb76ff1Sjsg 
smu_v13_0_7_set_default_dpm_table(struct smu_context * smu)5681bb76ff1Sjsg static int smu_v13_0_7_set_default_dpm_table(struct smu_context *smu)
5691bb76ff1Sjsg {
5701bb76ff1Sjsg 	struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
5711bb76ff1Sjsg 	PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
5721bb76ff1Sjsg 	SkuTable_t *skutable = &driver_ppt->SkuTable;
5731bb76ff1Sjsg 	struct smu_13_0_dpm_table *dpm_table;
5741bb76ff1Sjsg 	struct smu_13_0_pcie_table *pcie_table;
5751bb76ff1Sjsg 	uint32_t link_level;
5761bb76ff1Sjsg 	int ret = 0;
5771bb76ff1Sjsg 
5781bb76ff1Sjsg 	/* socclk dpm table setup */
5791bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.soc_table;
5801bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
5811bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
5821bb76ff1Sjsg 						     SMU_SOCCLK,
5831bb76ff1Sjsg 						     dpm_table);
5841bb76ff1Sjsg 		if (ret)
5851bb76ff1Sjsg 			return ret;
5861bb76ff1Sjsg 	} else {
5871bb76ff1Sjsg 		dpm_table->count = 1;
5881bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
5891bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
5901bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
5911bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
5921bb76ff1Sjsg 	}
5931bb76ff1Sjsg 
5941bb76ff1Sjsg 	/* gfxclk dpm table setup */
5951bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.gfx_table;
5961bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
5971bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
5981bb76ff1Sjsg 						     SMU_GFXCLK,
5991bb76ff1Sjsg 						     dpm_table);
6001bb76ff1Sjsg 		if (ret)
6011bb76ff1Sjsg 			return ret;
602b6e93a8fSjsg 
603b6e93a8fSjsg 		if (skutable->DriverReportedClocks.GameClockAc &&
604b6e93a8fSjsg 			(dpm_table->dpm_levels[dpm_table->count - 1].value >
605b6e93a8fSjsg 			skutable->DriverReportedClocks.GameClockAc)) {
606b6e93a8fSjsg 			dpm_table->dpm_levels[dpm_table->count - 1].value =
607b6e93a8fSjsg 				skutable->DriverReportedClocks.GameClockAc;
608b6e93a8fSjsg 			dpm_table->max = skutable->DriverReportedClocks.GameClockAc;
609b6e93a8fSjsg 		}
6101bb76ff1Sjsg 	} else {
6111bb76ff1Sjsg 		dpm_table->count = 1;
6121bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
6131bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
6141bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
6151bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
6161bb76ff1Sjsg 	}
6171bb76ff1Sjsg 
6181bb76ff1Sjsg 	/* uclk dpm table setup */
6191bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.uclk_table;
6201bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
6211bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
6221bb76ff1Sjsg 						     SMU_UCLK,
6231bb76ff1Sjsg 						     dpm_table);
6241bb76ff1Sjsg 		if (ret)
6251bb76ff1Sjsg 			return ret;
6261bb76ff1Sjsg 	} else {
6271bb76ff1Sjsg 		dpm_table->count = 1;
6281bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
6291bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
6301bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
6311bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
6321bb76ff1Sjsg 	}
6331bb76ff1Sjsg 
6341bb76ff1Sjsg 	/* fclk dpm table setup */
6351bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.fclk_table;
6361bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
6371bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
6381bb76ff1Sjsg 						     SMU_FCLK,
6391bb76ff1Sjsg 						     dpm_table);
6401bb76ff1Sjsg 		if (ret)
6411bb76ff1Sjsg 			return ret;
6421bb76ff1Sjsg 	} else {
6431bb76ff1Sjsg 		dpm_table->count = 1;
6441bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
6451bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
6461bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
6471bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
6481bb76ff1Sjsg 	}
6491bb76ff1Sjsg 
6501bb76ff1Sjsg 	/* vclk dpm table setup */
6511bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.vclk_table;
6521bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) {
6531bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
6541bb76ff1Sjsg 						     SMU_VCLK,
6551bb76ff1Sjsg 						     dpm_table);
6561bb76ff1Sjsg 		if (ret)
6571bb76ff1Sjsg 			return ret;
6581bb76ff1Sjsg 	} else {
6591bb76ff1Sjsg 		dpm_table->count = 1;
6601bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
6611bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
6621bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
6631bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
6641bb76ff1Sjsg 	}
6651bb76ff1Sjsg 
6661bb76ff1Sjsg 	/* dclk dpm table setup */
6671bb76ff1Sjsg 	dpm_table = &dpm_context->dpm_tables.dclk_table;
6681bb76ff1Sjsg 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) {
6691bb76ff1Sjsg 		ret = smu_v13_0_set_single_dpm_table(smu,
6701bb76ff1Sjsg 						     SMU_DCLK,
6711bb76ff1Sjsg 						     dpm_table);
6721bb76ff1Sjsg 		if (ret)
6731bb76ff1Sjsg 			return ret;
6741bb76ff1Sjsg 	} else {
6751bb76ff1Sjsg 		dpm_table->count = 1;
6761bb76ff1Sjsg 		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
6771bb76ff1Sjsg 		dpm_table->dpm_levels[0].enabled = true;
6781bb76ff1Sjsg 		dpm_table->min = dpm_table->dpm_levels[0].value;
6791bb76ff1Sjsg 		dpm_table->max = dpm_table->dpm_levels[0].value;
6801bb76ff1Sjsg 	}
6811bb76ff1Sjsg 
6821bb76ff1Sjsg 	/* lclk dpm table setup */
6831bb76ff1Sjsg 	pcie_table = &dpm_context->dpm_tables.pcie_table;
6841bb76ff1Sjsg 	pcie_table->num_of_link_levels = 0;
6851bb76ff1Sjsg 	for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) {
6861bb76ff1Sjsg 		if (!skutable->PcieGenSpeed[link_level] &&
6871bb76ff1Sjsg 		    !skutable->PcieLaneCount[link_level] &&
6881bb76ff1Sjsg 		    !skutable->LclkFreq[link_level])
6891bb76ff1Sjsg 			continue;
6901bb76ff1Sjsg 
6911bb76ff1Sjsg 		pcie_table->pcie_gen[pcie_table->num_of_link_levels] =
6921bb76ff1Sjsg 					skutable->PcieGenSpeed[link_level];
6931bb76ff1Sjsg 		pcie_table->pcie_lane[pcie_table->num_of_link_levels] =
6941bb76ff1Sjsg 					skutable->PcieLaneCount[link_level];
6951bb76ff1Sjsg 		pcie_table->clk_freq[pcie_table->num_of_link_levels] =
6961bb76ff1Sjsg 					skutable->LclkFreq[link_level];
6971bb76ff1Sjsg 		pcie_table->num_of_link_levels++;
6981bb76ff1Sjsg 	}
6991bb76ff1Sjsg 
7001bb76ff1Sjsg 	return 0;
7011bb76ff1Sjsg }
7021bb76ff1Sjsg 
smu_v13_0_7_is_dpm_running(struct smu_context * smu)7031bb76ff1Sjsg static bool smu_v13_0_7_is_dpm_running(struct smu_context *smu)
7041bb76ff1Sjsg {
7051bb76ff1Sjsg 	int ret = 0;
7061bb76ff1Sjsg 	uint64_t feature_enabled;
7071bb76ff1Sjsg 
7081bb76ff1Sjsg 	ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
7091bb76ff1Sjsg 	if (ret)
7101bb76ff1Sjsg 		return false;
7111bb76ff1Sjsg 
7121bb76ff1Sjsg 	return !!(feature_enabled & SMC_DPM_FEATURE);
7131bb76ff1Sjsg }
7141bb76ff1Sjsg 
smu_v13_0_7_dump_pptable(struct smu_context * smu)7151bb76ff1Sjsg static void smu_v13_0_7_dump_pptable(struct smu_context *smu)
7161bb76ff1Sjsg {
7171bb76ff1Sjsg        struct smu_table_context *table_context = &smu->smu_table;
7181bb76ff1Sjsg        PPTable_t *pptable = table_context->driver_pptable;
7191bb76ff1Sjsg        SkuTable_t *skutable = &pptable->SkuTable;
7201bb76ff1Sjsg 
7211bb76ff1Sjsg        dev_info(smu->adev->dev, "Dumped PPTable:\n");
7221bb76ff1Sjsg 
7231bb76ff1Sjsg        dev_info(smu->adev->dev, "Version = 0x%08x\n", skutable->Version);
7241bb76ff1Sjsg        dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", skutable->FeaturesToRun[0]);
7251bb76ff1Sjsg        dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", skutable->FeaturesToRun[1]);
7261bb76ff1Sjsg }
7271bb76ff1Sjsg 
smu_v13_0_7_get_throttler_status(SmuMetrics_t * metrics)7281bb76ff1Sjsg static uint32_t smu_v13_0_7_get_throttler_status(SmuMetrics_t *metrics)
7291bb76ff1Sjsg {
7301bb76ff1Sjsg 	uint32_t throttler_status = 0;
7311bb76ff1Sjsg 	int i;
7321bb76ff1Sjsg 
7331bb76ff1Sjsg 	for (i = 0; i < THROTTLER_COUNT; i++)
7341bb76ff1Sjsg 		throttler_status |=
7351bb76ff1Sjsg 			(metrics->ThrottlingPercentage[i] ? 1U << i : 0);
7361bb76ff1Sjsg 
7371bb76ff1Sjsg 	return throttler_status;
7381bb76ff1Sjsg }
7391bb76ff1Sjsg 
7401bb76ff1Sjsg #define SMU_13_0_7_BUSY_THRESHOLD	15
smu_v13_0_7_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)7411bb76ff1Sjsg static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
7421bb76ff1Sjsg 					    MetricsMember_t member,
7431bb76ff1Sjsg 					    uint32_t *value)
7441bb76ff1Sjsg {
7451bb76ff1Sjsg 	struct smu_table_context *smu_table = &smu->smu_table;
7461bb76ff1Sjsg 	SmuMetrics_t *metrics =
7471bb76ff1Sjsg 		&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
7481bb76ff1Sjsg 	int ret = 0;
7491bb76ff1Sjsg 
7501bb76ff1Sjsg 	ret = smu_cmn_get_metrics_table(smu,
7511bb76ff1Sjsg 					NULL,
7521bb76ff1Sjsg 					false);
7531bb76ff1Sjsg 	if (ret)
7541bb76ff1Sjsg 		return ret;
7551bb76ff1Sjsg 
7561bb76ff1Sjsg 	switch (member) {
7571bb76ff1Sjsg 	case METRICS_CURR_GFXCLK:
7581bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_GFXCLK];
7591bb76ff1Sjsg 		break;
7601bb76ff1Sjsg 	case METRICS_CURR_SOCCLK:
7611bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_SOCCLK];
7621bb76ff1Sjsg 		break;
7631bb76ff1Sjsg 	case METRICS_CURR_UCLK:
7641bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_UCLK];
7651bb76ff1Sjsg 		break;
7661bb76ff1Sjsg 	case METRICS_CURR_VCLK:
7671bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_VCLK_0];
7681bb76ff1Sjsg 		break;
7691bb76ff1Sjsg 	case METRICS_CURR_VCLK1:
7701bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_VCLK_1];
7711bb76ff1Sjsg 		break;
7721bb76ff1Sjsg 	case METRICS_CURR_DCLK:
7731bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_DCLK_0];
7741bb76ff1Sjsg 		break;
7751bb76ff1Sjsg 	case METRICS_CURR_DCLK1:
7761bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_DCLK_1];
7771bb76ff1Sjsg 		break;
7781bb76ff1Sjsg 	case METRICS_CURR_FCLK:
7791bb76ff1Sjsg 		*value = metrics->CurrClock[PPCLK_FCLK];
7801bb76ff1Sjsg 		break;
7811bb76ff1Sjsg 	case METRICS_AVERAGE_GFXCLK:
7821bb76ff1Sjsg 		*value = metrics->AverageGfxclkFrequencyPreDs;
7831bb76ff1Sjsg 		break;
7841bb76ff1Sjsg 	case METRICS_AVERAGE_FCLK:
7851bb76ff1Sjsg 		if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
7861bb76ff1Sjsg 			*value = metrics->AverageFclkFrequencyPostDs;
7871bb76ff1Sjsg 		else
7881bb76ff1Sjsg 			*value = metrics->AverageFclkFrequencyPreDs;
7891bb76ff1Sjsg 		break;
7901bb76ff1Sjsg 	case METRICS_AVERAGE_UCLK:
7911bb76ff1Sjsg 		if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
7921bb76ff1Sjsg 			*value = metrics->AverageMemclkFrequencyPostDs;
7931bb76ff1Sjsg 		else
7941bb76ff1Sjsg 			*value = metrics->AverageMemclkFrequencyPreDs;
7951bb76ff1Sjsg 		break;
7961bb76ff1Sjsg 	case METRICS_AVERAGE_VCLK:
7971bb76ff1Sjsg 		*value = metrics->AverageVclk0Frequency;
7981bb76ff1Sjsg 		break;
7991bb76ff1Sjsg 	case METRICS_AVERAGE_DCLK:
8001bb76ff1Sjsg 		*value = metrics->AverageDclk0Frequency;
8011bb76ff1Sjsg 		break;
8021bb76ff1Sjsg 	case METRICS_AVERAGE_VCLK1:
8031bb76ff1Sjsg 		*value = metrics->AverageVclk1Frequency;
8041bb76ff1Sjsg 		break;
8051bb76ff1Sjsg 	case METRICS_AVERAGE_DCLK1:
8061bb76ff1Sjsg 		*value = metrics->AverageDclk1Frequency;
8071bb76ff1Sjsg 		break;
8081bb76ff1Sjsg 	case METRICS_AVERAGE_GFXACTIVITY:
8091bb76ff1Sjsg 		*value = metrics->AverageGfxActivity;
8101bb76ff1Sjsg 		break;
8111bb76ff1Sjsg 	case METRICS_AVERAGE_MEMACTIVITY:
8121bb76ff1Sjsg 		*value = metrics->AverageUclkActivity;
8131bb76ff1Sjsg 		break;
8141bb76ff1Sjsg 	case METRICS_AVERAGE_SOCKETPOWER:
8151bb76ff1Sjsg 		*value = metrics->AverageSocketPower << 8;
8161bb76ff1Sjsg 		break;
8171bb76ff1Sjsg 	case METRICS_TEMPERATURE_EDGE:
8181bb76ff1Sjsg 		*value = metrics->AvgTemperature[TEMP_EDGE] *
8191bb76ff1Sjsg 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8201bb76ff1Sjsg 		break;
8211bb76ff1Sjsg 	case METRICS_TEMPERATURE_HOTSPOT:
8221bb76ff1Sjsg 		*value = metrics->AvgTemperature[TEMP_HOTSPOT] *
8231bb76ff1Sjsg 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8241bb76ff1Sjsg 		break;
8251bb76ff1Sjsg 	case METRICS_TEMPERATURE_MEM:
8261bb76ff1Sjsg 		*value = metrics->AvgTemperature[TEMP_MEM] *
8271bb76ff1Sjsg 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8281bb76ff1Sjsg 		break;
8291bb76ff1Sjsg 	case METRICS_TEMPERATURE_VRGFX:
8301bb76ff1Sjsg 		*value = metrics->AvgTemperature[TEMP_VR_GFX] *
8311bb76ff1Sjsg 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8321bb76ff1Sjsg 		break;
8331bb76ff1Sjsg 	case METRICS_TEMPERATURE_VRSOC:
8341bb76ff1Sjsg 		*value = metrics->AvgTemperature[TEMP_VR_SOC] *
8351bb76ff1Sjsg 			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8361bb76ff1Sjsg 		break;
8371bb76ff1Sjsg 	case METRICS_THROTTLER_STATUS:
8381bb76ff1Sjsg 		*value = smu_v13_0_7_get_throttler_status(metrics);
8391bb76ff1Sjsg 		break;
8401bb76ff1Sjsg 	case METRICS_CURR_FANSPEED:
8411bb76ff1Sjsg 		*value = metrics->AvgFanRpm;
8421bb76ff1Sjsg 		break;
8431bb76ff1Sjsg 	case METRICS_CURR_FANPWM:
8441bb76ff1Sjsg 		*value = metrics->AvgFanPwm;
8451bb76ff1Sjsg 		break;
8461bb76ff1Sjsg 	case METRICS_VOLTAGE_VDDGFX:
8471bb76ff1Sjsg 		*value = metrics->AvgVoltage[SVI_PLANE_GFX];
8481bb76ff1Sjsg 		break;
8491bb76ff1Sjsg 	case METRICS_PCIE_RATE:
8501bb76ff1Sjsg 		*value = metrics->PcieRate;
8511bb76ff1Sjsg 		break;
8521bb76ff1Sjsg 	case METRICS_PCIE_WIDTH:
8531bb76ff1Sjsg 		*value = metrics->PcieWidth;
8541bb76ff1Sjsg 		break;
8551bb76ff1Sjsg 	default:
8561bb76ff1Sjsg 		*value = UINT_MAX;
8571bb76ff1Sjsg 		break;
8581bb76ff1Sjsg 	}
8591bb76ff1Sjsg 
8601bb76ff1Sjsg 	return ret;
8611bb76ff1Sjsg }
8621bb76ff1Sjsg 
smu_v13_0_7_get_dpm_ultimate_freq(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t * min,uint32_t * max)863b6e93a8fSjsg static int smu_v13_0_7_get_dpm_ultimate_freq(struct smu_context *smu,
864b6e93a8fSjsg 					     enum smu_clk_type clk_type,
865b6e93a8fSjsg 					     uint32_t *min,
866b6e93a8fSjsg 					     uint32_t *max)
867b6e93a8fSjsg {
868b6e93a8fSjsg 	struct smu_13_0_dpm_context *dpm_context =
869b6e93a8fSjsg 		smu->smu_dpm.dpm_context;
870b6e93a8fSjsg 	struct smu_13_0_dpm_table *dpm_table;
871b6e93a8fSjsg 
872b6e93a8fSjsg 	switch (clk_type) {
873b6e93a8fSjsg 	case SMU_MCLK:
874b6e93a8fSjsg 	case SMU_UCLK:
875b6e93a8fSjsg 		/* uclk dpm table */
876b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.uclk_table;
877b6e93a8fSjsg 		break;
878b6e93a8fSjsg 	case SMU_GFXCLK:
879b6e93a8fSjsg 	case SMU_SCLK:
880b6e93a8fSjsg 		/* gfxclk dpm table */
881b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.gfx_table;
882b6e93a8fSjsg 		break;
883b6e93a8fSjsg 	case SMU_SOCCLK:
884b6e93a8fSjsg 		/* socclk dpm table */
885b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.soc_table;
886b6e93a8fSjsg 		break;
887b6e93a8fSjsg 	case SMU_FCLK:
888b6e93a8fSjsg 		/* fclk dpm table */
889b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.fclk_table;
890b6e93a8fSjsg 		break;
891b6e93a8fSjsg 	case SMU_VCLK:
892b6e93a8fSjsg 	case SMU_VCLK1:
893b6e93a8fSjsg 		/* vclk dpm table */
894b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.vclk_table;
895b6e93a8fSjsg 		break;
896b6e93a8fSjsg 	case SMU_DCLK:
897b6e93a8fSjsg 	case SMU_DCLK1:
898b6e93a8fSjsg 		/* dclk dpm table */
899b6e93a8fSjsg 		dpm_table = &dpm_context->dpm_tables.dclk_table;
900b6e93a8fSjsg 		break;
901b6e93a8fSjsg 	default:
902b6e93a8fSjsg 		dev_err(smu->adev->dev, "Unsupported clock type!\n");
903b6e93a8fSjsg 		return -EINVAL;
904b6e93a8fSjsg 	}
905b6e93a8fSjsg 
906b6e93a8fSjsg 	if (min)
907b6e93a8fSjsg 		*min = dpm_table->min;
908b6e93a8fSjsg 	if (max)
909b6e93a8fSjsg 		*max = dpm_table->max;
910b6e93a8fSjsg 
911b6e93a8fSjsg 	return 0;
912b6e93a8fSjsg }
913b6e93a8fSjsg 
smu_v13_0_7_read_sensor(struct smu_context * smu,enum amd_pp_sensors sensor,void * data,uint32_t * size)9141bb76ff1Sjsg static int smu_v13_0_7_read_sensor(struct smu_context *smu,
9151bb76ff1Sjsg 				   enum amd_pp_sensors sensor,
9161bb76ff1Sjsg 				   void *data,
9171bb76ff1Sjsg 				   uint32_t *size)
9181bb76ff1Sjsg {
9191bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
9201bb76ff1Sjsg 	PPTable_t *smc_pptable = table_context->driver_pptable;
9211bb76ff1Sjsg 	int ret = 0;
9221bb76ff1Sjsg 
9231bb76ff1Sjsg 	switch (sensor) {
9241bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
9251bb76ff1Sjsg 		*(uint16_t *)data = smc_pptable->SkuTable.FanMaximumRpm;
9261bb76ff1Sjsg 		*size = 4;
9271bb76ff1Sjsg 		break;
9281bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_MEM_LOAD:
9291bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9301bb76ff1Sjsg 						       METRICS_AVERAGE_MEMACTIVITY,
9311bb76ff1Sjsg 						       (uint32_t *)data);
9321bb76ff1Sjsg 		*size = 4;
9331bb76ff1Sjsg 		break;
9341bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_GPU_LOAD:
9351bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9361bb76ff1Sjsg 						       METRICS_AVERAGE_GFXACTIVITY,
9371bb76ff1Sjsg 						       (uint32_t *)data);
9381bb76ff1Sjsg 		*size = 4;
9391bb76ff1Sjsg 		break;
940*f005ef32Sjsg 	case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
9411bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9421bb76ff1Sjsg 						       METRICS_AVERAGE_SOCKETPOWER,
9431bb76ff1Sjsg 						       (uint32_t *)data);
9441bb76ff1Sjsg 		*size = 4;
9451bb76ff1Sjsg 		break;
9461bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
9471bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9481bb76ff1Sjsg 						       METRICS_TEMPERATURE_HOTSPOT,
9491bb76ff1Sjsg 						       (uint32_t *)data);
9501bb76ff1Sjsg 		*size = 4;
9511bb76ff1Sjsg 		break;
9521bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_EDGE_TEMP:
9531bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9541bb76ff1Sjsg 						       METRICS_TEMPERATURE_EDGE,
9551bb76ff1Sjsg 						       (uint32_t *)data);
9561bb76ff1Sjsg 		*size = 4;
9571bb76ff1Sjsg 		break;
9581bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_MEM_TEMP:
9591bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9601bb76ff1Sjsg 						       METRICS_TEMPERATURE_MEM,
9611bb76ff1Sjsg 						       (uint32_t *)data);
9621bb76ff1Sjsg 		*size = 4;
9631bb76ff1Sjsg 		break;
9641bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_GFX_MCLK:
9651bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9666ed427d8Sjsg 						       METRICS_CURR_UCLK,
9671bb76ff1Sjsg 						       (uint32_t *)data);
9681bb76ff1Sjsg 		*(uint32_t *)data *= 100;
9691bb76ff1Sjsg 		*size = 4;
9701bb76ff1Sjsg 		break;
9711bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_GFX_SCLK:
9721bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9731bb76ff1Sjsg 						       METRICS_AVERAGE_GFXCLK,
9741bb76ff1Sjsg 						       (uint32_t *)data);
9751bb76ff1Sjsg 		*(uint32_t *)data *= 100;
9761bb76ff1Sjsg 		*size = 4;
9771bb76ff1Sjsg 		break;
9781bb76ff1Sjsg 	case AMDGPU_PP_SENSOR_VDDGFX:
9791bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
9801bb76ff1Sjsg 						       METRICS_VOLTAGE_VDDGFX,
9811bb76ff1Sjsg 						       (uint32_t *)data);
9821bb76ff1Sjsg 		*size = 4;
9831bb76ff1Sjsg 		break;
984*f005ef32Sjsg 	case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
9851bb76ff1Sjsg 	default:
9861bb76ff1Sjsg 		ret = -EOPNOTSUPP;
9871bb76ff1Sjsg 		break;
9881bb76ff1Sjsg 	}
9891bb76ff1Sjsg 
9901bb76ff1Sjsg 	return ret;
9911bb76ff1Sjsg }
9921bb76ff1Sjsg 
smu_v13_0_7_get_current_clk_freq_by_table(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t * value)9931bb76ff1Sjsg static int smu_v13_0_7_get_current_clk_freq_by_table(struct smu_context *smu,
9941bb76ff1Sjsg 						     enum smu_clk_type clk_type,
9951bb76ff1Sjsg 						     uint32_t *value)
9961bb76ff1Sjsg {
9971bb76ff1Sjsg 	MetricsMember_t member_type;
9981bb76ff1Sjsg 	int clk_id = 0;
9991bb76ff1Sjsg 
10001bb76ff1Sjsg 	clk_id = smu_cmn_to_asic_specific_index(smu,
10011bb76ff1Sjsg 						CMN2ASIC_MAPPING_CLK,
10021bb76ff1Sjsg 						clk_type);
10031bb76ff1Sjsg 	if (clk_id < 0)
10041bb76ff1Sjsg 		return -EINVAL;
10051bb76ff1Sjsg 
10061bb76ff1Sjsg 	switch (clk_id) {
10071bb76ff1Sjsg 	case PPCLK_GFXCLK:
10081bb76ff1Sjsg 		member_type = METRICS_AVERAGE_GFXCLK;
10091bb76ff1Sjsg 		break;
10101bb76ff1Sjsg 	case PPCLK_UCLK:
10111bb76ff1Sjsg 		member_type = METRICS_CURR_UCLK;
10121bb76ff1Sjsg 		break;
10131bb76ff1Sjsg 	case PPCLK_FCLK:
10141bb76ff1Sjsg 		member_type = METRICS_CURR_FCLK;
10151bb76ff1Sjsg 		break;
10161bb76ff1Sjsg 	case PPCLK_SOCCLK:
10171bb76ff1Sjsg 		member_type = METRICS_CURR_SOCCLK;
10181bb76ff1Sjsg 		break;
10191bb76ff1Sjsg 	case PPCLK_VCLK_0:
10201bb76ff1Sjsg 		member_type = METRICS_CURR_VCLK;
10211bb76ff1Sjsg 		break;
10221bb76ff1Sjsg 	case PPCLK_DCLK_0:
10231bb76ff1Sjsg 		member_type = METRICS_CURR_DCLK;
10241bb76ff1Sjsg 		break;
10251bb76ff1Sjsg 	case PPCLK_VCLK_1:
10261bb76ff1Sjsg 		member_type = METRICS_CURR_VCLK1;
10271bb76ff1Sjsg 		break;
10281bb76ff1Sjsg 	case PPCLK_DCLK_1:
10291bb76ff1Sjsg 		member_type = METRICS_CURR_DCLK1;
10301bb76ff1Sjsg 		break;
10311bb76ff1Sjsg 	default:
10321bb76ff1Sjsg 		return -EINVAL;
10331bb76ff1Sjsg 	}
10341bb76ff1Sjsg 
10351bb76ff1Sjsg 	return smu_v13_0_7_get_smu_metrics_data(smu,
10361bb76ff1Sjsg 						member_type,
10371bb76ff1Sjsg 						value);
10381bb76ff1Sjsg }
10391bb76ff1Sjsg 
smu_v13_0_7_is_od_feature_supported(struct smu_context * smu,int od_feature_bit)1040*f005ef32Sjsg static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
1041*f005ef32Sjsg 						int od_feature_bit)
1042*f005ef32Sjsg {
1043*f005ef32Sjsg 	PPTable_t *pptable = smu->smu_table.driver_pptable;
1044*f005ef32Sjsg 	const OverDriveLimits_t * const overdrive_upperlimits =
1045*f005ef32Sjsg 				&pptable->SkuTable.OverDriveLimitsBasicMax;
1046*f005ef32Sjsg 
1047*f005ef32Sjsg 	return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
1048*f005ef32Sjsg }
1049*f005ef32Sjsg 
smu_v13_0_7_get_od_setting_limits(struct smu_context * smu,int od_feature_bit,int32_t * min,int32_t * max)1050*f005ef32Sjsg static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
1051*f005ef32Sjsg 					      int od_feature_bit,
1052*f005ef32Sjsg 					      int32_t *min,
1053*f005ef32Sjsg 					      int32_t *max)
1054*f005ef32Sjsg {
1055*f005ef32Sjsg 	PPTable_t *pptable = smu->smu_table.driver_pptable;
1056*f005ef32Sjsg 	const OverDriveLimits_t * const overdrive_upperlimits =
1057*f005ef32Sjsg 				&pptable->SkuTable.OverDriveLimitsBasicMax;
1058*f005ef32Sjsg 	const OverDriveLimits_t * const overdrive_lowerlimits =
1059*f005ef32Sjsg 				&pptable->SkuTable.OverDriveLimitsMin;
1060*f005ef32Sjsg 	int32_t od_min_setting, od_max_setting;
1061*f005ef32Sjsg 
1062*f005ef32Sjsg 	switch (od_feature_bit) {
1063*f005ef32Sjsg 	case PP_OD_FEATURE_GFXCLK_FMIN:
1064*f005ef32Sjsg 		od_min_setting = overdrive_lowerlimits->GfxclkFmin;
1065*f005ef32Sjsg 		od_max_setting = overdrive_upperlimits->GfxclkFmin;
1066*f005ef32Sjsg 		break;
1067*f005ef32Sjsg 	case PP_OD_FEATURE_GFXCLK_FMAX:
1068*f005ef32Sjsg 		od_min_setting = overdrive_lowerlimits->GfxclkFmax;
1069*f005ef32Sjsg 		od_max_setting = overdrive_upperlimits->GfxclkFmax;
1070*f005ef32Sjsg 		break;
1071*f005ef32Sjsg 	case PP_OD_FEATURE_UCLK_FMIN:
1072*f005ef32Sjsg 		od_min_setting = overdrive_lowerlimits->UclkFmin;
1073*f005ef32Sjsg 		od_max_setting = overdrive_upperlimits->UclkFmin;
1074*f005ef32Sjsg 		break;
1075*f005ef32Sjsg 	case PP_OD_FEATURE_UCLK_FMAX:
1076*f005ef32Sjsg 		od_min_setting = overdrive_lowerlimits->UclkFmax;
1077*f005ef32Sjsg 		od_max_setting = overdrive_upperlimits->UclkFmax;
1078*f005ef32Sjsg 		break;
1079*f005ef32Sjsg 	case PP_OD_FEATURE_GFX_VF_CURVE:
1080*f005ef32Sjsg 		od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary;
1081*f005ef32Sjsg 		od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary;
1082*f005ef32Sjsg 		break;
1083*f005ef32Sjsg 	default:
1084*f005ef32Sjsg 		od_min_setting = od_max_setting = INT_MAX;
1085*f005ef32Sjsg 		break;
1086*f005ef32Sjsg 	}
1087*f005ef32Sjsg 
1088*f005ef32Sjsg 	if (min)
1089*f005ef32Sjsg 		*min = od_min_setting;
1090*f005ef32Sjsg 	if (max)
1091*f005ef32Sjsg 		*max = od_max_setting;
1092*f005ef32Sjsg }
1093*f005ef32Sjsg 
smu_v13_0_7_dump_od_table(struct smu_context * smu,OverDriveTableExternal_t * od_table)1094*f005ef32Sjsg static void smu_v13_0_7_dump_od_table(struct smu_context *smu,
1095*f005ef32Sjsg 				      OverDriveTableExternal_t *od_table)
1096*f005ef32Sjsg {
1097*f005ef32Sjsg 	struct amdgpu_device *adev = smu->adev;
1098*f005ef32Sjsg 
1099*f005ef32Sjsg 	dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin,
1100*f005ef32Sjsg 						     od_table->OverDriveTable.GfxclkFmax);
1101*f005ef32Sjsg 	dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
1102*f005ef32Sjsg 						   od_table->OverDriveTable.UclkFmax);
1103*f005ef32Sjsg }
1104*f005ef32Sjsg 
smu_v13_0_7_get_overdrive_table(struct smu_context * smu,OverDriveTableExternal_t * od_table)1105*f005ef32Sjsg static int smu_v13_0_7_get_overdrive_table(struct smu_context *smu,
1106*f005ef32Sjsg 					   OverDriveTableExternal_t *od_table)
1107*f005ef32Sjsg {
1108*f005ef32Sjsg 	int ret = 0;
1109*f005ef32Sjsg 
1110*f005ef32Sjsg 	ret = smu_cmn_update_table(smu,
1111*f005ef32Sjsg 				   SMU_TABLE_OVERDRIVE,
1112*f005ef32Sjsg 				   0,
1113*f005ef32Sjsg 				   (void *)od_table,
1114*f005ef32Sjsg 				   false);
1115*f005ef32Sjsg 	if (ret)
1116*f005ef32Sjsg 		dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
1117*f005ef32Sjsg 
1118*f005ef32Sjsg 	return ret;
1119*f005ef32Sjsg }
1120*f005ef32Sjsg 
smu_v13_0_7_upload_overdrive_table(struct smu_context * smu,OverDriveTableExternal_t * od_table)1121*f005ef32Sjsg static int smu_v13_0_7_upload_overdrive_table(struct smu_context *smu,
1122*f005ef32Sjsg 					      OverDriveTableExternal_t *od_table)
1123*f005ef32Sjsg {
1124*f005ef32Sjsg 	int ret = 0;
1125*f005ef32Sjsg 
1126*f005ef32Sjsg 	ret = smu_cmn_update_table(smu,
1127*f005ef32Sjsg 				   SMU_TABLE_OVERDRIVE,
1128*f005ef32Sjsg 				   0,
1129*f005ef32Sjsg 				   (void *)od_table,
1130*f005ef32Sjsg 				   true);
1131*f005ef32Sjsg 	if (ret)
1132*f005ef32Sjsg 		dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
1133*f005ef32Sjsg 
1134*f005ef32Sjsg 	return ret;
1135*f005ef32Sjsg }
1136*f005ef32Sjsg 
smu_v13_0_7_print_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,char * buf)11371bb76ff1Sjsg static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
11381bb76ff1Sjsg 					enum smu_clk_type clk_type,
11391bb76ff1Sjsg 					char *buf)
11401bb76ff1Sjsg {
11411bb76ff1Sjsg 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
11421bb76ff1Sjsg 	struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1143*f005ef32Sjsg 	OverDriveTableExternal_t *od_table =
1144*f005ef32Sjsg 		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
11451bb76ff1Sjsg 	struct smu_13_0_dpm_table *single_dpm_table;
11461bb76ff1Sjsg 	struct smu_13_0_pcie_table *pcie_table;
11471bb76ff1Sjsg 	uint32_t gen_speed, lane_width;
11481bb76ff1Sjsg 	int i, curr_freq, size = 0;
1149*f005ef32Sjsg 	int32_t min_value, max_value;
11501bb76ff1Sjsg 	int ret = 0;
11511bb76ff1Sjsg 
11521bb76ff1Sjsg 	smu_cmn_get_sysfs_buf(&buf, &size);
11531bb76ff1Sjsg 
11541bb76ff1Sjsg 	if (amdgpu_ras_intr_triggered()) {
11551bb76ff1Sjsg 		size += sysfs_emit_at(buf, size, "unavailable\n");
11561bb76ff1Sjsg 		return size;
11571bb76ff1Sjsg 	}
11581bb76ff1Sjsg 
11591bb76ff1Sjsg 	switch (clk_type) {
11601bb76ff1Sjsg 	case SMU_SCLK:
11611bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
11621bb76ff1Sjsg 		break;
11631bb76ff1Sjsg 	case SMU_MCLK:
11641bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
11651bb76ff1Sjsg 		break;
11661bb76ff1Sjsg 	case SMU_SOCCLK:
11671bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
11681bb76ff1Sjsg 		break;
11691bb76ff1Sjsg 	case SMU_FCLK:
11701bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
11711bb76ff1Sjsg 		break;
11721bb76ff1Sjsg 	case SMU_VCLK:
11731bb76ff1Sjsg 	case SMU_VCLK1:
11741bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
11751bb76ff1Sjsg 		break;
11761bb76ff1Sjsg 	case SMU_DCLK:
11771bb76ff1Sjsg 	case SMU_DCLK1:
11781bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
11791bb76ff1Sjsg 		break;
11801bb76ff1Sjsg 	default:
11811bb76ff1Sjsg 		break;
11821bb76ff1Sjsg 	}
11831bb76ff1Sjsg 
11841bb76ff1Sjsg 	switch (clk_type) {
11851bb76ff1Sjsg 	case SMU_SCLK:
11861bb76ff1Sjsg 	case SMU_MCLK:
11871bb76ff1Sjsg 	case SMU_SOCCLK:
11881bb76ff1Sjsg 	case SMU_FCLK:
11891bb76ff1Sjsg 	case SMU_VCLK:
11901bb76ff1Sjsg 	case SMU_VCLK1:
11911bb76ff1Sjsg 	case SMU_DCLK:
11921bb76ff1Sjsg 	case SMU_DCLK1:
11931bb76ff1Sjsg 		ret = smu_v13_0_7_get_current_clk_freq_by_table(smu, clk_type, &curr_freq);
11941bb76ff1Sjsg 		if (ret) {
11951bb76ff1Sjsg 			dev_err(smu->adev->dev, "Failed to get current clock freq!");
11961bb76ff1Sjsg 			return ret;
11971bb76ff1Sjsg 		}
11981bb76ff1Sjsg 
11991bb76ff1Sjsg 		if (single_dpm_table->is_fine_grained) {
12001bb76ff1Sjsg 			/*
12011bb76ff1Sjsg 			 * For fine grained dpms, there are only two dpm levels:
12021bb76ff1Sjsg 			 *   - level 0 -> min clock freq
12031bb76ff1Sjsg 			 *   - level 1 -> max clock freq
12041bb76ff1Sjsg 			 * And the current clock frequency can be any value between them.
12051bb76ff1Sjsg 			 * So, if the current clock frequency is not at level 0 or level 1,
12061bb76ff1Sjsg 			 * we will fake it as three dpm levels:
12071bb76ff1Sjsg 			 *   - level 0 -> min clock freq
12081bb76ff1Sjsg 			 *   - level 1 -> current actual clock freq
12091bb76ff1Sjsg 			 *   - level 2 -> max clock freq
12101bb76ff1Sjsg 			 */
12111bb76ff1Sjsg 			if ((single_dpm_table->dpm_levels[0].value != curr_freq) &&
12121bb76ff1Sjsg 			     (single_dpm_table->dpm_levels[1].value != curr_freq)) {
12131bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "0: %uMhz\n",
12141bb76ff1Sjsg 						single_dpm_table->dpm_levels[0].value);
12151bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "1: %uMhz *\n",
12161bb76ff1Sjsg 						curr_freq);
12171bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "2: %uMhz\n",
12181bb76ff1Sjsg 						single_dpm_table->dpm_levels[1].value);
12191bb76ff1Sjsg 			} else {
12201bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
12211bb76ff1Sjsg 						single_dpm_table->dpm_levels[0].value,
12221bb76ff1Sjsg 						single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : "");
12231bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
12241bb76ff1Sjsg 						single_dpm_table->dpm_levels[1].value,
12251bb76ff1Sjsg 						single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : "");
12261bb76ff1Sjsg 			}
12271bb76ff1Sjsg 		} else {
12281bb76ff1Sjsg 			for (i = 0; i < single_dpm_table->count; i++)
12291bb76ff1Sjsg 				size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
12301bb76ff1Sjsg 						i, single_dpm_table->dpm_levels[i].value,
12311bb76ff1Sjsg 						single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : "");
12321bb76ff1Sjsg 		}
12331bb76ff1Sjsg 		break;
12341bb76ff1Sjsg 	case SMU_PCIE:
12351bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
12361bb76ff1Sjsg 						       METRICS_PCIE_RATE,
12371bb76ff1Sjsg 						       &gen_speed);
12381bb76ff1Sjsg 		if (ret)
12391bb76ff1Sjsg 			return ret;
12401bb76ff1Sjsg 
12411bb76ff1Sjsg 		ret = smu_v13_0_7_get_smu_metrics_data(smu,
12421bb76ff1Sjsg 						       METRICS_PCIE_WIDTH,
12431bb76ff1Sjsg 						       &lane_width);
12441bb76ff1Sjsg 		if (ret)
12451bb76ff1Sjsg 			return ret;
12461bb76ff1Sjsg 
12471bb76ff1Sjsg 		pcie_table = &(dpm_context->dpm_tables.pcie_table);
12481bb76ff1Sjsg 		for (i = 0; i < pcie_table->num_of_link_levels; i++)
12491bb76ff1Sjsg 			size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
12501bb76ff1Sjsg 					(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
12511bb76ff1Sjsg 					(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
12521bb76ff1Sjsg 					(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
12531bb76ff1Sjsg 					(pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
12541bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 1) ? "x1" :
12551bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 2) ? "x2" :
12561bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 3) ? "x4" :
12571bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 4) ? "x8" :
12581bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 5) ? "x12" :
12591bb76ff1Sjsg 					(pcie_table->pcie_lane[i] == 6) ? "x16" : "",
12601bb76ff1Sjsg 					pcie_table->clk_freq[i],
1261*f005ef32Sjsg 					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
1262*f005ef32Sjsg 					(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
12631bb76ff1Sjsg 					"*" : "");
12641bb76ff1Sjsg 		break;
12651bb76ff1Sjsg 
1266*f005ef32Sjsg 	case SMU_OD_SCLK:
1267*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu,
1268*f005ef32Sjsg 							 PP_OD_FEATURE_GFXCLK_BIT))
1269*f005ef32Sjsg 			break;
1270*f005ef32Sjsg 
1271*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
1272*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
1273*f005ef32Sjsg 					od_table->OverDriveTable.GfxclkFmin,
1274*f005ef32Sjsg 					od_table->OverDriveTable.GfxclkFmax);
1275*f005ef32Sjsg 		break;
1276*f005ef32Sjsg 
1277*f005ef32Sjsg 	case SMU_OD_MCLK:
1278*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu,
1279*f005ef32Sjsg 							 PP_OD_FEATURE_UCLK_BIT))
1280*f005ef32Sjsg 			break;
1281*f005ef32Sjsg 
1282*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
1283*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
1284*f005ef32Sjsg 					od_table->OverDriveTable.UclkFmin,
1285*f005ef32Sjsg 					od_table->OverDriveTable.UclkFmax);
1286*f005ef32Sjsg 		break;
1287*f005ef32Sjsg 
1288*f005ef32Sjsg 	case SMU_OD_VDDC_CURVE:
1289*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu,
1290*f005ef32Sjsg 							 PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1291*f005ef32Sjsg 			break;
1292*f005ef32Sjsg 
1293*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "OD_VDDC_CURVE:\n");
1294*f005ef32Sjsg 		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
1295*f005ef32Sjsg 			size += sysfs_emit_at(buf, size, "%d: %dmv\n",
1296*f005ef32Sjsg 						i,
1297*f005ef32Sjsg 						od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i]);
1298*f005ef32Sjsg 		break;
1299*f005ef32Sjsg 
1300*f005ef32Sjsg 	case SMU_OD_RANGE:
1301*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
1302*f005ef32Sjsg 		    !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
1303*f005ef32Sjsg 		    !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1304*f005ef32Sjsg 			break;
1305*f005ef32Sjsg 
1306*f005ef32Sjsg 		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1307*f005ef32Sjsg 
1308*f005ef32Sjsg 		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
1309*f005ef32Sjsg 			smu_v13_0_7_get_od_setting_limits(smu,
1310*f005ef32Sjsg 							  PP_OD_FEATURE_GFXCLK_FMIN,
1311*f005ef32Sjsg 							  &min_value,
1312*f005ef32Sjsg 							  NULL);
1313*f005ef32Sjsg 			smu_v13_0_7_get_od_setting_limits(smu,
1314*f005ef32Sjsg 							  PP_OD_FEATURE_GFXCLK_FMAX,
1315*f005ef32Sjsg 							  NULL,
1316*f005ef32Sjsg 							  &max_value);
1317*f005ef32Sjsg 			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
1318*f005ef32Sjsg 					      min_value, max_value);
1319*f005ef32Sjsg 		}
1320*f005ef32Sjsg 
1321*f005ef32Sjsg 		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
1322*f005ef32Sjsg 			smu_v13_0_7_get_od_setting_limits(smu,
1323*f005ef32Sjsg 							  PP_OD_FEATURE_UCLK_FMIN,
1324*f005ef32Sjsg 							  &min_value,
1325*f005ef32Sjsg 							  NULL);
1326*f005ef32Sjsg 			smu_v13_0_7_get_od_setting_limits(smu,
1327*f005ef32Sjsg 							  PP_OD_FEATURE_UCLK_FMAX,
1328*f005ef32Sjsg 							  NULL,
1329*f005ef32Sjsg 							  &max_value);
1330*f005ef32Sjsg 			size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
1331*f005ef32Sjsg 					      min_value, max_value);
1332*f005ef32Sjsg 		}
1333*f005ef32Sjsg 
1334*f005ef32Sjsg 		if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
1335*f005ef32Sjsg 			smu_v13_0_7_get_od_setting_limits(smu,
1336*f005ef32Sjsg 							  PP_OD_FEATURE_GFX_VF_CURVE,
1337*f005ef32Sjsg 							  &min_value,
1338*f005ef32Sjsg 							  &max_value);
1339*f005ef32Sjsg 			size += sysfs_emit_at(buf, size, "VDDC_CURVE: %7dmv %10dmv\n",
1340*f005ef32Sjsg 					      min_value, max_value);
1341*f005ef32Sjsg 		}
1342*f005ef32Sjsg 		break;
1343*f005ef32Sjsg 
13441bb76ff1Sjsg 	default:
13451bb76ff1Sjsg 		break;
13461bb76ff1Sjsg 	}
13471bb76ff1Sjsg 
13481bb76ff1Sjsg 	return size;
13491bb76ff1Sjsg }
13501bb76ff1Sjsg 
smu_v13_0_7_od_edit_dpm_table(struct smu_context * smu,enum PP_OD_DPM_TABLE_COMMAND type,long input[],uint32_t size)1351*f005ef32Sjsg static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
1352*f005ef32Sjsg 					 enum PP_OD_DPM_TABLE_COMMAND type,
1353*f005ef32Sjsg 					 long input[],
1354*f005ef32Sjsg 					 uint32_t size)
1355*f005ef32Sjsg {
1356*f005ef32Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
1357*f005ef32Sjsg 	OverDriveTableExternal_t *od_table =
1358*f005ef32Sjsg 		(OverDriveTableExternal_t *)table_context->overdrive_table;
1359*f005ef32Sjsg 	struct amdgpu_device *adev = smu->adev;
1360*f005ef32Sjsg 	uint32_t offset_of_voltageoffset;
1361*f005ef32Sjsg 	int32_t minimum, maximum;
1362*f005ef32Sjsg 	uint32_t feature_ctrlmask;
1363*f005ef32Sjsg 	int i, ret = 0;
1364*f005ef32Sjsg 
1365*f005ef32Sjsg 	switch (type) {
1366*f005ef32Sjsg 	case PP_OD_EDIT_SCLK_VDDC_TABLE:
1367*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
1368*f005ef32Sjsg 			dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
1369*f005ef32Sjsg 			return -ENOTSUPP;
1370*f005ef32Sjsg 		}
1371*f005ef32Sjsg 
1372*f005ef32Sjsg 		for (i = 0; i < size; i += 2) {
1373*f005ef32Sjsg 			if (i + 2 > size) {
1374*f005ef32Sjsg 				dev_info(adev->dev, "invalid number of input parameters %d\n", size);
1375*f005ef32Sjsg 				return -EINVAL;
1376*f005ef32Sjsg 			}
1377*f005ef32Sjsg 
1378*f005ef32Sjsg 			switch (input[i]) {
1379*f005ef32Sjsg 			case 0:
1380*f005ef32Sjsg 				smu_v13_0_7_get_od_setting_limits(smu,
1381*f005ef32Sjsg 								  PP_OD_FEATURE_GFXCLK_FMIN,
1382*f005ef32Sjsg 								  &minimum,
1383*f005ef32Sjsg 								  &maximum);
1384*f005ef32Sjsg 				if (input[i + 1] < minimum ||
1385*f005ef32Sjsg 				    input[i + 1] > maximum) {
1386*f005ef32Sjsg 					dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n",
1387*f005ef32Sjsg 						input[i + 1], minimum, maximum);
1388*f005ef32Sjsg 					return -EINVAL;
1389*f005ef32Sjsg 				}
1390*f005ef32Sjsg 
1391*f005ef32Sjsg 				od_table->OverDriveTable.GfxclkFmin = input[i + 1];
1392*f005ef32Sjsg 				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
1393*f005ef32Sjsg 				break;
1394*f005ef32Sjsg 
1395*f005ef32Sjsg 			case 1:
1396*f005ef32Sjsg 				smu_v13_0_7_get_od_setting_limits(smu,
1397*f005ef32Sjsg 								  PP_OD_FEATURE_GFXCLK_FMAX,
1398*f005ef32Sjsg 								  &minimum,
1399*f005ef32Sjsg 								  &maximum);
1400*f005ef32Sjsg 				if (input[i + 1] < minimum ||
1401*f005ef32Sjsg 				    input[i + 1] > maximum) {
1402*f005ef32Sjsg 					dev_info(adev->dev, "GfxclkFmax (%ld) must be within [%u, %u]!\n",
1403*f005ef32Sjsg 						input[i + 1], minimum, maximum);
1404*f005ef32Sjsg 					return -EINVAL;
1405*f005ef32Sjsg 				}
1406*f005ef32Sjsg 
1407*f005ef32Sjsg 				od_table->OverDriveTable.GfxclkFmax = input[i + 1];
1408*f005ef32Sjsg 				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
1409*f005ef32Sjsg 				break;
1410*f005ef32Sjsg 
1411*f005ef32Sjsg 			default:
1412*f005ef32Sjsg 				dev_info(adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
1413*f005ef32Sjsg 				dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
1414*f005ef32Sjsg 				return -EINVAL;
1415*f005ef32Sjsg 			}
1416*f005ef32Sjsg 		}
1417*f005ef32Sjsg 
1418*f005ef32Sjsg 		if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) {
1419*f005ef32Sjsg 			dev_err(adev->dev,
1420*f005ef32Sjsg 				"Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n",
1421*f005ef32Sjsg 				(uint32_t)od_table->OverDriveTable.GfxclkFmin,
1422*f005ef32Sjsg 				(uint32_t)od_table->OverDriveTable.GfxclkFmax);
1423*f005ef32Sjsg 			return -EINVAL;
1424*f005ef32Sjsg 		}
1425*f005ef32Sjsg 		break;
1426*f005ef32Sjsg 
1427*f005ef32Sjsg 	case PP_OD_EDIT_MCLK_VDDC_TABLE:
1428*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
1429*f005ef32Sjsg 			dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
1430*f005ef32Sjsg 			return -ENOTSUPP;
1431*f005ef32Sjsg 		}
1432*f005ef32Sjsg 
1433*f005ef32Sjsg 		for (i = 0; i < size; i += 2) {
1434*f005ef32Sjsg 			if (i + 2 > size) {
1435*f005ef32Sjsg 				dev_info(adev->dev, "invalid number of input parameters %d\n", size);
1436*f005ef32Sjsg 				return -EINVAL;
1437*f005ef32Sjsg 			}
1438*f005ef32Sjsg 
1439*f005ef32Sjsg 			switch (input[i]) {
1440*f005ef32Sjsg 			case 0:
1441*f005ef32Sjsg 				smu_v13_0_7_get_od_setting_limits(smu,
1442*f005ef32Sjsg 								  PP_OD_FEATURE_UCLK_FMIN,
1443*f005ef32Sjsg 								  &minimum,
1444*f005ef32Sjsg 								  &maximum);
1445*f005ef32Sjsg 				if (input[i + 1] < minimum ||
1446*f005ef32Sjsg 				    input[i + 1] > maximum) {
1447*f005ef32Sjsg 					dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
1448*f005ef32Sjsg 						input[i + 1], minimum, maximum);
1449*f005ef32Sjsg 					return -EINVAL;
1450*f005ef32Sjsg 				}
1451*f005ef32Sjsg 
1452*f005ef32Sjsg 				od_table->OverDriveTable.UclkFmin = input[i + 1];
1453*f005ef32Sjsg 				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
1454*f005ef32Sjsg 				break;
1455*f005ef32Sjsg 
1456*f005ef32Sjsg 			case 1:
1457*f005ef32Sjsg 				smu_v13_0_7_get_od_setting_limits(smu,
1458*f005ef32Sjsg 								  PP_OD_FEATURE_UCLK_FMAX,
1459*f005ef32Sjsg 								  &minimum,
1460*f005ef32Sjsg 								  &maximum);
1461*f005ef32Sjsg 				if (input[i + 1] < minimum ||
1462*f005ef32Sjsg 				    input[i + 1] > maximum) {
1463*f005ef32Sjsg 					dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
1464*f005ef32Sjsg 						input[i + 1], minimum, maximum);
1465*f005ef32Sjsg 					return -EINVAL;
1466*f005ef32Sjsg 				}
1467*f005ef32Sjsg 
1468*f005ef32Sjsg 				od_table->OverDriveTable.UclkFmax = input[i + 1];
1469*f005ef32Sjsg 				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
1470*f005ef32Sjsg 				break;
1471*f005ef32Sjsg 
1472*f005ef32Sjsg 			default:
1473*f005ef32Sjsg 				dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
1474*f005ef32Sjsg 				dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
1475*f005ef32Sjsg 				return -EINVAL;
1476*f005ef32Sjsg 			}
1477*f005ef32Sjsg 		}
1478*f005ef32Sjsg 
1479*f005ef32Sjsg 		if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
1480*f005ef32Sjsg 			dev_err(adev->dev,
1481*f005ef32Sjsg 				"Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
1482*f005ef32Sjsg 				(uint32_t)od_table->OverDriveTable.UclkFmin,
1483*f005ef32Sjsg 				(uint32_t)od_table->OverDriveTable.UclkFmax);
1484*f005ef32Sjsg 			return -EINVAL;
1485*f005ef32Sjsg 		}
1486*f005ef32Sjsg 		break;
1487*f005ef32Sjsg 
1488*f005ef32Sjsg 	case PP_OD_EDIT_VDDC_CURVE:
1489*f005ef32Sjsg 		if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
1490*f005ef32Sjsg 			dev_warn(adev->dev, "VF curve setting not supported!\n");
1491*f005ef32Sjsg 			return -ENOTSUPP;
1492*f005ef32Sjsg 		}
1493*f005ef32Sjsg 
1494*f005ef32Sjsg 		if (input[0] >= PP_NUM_OD_VF_CURVE_POINTS ||
1495*f005ef32Sjsg 		    input[0] < 0)
1496*f005ef32Sjsg 			return -EINVAL;
1497*f005ef32Sjsg 
1498*f005ef32Sjsg 		smu_v13_0_7_get_od_setting_limits(smu,
1499*f005ef32Sjsg 						  PP_OD_FEATURE_GFX_VF_CURVE,
1500*f005ef32Sjsg 						  &minimum,
1501*f005ef32Sjsg 						  &maximum);
1502*f005ef32Sjsg 		if (input[1] < minimum ||
1503*f005ef32Sjsg 		    input[1] > maximum) {
1504*f005ef32Sjsg 			dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
1505*f005ef32Sjsg 				 input[1], minimum, maximum);
1506*f005ef32Sjsg 			return -EINVAL;
1507*f005ef32Sjsg 		}
1508*f005ef32Sjsg 
1509*f005ef32Sjsg 		od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[input[0]] = input[1];
1510*f005ef32Sjsg 		od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
1511*f005ef32Sjsg 		break;
1512*f005ef32Sjsg 
1513*f005ef32Sjsg 	case PP_OD_RESTORE_DEFAULT_TABLE:
1514*f005ef32Sjsg 		feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
1515*f005ef32Sjsg 		memcpy(od_table,
1516*f005ef32Sjsg 		       table_context->boot_overdrive_table,
1517*f005ef32Sjsg 		       sizeof(OverDriveTableExternal_t));
1518*f005ef32Sjsg 		od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
1519*f005ef32Sjsg 		fallthrough;
1520*f005ef32Sjsg 
1521*f005ef32Sjsg 	case PP_OD_COMMIT_DPM_TABLE:
1522*f005ef32Sjsg 		/*
1523*f005ef32Sjsg 		 * The member below instructs PMFW the settings focused in
1524*f005ef32Sjsg 		 * this single operation.
1525*f005ef32Sjsg 		 * `uint32_t FeatureCtrlMask;`
1526*f005ef32Sjsg 		 * It does not contain actual informations about user's custom
1527*f005ef32Sjsg 		 * settings. Thus we do not cache it.
1528*f005ef32Sjsg 		 */
1529*f005ef32Sjsg 		offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
1530*f005ef32Sjsg 		if (memcmp((u8 *)od_table + offset_of_voltageoffset,
1531*f005ef32Sjsg 			   table_context->user_overdrive_table + offset_of_voltageoffset,
1532*f005ef32Sjsg 			   sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
1533*f005ef32Sjsg 			smu_v13_0_7_dump_od_table(smu, od_table);
1534*f005ef32Sjsg 
1535*f005ef32Sjsg 			ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
1536*f005ef32Sjsg 			if (ret) {
1537*f005ef32Sjsg 				dev_err(adev->dev, "Failed to upload overdrive table!\n");
1538*f005ef32Sjsg 				return ret;
1539*f005ef32Sjsg 			}
1540*f005ef32Sjsg 
1541*f005ef32Sjsg 			od_table->OverDriveTable.FeatureCtrlMask = 0;
1542*f005ef32Sjsg 			memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
1543*f005ef32Sjsg 			       (u8 *)od_table + offset_of_voltageoffset,
1544*f005ef32Sjsg 			       sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
1545*f005ef32Sjsg 
1546*f005ef32Sjsg 			if (!memcmp(table_context->user_overdrive_table,
1547*f005ef32Sjsg 				    table_context->boot_overdrive_table,
1548*f005ef32Sjsg 				    sizeof(OverDriveTableExternal_t)))
1549*f005ef32Sjsg 				smu->user_dpm_profile.user_od = false;
1550*f005ef32Sjsg 			else
1551*f005ef32Sjsg 				smu->user_dpm_profile.user_od = true;
1552*f005ef32Sjsg 		}
1553*f005ef32Sjsg 		break;
1554*f005ef32Sjsg 
1555*f005ef32Sjsg 	default:
1556*f005ef32Sjsg 		return -ENOSYS;
1557*f005ef32Sjsg 	}
1558*f005ef32Sjsg 
1559*f005ef32Sjsg 	return ret;
1560*f005ef32Sjsg }
1561*f005ef32Sjsg 
smu_v13_0_7_force_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t mask)15621bb76ff1Sjsg static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
15631bb76ff1Sjsg 					enum smu_clk_type clk_type,
15641bb76ff1Sjsg 					uint32_t mask)
15651bb76ff1Sjsg {
15661bb76ff1Sjsg 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
15671bb76ff1Sjsg 	struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
15681bb76ff1Sjsg 	struct smu_13_0_dpm_table *single_dpm_table;
15691bb76ff1Sjsg 	uint32_t soft_min_level, soft_max_level;
15701bb76ff1Sjsg 	uint32_t min_freq, max_freq;
15711bb76ff1Sjsg 	int ret = 0;
15721bb76ff1Sjsg 
15731bb76ff1Sjsg 	soft_min_level = mask ? (ffs(mask) - 1) : 0;
15741bb76ff1Sjsg 	soft_max_level = mask ? (fls(mask) - 1) : 0;
15751bb76ff1Sjsg 
15761bb76ff1Sjsg 	switch (clk_type) {
15771bb76ff1Sjsg 	case SMU_GFXCLK:
15781bb76ff1Sjsg 	case SMU_SCLK:
15791bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
15801bb76ff1Sjsg 		break;
15811bb76ff1Sjsg 	case SMU_MCLK:
15821bb76ff1Sjsg 	case SMU_UCLK:
15831bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
15841bb76ff1Sjsg 		break;
15851bb76ff1Sjsg 	case SMU_SOCCLK:
15861bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
15871bb76ff1Sjsg 		break;
15881bb76ff1Sjsg 	case SMU_FCLK:
15891bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
15901bb76ff1Sjsg 		break;
15911bb76ff1Sjsg 	case SMU_VCLK:
15921bb76ff1Sjsg 	case SMU_VCLK1:
15931bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
15941bb76ff1Sjsg 		break;
15951bb76ff1Sjsg 	case SMU_DCLK:
15961bb76ff1Sjsg 	case SMU_DCLK1:
15971bb76ff1Sjsg 		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
15981bb76ff1Sjsg 		break;
15991bb76ff1Sjsg 	default:
16001bb76ff1Sjsg 		break;
16011bb76ff1Sjsg 	}
16021bb76ff1Sjsg 
16031bb76ff1Sjsg 	switch (clk_type) {
16041bb76ff1Sjsg 	case SMU_GFXCLK:
16051bb76ff1Sjsg 	case SMU_SCLK:
16061bb76ff1Sjsg 	case SMU_MCLK:
16071bb76ff1Sjsg 	case SMU_UCLK:
16081bb76ff1Sjsg 	case SMU_SOCCLK:
16091bb76ff1Sjsg 	case SMU_FCLK:
16101bb76ff1Sjsg 	case SMU_VCLK:
16111bb76ff1Sjsg 	case SMU_VCLK1:
16121bb76ff1Sjsg 	case SMU_DCLK:
16131bb76ff1Sjsg 	case SMU_DCLK1:
16141bb76ff1Sjsg 		if (single_dpm_table->is_fine_grained) {
16151bb76ff1Sjsg 			/* There is only 2 levels for fine grained DPM */
16161bb76ff1Sjsg 			soft_max_level = (soft_max_level >= 1 ? 1 : 0);
16171bb76ff1Sjsg 			soft_min_level = (soft_min_level >= 1 ? 1 : 0);
16181bb76ff1Sjsg 		} else {
16191bb76ff1Sjsg 			if ((soft_max_level >= single_dpm_table->count) ||
16201bb76ff1Sjsg 			    (soft_min_level >= single_dpm_table->count))
16211bb76ff1Sjsg 				return -EINVAL;
16221bb76ff1Sjsg 		}
16231bb76ff1Sjsg 
16241bb76ff1Sjsg 		min_freq = single_dpm_table->dpm_levels[soft_min_level].value;
16251bb76ff1Sjsg 		max_freq = single_dpm_table->dpm_levels[soft_max_level].value;
16261bb76ff1Sjsg 
16271bb76ff1Sjsg 		ret = smu_v13_0_set_soft_freq_limited_range(smu,
16281bb76ff1Sjsg 							    clk_type,
16291bb76ff1Sjsg 							    min_freq,
16301bb76ff1Sjsg 							    max_freq);
16311bb76ff1Sjsg 		break;
16321bb76ff1Sjsg 	case SMU_DCEFCLK:
16331bb76ff1Sjsg 	case SMU_PCIE:
16341bb76ff1Sjsg 	default:
16351bb76ff1Sjsg 		break;
16361bb76ff1Sjsg 	}
16371bb76ff1Sjsg 
16381bb76ff1Sjsg 	return ret;
16391bb76ff1Sjsg }
16401bb76ff1Sjsg 
1641*f005ef32Sjsg static const struct smu_temperature_range smu13_thermal_policy[] = {
16421bb76ff1Sjsg 	{-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
16431bb76ff1Sjsg 	{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
16441bb76ff1Sjsg };
16451bb76ff1Sjsg 
smu_v13_0_7_get_thermal_temperature_range(struct smu_context * smu,struct smu_temperature_range * range)16461bb76ff1Sjsg static int smu_v13_0_7_get_thermal_temperature_range(struct smu_context *smu,
16471bb76ff1Sjsg 						     struct smu_temperature_range *range)
16481bb76ff1Sjsg {
16491bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
16501bb76ff1Sjsg 	struct smu_13_0_7_powerplay_table *powerplay_table =
16511bb76ff1Sjsg 		table_context->power_play_table;
16521bb76ff1Sjsg 	PPTable_t *pptable = smu->smu_table.driver_pptable;
16531bb76ff1Sjsg 
16541bb76ff1Sjsg 	if (!range)
16551bb76ff1Sjsg 		return -EINVAL;
16561bb76ff1Sjsg 
16571bb76ff1Sjsg 	memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
16581bb76ff1Sjsg 
16591bb76ff1Sjsg 	range->max = pptable->SkuTable.TemperatureLimit[TEMP_EDGE] *
16601bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16611bb76ff1Sjsg 	range->edge_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) *
16621bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16631bb76ff1Sjsg 	range->hotspot_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] *
16641bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16651bb76ff1Sjsg 	range->hotspot_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) *
16661bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16671bb76ff1Sjsg 	range->mem_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_MEM] *
16681bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16691bb76ff1Sjsg 	range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
16701bb76ff1Sjsg 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
16711bb76ff1Sjsg 	range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
1672ff290ac4Sjsg 	range->software_shutdown_temp_offset = pptable->SkuTable.FanAbnormalTempLimitOffset;
16731bb76ff1Sjsg 
16741bb76ff1Sjsg 	return 0;
16751bb76ff1Sjsg }
16761bb76ff1Sjsg 
16771bb76ff1Sjsg #ifndef MAX
16781bb76ff1Sjsg #define MAX(a, b)	((a) > (b) ? (a) : (b))
16791bb76ff1Sjsg #endif
smu_v13_0_7_get_gpu_metrics(struct smu_context * smu,void ** table)16801bb76ff1Sjsg static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
16811bb76ff1Sjsg 					   void **table)
16821bb76ff1Sjsg {
16831bb76ff1Sjsg 	struct smu_table_context *smu_table = &smu->smu_table;
16841bb76ff1Sjsg 	struct gpu_metrics_v1_3 *gpu_metrics =
16851bb76ff1Sjsg 		(struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
16861bb76ff1Sjsg 	SmuMetricsExternal_t metrics_ext;
16871bb76ff1Sjsg 	SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
16881bb76ff1Sjsg 	int ret = 0;
16891bb76ff1Sjsg 
16901bb76ff1Sjsg 	ret = smu_cmn_get_metrics_table(smu,
16911bb76ff1Sjsg 					&metrics_ext,
16921bb76ff1Sjsg 					true);
16931bb76ff1Sjsg 	if (ret)
16941bb76ff1Sjsg 		return ret;
16951bb76ff1Sjsg 
16961bb76ff1Sjsg 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
16971bb76ff1Sjsg 
16981bb76ff1Sjsg 	gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE];
16991bb76ff1Sjsg 	gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT];
17001bb76ff1Sjsg 	gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM];
17011bb76ff1Sjsg 	gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX];
17021bb76ff1Sjsg 	gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC];
17031bb76ff1Sjsg 	gpu_metrics->temperature_vrmem = MAX(metrics->AvgTemperature[TEMP_VR_MEM0],
17041bb76ff1Sjsg 					     metrics->AvgTemperature[TEMP_VR_MEM1]);
17051bb76ff1Sjsg 
17061bb76ff1Sjsg 	gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
17071bb76ff1Sjsg 	gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
17081bb76ff1Sjsg 	gpu_metrics->average_mm_activity = MAX(metrics->Vcn0ActivityPercentage,
17091bb76ff1Sjsg 					       metrics->Vcn1ActivityPercentage);
17101bb76ff1Sjsg 
17111bb76ff1Sjsg 	gpu_metrics->average_socket_power = metrics->AverageSocketPower;
17121bb76ff1Sjsg 	gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
17131bb76ff1Sjsg 
17141bb76ff1Sjsg 	if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
17151bb76ff1Sjsg 		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
17161bb76ff1Sjsg 	else
17171bb76ff1Sjsg 		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
17181bb76ff1Sjsg 
17191bb76ff1Sjsg 	if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
17201bb76ff1Sjsg 		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
17211bb76ff1Sjsg 	else
17221bb76ff1Sjsg 		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
17231bb76ff1Sjsg 
17241bb76ff1Sjsg 	gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
17251bb76ff1Sjsg 	gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
17261bb76ff1Sjsg 	gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
17271bb76ff1Sjsg 	gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
17281bb76ff1Sjsg 
17291bb76ff1Sjsg 	gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
17301bb76ff1Sjsg 	gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
17311bb76ff1Sjsg 	gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
17321bb76ff1Sjsg 	gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
17331bb76ff1Sjsg 	gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
17341bb76ff1Sjsg 
17351bb76ff1Sjsg 	gpu_metrics->throttle_status =
17361bb76ff1Sjsg 			smu_v13_0_7_get_throttler_status(metrics);
17371bb76ff1Sjsg 	gpu_metrics->indep_throttle_status =
17381bb76ff1Sjsg 			smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
17391bb76ff1Sjsg 							   smu_v13_0_7_throttler_map);
17401bb76ff1Sjsg 
17411bb76ff1Sjsg 	gpu_metrics->current_fan_speed = metrics->AvgFanRpm;
17421bb76ff1Sjsg 
17431bb76ff1Sjsg 	gpu_metrics->pcie_link_width = metrics->PcieWidth;
1744*f005ef32Sjsg 	if ((metrics->PcieRate - 1) > LINK_SPEED_MAX)
1745*f005ef32Sjsg 		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(1);
1746*f005ef32Sjsg 	else
1747*f005ef32Sjsg 		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(metrics->PcieRate);
17481bb76ff1Sjsg 
17491bb76ff1Sjsg 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
17501bb76ff1Sjsg 
17511bb76ff1Sjsg 	gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_GFX];
17521bb76ff1Sjsg 	gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_SOC];
17531bb76ff1Sjsg 	gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VMEMP];
17541bb76ff1Sjsg 
17551bb76ff1Sjsg 	*table = (void *)gpu_metrics;
17561bb76ff1Sjsg 
17571bb76ff1Sjsg 	return sizeof(struct gpu_metrics_v1_3);
17581bb76ff1Sjsg }
17591bb76ff1Sjsg 
smu_v13_0_7_set_default_od_settings(struct smu_context * smu)1760*f005ef32Sjsg static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
1761*f005ef32Sjsg {
1762*f005ef32Sjsg 	OverDriveTableExternal_t *od_table =
1763*f005ef32Sjsg 		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
1764*f005ef32Sjsg 	OverDriveTableExternal_t *boot_od_table =
1765*f005ef32Sjsg 		(OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
1766*f005ef32Sjsg 	OverDriveTableExternal_t *user_od_table =
1767*f005ef32Sjsg 		(OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
1768*f005ef32Sjsg 	OverDriveTableExternal_t user_od_table_bak;
1769*f005ef32Sjsg 	int ret = 0;
1770*f005ef32Sjsg 	int i;
1771*f005ef32Sjsg 
1772*f005ef32Sjsg 	ret = smu_v13_0_7_get_overdrive_table(smu, boot_od_table);
1773*f005ef32Sjsg 	if (ret)
1774*f005ef32Sjsg 		return ret;
1775*f005ef32Sjsg 
1776*f005ef32Sjsg 	smu_v13_0_7_dump_od_table(smu, boot_od_table);
1777*f005ef32Sjsg 
1778*f005ef32Sjsg 	memcpy(od_table,
1779*f005ef32Sjsg 	       boot_od_table,
1780*f005ef32Sjsg 	       sizeof(OverDriveTableExternal_t));
1781*f005ef32Sjsg 
1782*f005ef32Sjsg 	/*
1783*f005ef32Sjsg 	 * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
1784*f005ef32Sjsg 	 * but we have to preserve user defined values in "user_od_table".
1785*f005ef32Sjsg 	 */
1786*f005ef32Sjsg 	if (!smu->adev->in_suspend) {
1787*f005ef32Sjsg 		memcpy(user_od_table,
1788*f005ef32Sjsg 		       boot_od_table,
1789*f005ef32Sjsg 		       sizeof(OverDriveTableExternal_t));
1790*f005ef32Sjsg 		smu->user_dpm_profile.user_od = false;
1791*f005ef32Sjsg 	} else if (smu->user_dpm_profile.user_od) {
1792*f005ef32Sjsg 		memcpy(&user_od_table_bak,
1793*f005ef32Sjsg 		       user_od_table,
1794*f005ef32Sjsg 		       sizeof(OverDriveTableExternal_t));
1795*f005ef32Sjsg 		memcpy(user_od_table,
1796*f005ef32Sjsg 		       boot_od_table,
1797*f005ef32Sjsg 		       sizeof(OverDriveTableExternal_t));
1798*f005ef32Sjsg 		user_od_table->OverDriveTable.GfxclkFmin =
1799*f005ef32Sjsg 				user_od_table_bak.OverDriveTable.GfxclkFmin;
1800*f005ef32Sjsg 		user_od_table->OverDriveTable.GfxclkFmax =
1801*f005ef32Sjsg 				user_od_table_bak.OverDriveTable.GfxclkFmax;
1802*f005ef32Sjsg 		user_od_table->OverDriveTable.UclkFmin =
1803*f005ef32Sjsg 				user_od_table_bak.OverDriveTable.UclkFmin;
1804*f005ef32Sjsg 		user_od_table->OverDriveTable.UclkFmax =
1805*f005ef32Sjsg 				user_od_table_bak.OverDriveTable.UclkFmax;
1806*f005ef32Sjsg 		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
1807*f005ef32Sjsg 			user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
1808*f005ef32Sjsg 				user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
1809*f005ef32Sjsg 	}
1810*f005ef32Sjsg 
1811*f005ef32Sjsg 	return 0;
1812*f005ef32Sjsg }
1813*f005ef32Sjsg 
smu_v13_0_7_restore_user_od_settings(struct smu_context * smu)1814*f005ef32Sjsg static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu)
1815*f005ef32Sjsg {
1816*f005ef32Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
1817*f005ef32Sjsg 	OverDriveTableExternal_t *od_table = table_context->overdrive_table;
1818*f005ef32Sjsg 	OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
1819*f005ef32Sjsg 	int res;
1820*f005ef32Sjsg 
1821*f005ef32Sjsg 	user_od_table->OverDriveTable.FeatureCtrlMask = 1U << PP_OD_FEATURE_GFXCLK_BIT |
1822*f005ef32Sjsg 							1U << PP_OD_FEATURE_UCLK_BIT |
1823*f005ef32Sjsg 							1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
1824*f005ef32Sjsg 	res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table);
1825*f005ef32Sjsg 	user_od_table->OverDriveTable.FeatureCtrlMask = 0;
1826*f005ef32Sjsg 	if (res == 0)
1827*f005ef32Sjsg 		memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
1828*f005ef32Sjsg 
1829*f005ef32Sjsg 	return res;
1830*f005ef32Sjsg }
1831*f005ef32Sjsg 
smu_v13_0_7_populate_umd_state_clk(struct smu_context * smu)18321bb76ff1Sjsg static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
18331bb76ff1Sjsg {
18341bb76ff1Sjsg 	struct smu_13_0_dpm_context *dpm_context =
18351bb76ff1Sjsg 				smu->smu_dpm.dpm_context;
18361bb76ff1Sjsg 	struct smu_13_0_dpm_table *gfx_table =
18371bb76ff1Sjsg 				&dpm_context->dpm_tables.gfx_table;
18381bb76ff1Sjsg 	struct smu_13_0_dpm_table *mem_table =
18391bb76ff1Sjsg 				&dpm_context->dpm_tables.uclk_table;
18401bb76ff1Sjsg 	struct smu_13_0_dpm_table *soc_table =
18411bb76ff1Sjsg 				&dpm_context->dpm_tables.soc_table;
18421bb76ff1Sjsg 	struct smu_13_0_dpm_table *vclk_table =
18431bb76ff1Sjsg 				&dpm_context->dpm_tables.vclk_table;
18441bb76ff1Sjsg 	struct smu_13_0_dpm_table *dclk_table =
18451bb76ff1Sjsg 				&dpm_context->dpm_tables.dclk_table;
18461bb76ff1Sjsg 	struct smu_13_0_dpm_table *fclk_table =
18471bb76ff1Sjsg 				&dpm_context->dpm_tables.fclk_table;
18481bb76ff1Sjsg 	struct smu_umd_pstate_table *pstate_table =
18491bb76ff1Sjsg 				&smu->pstate_table;
18506dedd6ecSjsg 	struct smu_table_context *table_context = &smu->smu_table;
18516dedd6ecSjsg 	PPTable_t *pptable = table_context->driver_pptable;
18526dedd6ecSjsg 	DriverReportedClocks_t driver_clocks =
18536dedd6ecSjsg 		pptable->SkuTable.DriverReportedClocks;
18541bb76ff1Sjsg 
18551bb76ff1Sjsg 	pstate_table->gfxclk_pstate.min = gfx_table->min;
18566dedd6ecSjsg 	if (driver_clocks.GameClockAc &&
18576dedd6ecSjsg 		(driver_clocks.GameClockAc < gfx_table->max))
18586dedd6ecSjsg 		pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc;
18596dedd6ecSjsg 	else
18601bb76ff1Sjsg 		pstate_table->gfxclk_pstate.peak = gfx_table->max;
18611bb76ff1Sjsg 
18621bb76ff1Sjsg 	pstate_table->uclk_pstate.min = mem_table->min;
18631bb76ff1Sjsg 	pstate_table->uclk_pstate.peak = mem_table->max;
18641bb76ff1Sjsg 
18651bb76ff1Sjsg 	pstate_table->socclk_pstate.min = soc_table->min;
18661bb76ff1Sjsg 	pstate_table->socclk_pstate.peak = soc_table->max;
18671bb76ff1Sjsg 
18681bb76ff1Sjsg 	pstate_table->vclk_pstate.min = vclk_table->min;
18691bb76ff1Sjsg 	pstate_table->vclk_pstate.peak = vclk_table->max;
18701bb76ff1Sjsg 
18711bb76ff1Sjsg 	pstate_table->dclk_pstate.min = dclk_table->min;
18721bb76ff1Sjsg 	pstate_table->dclk_pstate.peak = dclk_table->max;
18731bb76ff1Sjsg 
18741bb76ff1Sjsg 	pstate_table->fclk_pstate.min = fclk_table->min;
18751bb76ff1Sjsg 	pstate_table->fclk_pstate.peak = fclk_table->max;
18761bb76ff1Sjsg 
18776dedd6ecSjsg 	if (driver_clocks.BaseClockAc &&
18786dedd6ecSjsg 		driver_clocks.BaseClockAc < gfx_table->max)
18796dedd6ecSjsg 		pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc;
18806dedd6ecSjsg 	else
18816dedd6ecSjsg 		pstate_table->gfxclk_pstate.standard = gfx_table->max;
18826dedd6ecSjsg 	pstate_table->uclk_pstate.standard = mem_table->max;
18831bb76ff1Sjsg 	pstate_table->socclk_pstate.standard = soc_table->min;
18841bb76ff1Sjsg 	pstate_table->vclk_pstate.standard = vclk_table->min;
18851bb76ff1Sjsg 	pstate_table->dclk_pstate.standard = dclk_table->min;
18861bb76ff1Sjsg 	pstate_table->fclk_pstate.standard = fclk_table->min;
18871bb76ff1Sjsg 
18881bb76ff1Sjsg 	return 0;
18891bb76ff1Sjsg }
18901bb76ff1Sjsg 
smu_v13_0_7_get_fan_speed_pwm(struct smu_context * smu,uint32_t * speed)18911bb76ff1Sjsg static int smu_v13_0_7_get_fan_speed_pwm(struct smu_context *smu,
18921bb76ff1Sjsg 					 uint32_t *speed)
18931bb76ff1Sjsg {
18943415d987Sjsg 	int ret;
18953415d987Sjsg 
18961bb76ff1Sjsg 	if (!speed)
18971bb76ff1Sjsg 		return -EINVAL;
18981bb76ff1Sjsg 
18993415d987Sjsg 	ret = smu_v13_0_7_get_smu_metrics_data(smu,
19001bb76ff1Sjsg 					       METRICS_CURR_FANPWM,
19011bb76ff1Sjsg 					       speed);
19023415d987Sjsg 	if (ret) {
19033415d987Sjsg 		dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!");
19043415d987Sjsg 		return ret;
19053415d987Sjsg 	}
19063415d987Sjsg 
19073415d987Sjsg 	/* Convert the PMFW output which is in percent to pwm(255) based */
19083415d987Sjsg 	*speed = MIN(*speed * 255 / 100, 255);
19093415d987Sjsg 
19103415d987Sjsg 	return 0;
19111bb76ff1Sjsg }
19121bb76ff1Sjsg 
smu_v13_0_7_get_fan_speed_rpm(struct smu_context * smu,uint32_t * speed)19131bb76ff1Sjsg static int smu_v13_0_7_get_fan_speed_rpm(struct smu_context *smu,
19141bb76ff1Sjsg 					 uint32_t *speed)
19151bb76ff1Sjsg {
19161bb76ff1Sjsg 	if (!speed)
19171bb76ff1Sjsg 		return -EINVAL;
19181bb76ff1Sjsg 
19191bb76ff1Sjsg 	return smu_v13_0_7_get_smu_metrics_data(smu,
19201bb76ff1Sjsg 						METRICS_CURR_FANSPEED,
19211bb76ff1Sjsg 						speed);
19221bb76ff1Sjsg }
19231bb76ff1Sjsg 
smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context * smu)19241bb76ff1Sjsg static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
19251bb76ff1Sjsg {
19261bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
19271bb76ff1Sjsg 	PPTable_t *pptable = table_context->driver_pptable;
19281bb76ff1Sjsg 	SkuTable_t *skutable = &pptable->SkuTable;
19291bb76ff1Sjsg 
19301bb76ff1Sjsg 	/*
19311bb76ff1Sjsg 	 * Skip the MGpuFanBoost setting for those ASICs
19321bb76ff1Sjsg 	 * which do not support it
19331bb76ff1Sjsg 	 */
19341bb76ff1Sjsg 	if (skutable->MGpuAcousticLimitRpmThreshold == 0)
19351bb76ff1Sjsg 		return 0;
19361bb76ff1Sjsg 
19371bb76ff1Sjsg 	return smu_cmn_send_smc_msg_with_param(smu,
19381bb76ff1Sjsg 					       SMU_MSG_SetMGpuFanBoostLimitRpm,
19391bb76ff1Sjsg 					       0,
19401bb76ff1Sjsg 					       NULL);
19411bb76ff1Sjsg }
19421bb76ff1Sjsg 
smu_v13_0_7_get_power_limit(struct smu_context * smu,uint32_t * current_power_limit,uint32_t * default_power_limit,uint32_t * max_power_limit)19431bb76ff1Sjsg static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
19441bb76ff1Sjsg 				       uint32_t *current_power_limit,
19451bb76ff1Sjsg 				       uint32_t *default_power_limit,
19461bb76ff1Sjsg 				       uint32_t *max_power_limit)
19471bb76ff1Sjsg {
19481bb76ff1Sjsg 	struct smu_table_context *table_context = &smu->smu_table;
19491bb76ff1Sjsg 	struct smu_13_0_7_powerplay_table *powerplay_table =
19501bb76ff1Sjsg 		(struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
19511bb76ff1Sjsg 	PPTable_t *pptable = table_context->driver_pptable;
19521bb76ff1Sjsg 	SkuTable_t *skutable = &pptable->SkuTable;
19531bb76ff1Sjsg 	uint32_t power_limit, od_percent;
19541bb76ff1Sjsg 
19551bb76ff1Sjsg 	if (smu_v13_0_get_current_power_limit(smu, &power_limit))
19561bb76ff1Sjsg 		power_limit = smu->adev->pm.ac_power ?
19571bb76ff1Sjsg 			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
19581bb76ff1Sjsg 			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
19591bb76ff1Sjsg 
19601bb76ff1Sjsg 	if (current_power_limit)
19611bb76ff1Sjsg 		*current_power_limit = power_limit;
19621bb76ff1Sjsg 	if (default_power_limit)
19631bb76ff1Sjsg 		*default_power_limit = power_limit;
19641bb76ff1Sjsg 
19651bb76ff1Sjsg 	if (max_power_limit) {
19661bb76ff1Sjsg 		if (smu->od_enabled) {
19671bb76ff1Sjsg 			od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
19681bb76ff1Sjsg 
19691bb76ff1Sjsg 			dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
19701bb76ff1Sjsg 
19711bb76ff1Sjsg 			power_limit *= (100 + od_percent);
19721bb76ff1Sjsg 			power_limit /= 100;
19731bb76ff1Sjsg 		}
19741bb76ff1Sjsg 		*max_power_limit = power_limit;
19751bb76ff1Sjsg 	}
19761bb76ff1Sjsg 
19771bb76ff1Sjsg 	return 0;
19781bb76ff1Sjsg }
19791bb76ff1Sjsg 
smu_v13_0_7_get_power_profile_mode(struct smu_context * smu,char * buf)19801bb76ff1Sjsg static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf)
19811bb76ff1Sjsg {
19821bb76ff1Sjsg 	DpmActivityMonitorCoeffIntExternal_t *activity_monitor_external;
19831bb76ff1Sjsg 	uint32_t i, j, size = 0;
19841bb76ff1Sjsg 	int16_t workload_type = 0;
19851bb76ff1Sjsg 	int result = 0;
19861bb76ff1Sjsg 
19871bb76ff1Sjsg 	if (!buf)
19881bb76ff1Sjsg 		return -EINVAL;
19891bb76ff1Sjsg 
19901bb76ff1Sjsg 	activity_monitor_external = kcalloc(PP_SMC_POWER_PROFILE_COUNT,
19911bb76ff1Sjsg 					    sizeof(*activity_monitor_external),
19921bb76ff1Sjsg 					    GFP_KERNEL);
19931bb76ff1Sjsg 	if (!activity_monitor_external)
19941bb76ff1Sjsg 		return -ENOMEM;
19951bb76ff1Sjsg 
19961bb76ff1Sjsg 	size += sysfs_emit_at(buf, size, "                              ");
19971bb76ff1Sjsg 	for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++)
19981bb76ff1Sjsg 		size += sysfs_emit_at(buf, size, "%-14s%s", amdgpu_pp_profile_name[i],
19991bb76ff1Sjsg 			(i == smu->power_profile_mode) ? "* " : "  ");
20001bb76ff1Sjsg 
20011bb76ff1Sjsg 	size += sysfs_emit_at(buf, size, "\n");
20021bb76ff1Sjsg 
20031bb76ff1Sjsg 	for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) {
20041bb76ff1Sjsg 		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
20051bb76ff1Sjsg 		workload_type = smu_cmn_to_asic_specific_index(smu,
20061bb76ff1Sjsg 							       CMN2ASIC_MAPPING_WORKLOAD,
20071bb76ff1Sjsg 							       i);
2008*f005ef32Sjsg 		if (workload_type == -ENOTSUPP)
2009*f005ef32Sjsg 			continue;
2010*f005ef32Sjsg 		else if (workload_type < 0) {
20111bb76ff1Sjsg 			result = -EINVAL;
20121bb76ff1Sjsg 			goto out;
20131bb76ff1Sjsg 		}
20141bb76ff1Sjsg 
20151bb76ff1Sjsg 		result = smu_cmn_update_table(smu,
20161bb76ff1Sjsg 					  SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
20171bb76ff1Sjsg 					  (void *)(&activity_monitor_external[i]), false);
20181bb76ff1Sjsg 		if (result) {
20191bb76ff1Sjsg 			dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
20201bb76ff1Sjsg 			goto out;
20211bb76ff1Sjsg 		}
20221bb76ff1Sjsg 	}
20231bb76ff1Sjsg 
20241bb76ff1Sjsg #define PRINT_DPM_MONITOR(field)									\
20251bb76ff1Sjsg do {													\
20261bb76ff1Sjsg 	size += sysfs_emit_at(buf, size, "%-30s", #field);						\
20271bb76ff1Sjsg 	for (j = 0; j <= PP_SMC_POWER_PROFILE_WINDOW3D; j++)						\
20281bb76ff1Sjsg 		size += sysfs_emit_at(buf, size, "%-16d", activity_monitor_external[j].DpmActivityMonitorCoeffInt.field);		\
20291bb76ff1Sjsg 	size += sysfs_emit_at(buf, size, "\n");								\
20301bb76ff1Sjsg } while (0)
20311bb76ff1Sjsg 
20321bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_ActiveHystLimit);
20331bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_IdleHystLimit);
20341bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_FPS);
20351bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_MinActiveFreqType);
20361bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_BoosterFreqType);
20371bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_MinActiveFreq);
20381bb76ff1Sjsg 	PRINT_DPM_MONITOR(Gfx_BoosterFreq);
20391bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_ActiveHystLimit);
20401bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_IdleHystLimit);
20411bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_FPS);
20421bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_MinActiveFreqType);
20431bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_BoosterFreqType);
20441bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_MinActiveFreq);
20451bb76ff1Sjsg 	PRINT_DPM_MONITOR(Fclk_BoosterFreq);
20461bb76ff1Sjsg #undef PRINT_DPM_MONITOR
20471bb76ff1Sjsg 
20481bb76ff1Sjsg 	result = size;
20491bb76ff1Sjsg out:
20501bb76ff1Sjsg 	kfree(activity_monitor_external);
20511bb76ff1Sjsg 	return result;
20521bb76ff1Sjsg }
20531bb76ff1Sjsg 
smu_v13_0_7_set_power_profile_mode(struct smu_context * smu,long * input,uint32_t size)20541bb76ff1Sjsg static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
20551bb76ff1Sjsg {
20561bb76ff1Sjsg 
20571bb76ff1Sjsg 	DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
20581bb76ff1Sjsg 	DpmActivityMonitorCoeffInt_t *activity_monitor =
20591bb76ff1Sjsg 		&(activity_monitor_external.DpmActivityMonitorCoeffInt);
20601bb76ff1Sjsg 	int workload_type, ret = 0;
20611bb76ff1Sjsg 
20621bb76ff1Sjsg 	smu->power_profile_mode = input[size];
20631bb76ff1Sjsg 
20641bb76ff1Sjsg 	if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
20651bb76ff1Sjsg 		dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
20661bb76ff1Sjsg 		return -EINVAL;
20671bb76ff1Sjsg 	}
20681bb76ff1Sjsg 
20691bb76ff1Sjsg 	if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
20701bb76ff1Sjsg 
20711bb76ff1Sjsg 		ret = smu_cmn_update_table(smu,
20721bb76ff1Sjsg 				       SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
20731bb76ff1Sjsg 				       (void *)(&activity_monitor_external), false);
20741bb76ff1Sjsg 		if (ret) {
20751bb76ff1Sjsg 			dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
20761bb76ff1Sjsg 			return ret;
20771bb76ff1Sjsg 		}
20781bb76ff1Sjsg 
20791bb76ff1Sjsg 		switch (input[0]) {
20801bb76ff1Sjsg 		case 0: /* Gfxclk */
20811bb76ff1Sjsg 			activity_monitor->Gfx_ActiveHystLimit = input[1];
20821bb76ff1Sjsg 			activity_monitor->Gfx_IdleHystLimit = input[2];
20831bb76ff1Sjsg 			activity_monitor->Gfx_FPS = input[3];
20841bb76ff1Sjsg 			activity_monitor->Gfx_MinActiveFreqType = input[4];
20851bb76ff1Sjsg 			activity_monitor->Gfx_BoosterFreqType = input[5];
20861bb76ff1Sjsg 			activity_monitor->Gfx_MinActiveFreq = input[6];
20871bb76ff1Sjsg 			activity_monitor->Gfx_BoosterFreq = input[7];
20881bb76ff1Sjsg 			break;
20891bb76ff1Sjsg 		case 1: /* Fclk */
20901bb76ff1Sjsg 			activity_monitor->Fclk_ActiveHystLimit = input[1];
20911bb76ff1Sjsg 			activity_monitor->Fclk_IdleHystLimit = input[2];
20921bb76ff1Sjsg 			activity_monitor->Fclk_FPS = input[3];
20931bb76ff1Sjsg 			activity_monitor->Fclk_MinActiveFreqType = input[4];
20941bb76ff1Sjsg 			activity_monitor->Fclk_BoosterFreqType = input[5];
20951bb76ff1Sjsg 			activity_monitor->Fclk_MinActiveFreq = input[6];
20961bb76ff1Sjsg 			activity_monitor->Fclk_BoosterFreq = input[7];
20971bb76ff1Sjsg 			break;
20981bb76ff1Sjsg 		}
20991bb76ff1Sjsg 
21001bb76ff1Sjsg 		ret = smu_cmn_update_table(smu,
21011bb76ff1Sjsg 				       SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
21021bb76ff1Sjsg 				       (void *)(&activity_monitor_external), true);
21031bb76ff1Sjsg 		if (ret) {
21041bb76ff1Sjsg 			dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
21051bb76ff1Sjsg 			return ret;
21061bb76ff1Sjsg 		}
21071bb76ff1Sjsg 	}
21081bb76ff1Sjsg 
21091bb76ff1Sjsg 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
21101bb76ff1Sjsg 	workload_type = smu_cmn_to_asic_specific_index(smu,
21111bb76ff1Sjsg 						       CMN2ASIC_MAPPING_WORKLOAD,
21121bb76ff1Sjsg 						       smu->power_profile_mode);
21131bb76ff1Sjsg 	if (workload_type < 0)
21141bb76ff1Sjsg 		return -EINVAL;
21151bb76ff1Sjsg 	smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
21161bb76ff1Sjsg 				    1 << workload_type, NULL);
21171bb76ff1Sjsg 
21181bb76ff1Sjsg 	return ret;
21191bb76ff1Sjsg }
21201bb76ff1Sjsg 
smu_v13_0_7_set_mp1_state(struct smu_context * smu,enum pp_mp1_state mp1_state)21211bb76ff1Sjsg static int smu_v13_0_7_set_mp1_state(struct smu_context *smu,
21221bb76ff1Sjsg 				     enum pp_mp1_state mp1_state)
21231bb76ff1Sjsg {
21241bb76ff1Sjsg 	int ret;
21251bb76ff1Sjsg 
21261bb76ff1Sjsg 	switch (mp1_state) {
21271bb76ff1Sjsg 	case PP_MP1_STATE_UNLOAD:
21281bb76ff1Sjsg 		ret = smu_cmn_set_mp1_state(smu, mp1_state);
21291bb76ff1Sjsg 		break;
21301bb76ff1Sjsg 	default:
21311bb76ff1Sjsg 		/* Ignore others */
21321bb76ff1Sjsg 		ret = 0;
21331bb76ff1Sjsg 	}
21341bb76ff1Sjsg 
21351bb76ff1Sjsg 	return ret;
21361bb76ff1Sjsg }
21371bb76ff1Sjsg 
smu_v13_0_7_baco_enter(struct smu_context * smu)21381bb76ff1Sjsg static int smu_v13_0_7_baco_enter(struct smu_context *smu)
21391bb76ff1Sjsg {
21401bb76ff1Sjsg 	struct smu_baco_context *smu_baco = &smu->smu_baco;
21411bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
21421bb76ff1Sjsg 
21431bb76ff1Sjsg 	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev))
21441bb76ff1Sjsg 		return smu_v13_0_baco_set_armd3_sequence(smu,
2145*f005ef32Sjsg 				(smu_baco->maco_support && amdgpu_runtime_pm != 1) ?
2146*f005ef32Sjsg 					BACO_SEQ_BAMACO : BACO_SEQ_BACO);
21471bb76ff1Sjsg 	else
21481bb76ff1Sjsg 		return smu_v13_0_baco_enter(smu);
21491bb76ff1Sjsg }
21501bb76ff1Sjsg 
smu_v13_0_7_baco_exit(struct smu_context * smu)21511bb76ff1Sjsg static int smu_v13_0_7_baco_exit(struct smu_context *smu)
21521bb76ff1Sjsg {
21531bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
21541bb76ff1Sjsg 
21551bb76ff1Sjsg 	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {
21561bb76ff1Sjsg 		/* Wait for PMFW handling for the Dstate change */
21571bb76ff1Sjsg 		usleep_range(10000, 11000);
21581bb76ff1Sjsg 		return smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
21591bb76ff1Sjsg 	} else {
21601bb76ff1Sjsg 		return smu_v13_0_baco_exit(smu);
21611bb76ff1Sjsg 	}
21621bb76ff1Sjsg }
21631bb76ff1Sjsg 
smu_v13_0_7_is_mode1_reset_supported(struct smu_context * smu)21641bb76ff1Sjsg static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu)
21651bb76ff1Sjsg {
21661bb76ff1Sjsg 	struct amdgpu_device *adev = smu->adev;
21671bb76ff1Sjsg 
21681bb76ff1Sjsg 	/* SRIOV does not support SMU mode1 reset */
21691bb76ff1Sjsg 	if (amdgpu_sriov_vf(adev))
21701bb76ff1Sjsg 		return false;
21711bb76ff1Sjsg 
21721bb76ff1Sjsg 	return true;
21731bb76ff1Sjsg }
21741bb76ff1Sjsg 
smu_v13_0_7_set_df_cstate(struct smu_context * smu,enum pp_df_cstate state)21751bb76ff1Sjsg static int smu_v13_0_7_set_df_cstate(struct smu_context *smu,
21761bb76ff1Sjsg 				     enum pp_df_cstate state)
21771bb76ff1Sjsg {
21781bb76ff1Sjsg 	return smu_cmn_send_smc_msg_with_param(smu,
21791bb76ff1Sjsg 					       SMU_MSG_DFCstateControl,
21801bb76ff1Sjsg 					       state,
21811bb76ff1Sjsg 					       NULL);
21821bb76ff1Sjsg }
21831bb76ff1Sjsg 
21841bb76ff1Sjsg static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
21851bb76ff1Sjsg 	.get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
21861bb76ff1Sjsg 	.set_default_dpm_table = smu_v13_0_7_set_default_dpm_table,
21871bb76ff1Sjsg 	.is_dpm_running = smu_v13_0_7_is_dpm_running,
21881bb76ff1Sjsg 	.dump_pptable = smu_v13_0_7_dump_pptable,
21891bb76ff1Sjsg 	.init_microcode = smu_v13_0_init_microcode,
21901bb76ff1Sjsg 	.load_microcode = smu_v13_0_load_microcode,
21911bb76ff1Sjsg 	.fini_microcode = smu_v13_0_fini_microcode,
21921bb76ff1Sjsg 	.init_smc_tables = smu_v13_0_7_init_smc_tables,
21931bb76ff1Sjsg 	.fini_smc_tables = smu_v13_0_fini_smc_tables,
21941bb76ff1Sjsg 	.init_power = smu_v13_0_init_power,
21951bb76ff1Sjsg 	.fini_power = smu_v13_0_fini_power,
21961bb76ff1Sjsg 	.check_fw_status = smu_v13_0_7_check_fw_status,
21971bb76ff1Sjsg 	.setup_pptable = smu_v13_0_7_setup_pptable,
21981bb76ff1Sjsg 	.check_fw_version = smu_v13_0_check_fw_version,
21991bb76ff1Sjsg 	.write_pptable = smu_cmn_write_pptable,
22001bb76ff1Sjsg 	.set_driver_table_location = smu_v13_0_set_driver_table_location,
22011bb76ff1Sjsg 	.system_features_control = smu_v13_0_system_features_control,
22021bb76ff1Sjsg 	.set_allowed_mask = smu_v13_0_set_allowed_mask,
22031bb76ff1Sjsg 	.get_enabled_mask = smu_cmn_get_enabled_mask,
22041bb76ff1Sjsg 	.dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
22051bb76ff1Sjsg 	.dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
22061bb76ff1Sjsg 	.init_pptable_microcode = smu_v13_0_init_pptable_microcode,
22071bb76ff1Sjsg 	.populate_umd_state_clk = smu_v13_0_7_populate_umd_state_clk,
2208b6e93a8fSjsg 	.get_dpm_ultimate_freq = smu_v13_0_7_get_dpm_ultimate_freq,
22091bb76ff1Sjsg 	.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
22101bb76ff1Sjsg 	.read_sensor = smu_v13_0_7_read_sensor,
22111bb76ff1Sjsg 	.feature_is_enabled = smu_cmn_feature_is_enabled,
22121bb76ff1Sjsg 	.print_clk_levels = smu_v13_0_7_print_clk_levels,
22131bb76ff1Sjsg 	.force_clk_levels = smu_v13_0_7_force_clk_levels,
22142ebcbf6cSjsg 	.update_pcie_parameters = smu_v13_0_update_pcie_parameters,
22151bb76ff1Sjsg 	.get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range,
22161bb76ff1Sjsg 	.register_irq_handler = smu_v13_0_register_irq_handler,
22171bb76ff1Sjsg 	.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
22181bb76ff1Sjsg 	.disable_thermal_alert = smu_v13_0_disable_thermal_alert,
22191bb76ff1Sjsg 	.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
22201bb76ff1Sjsg 	.get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
22211bb76ff1Sjsg 	.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
2222*f005ef32Sjsg 	.set_default_od_settings = smu_v13_0_7_set_default_od_settings,
2223*f005ef32Sjsg 	.restore_user_od_settings = smu_v13_0_7_restore_user_od_settings,
2224*f005ef32Sjsg 	.od_edit_dpm_table = smu_v13_0_7_od_edit_dpm_table,
22251bb76ff1Sjsg 	.set_performance_level = smu_v13_0_set_performance_level,
22261bb76ff1Sjsg 	.gfx_off_control = smu_v13_0_gfx_off_control,
22271bb76ff1Sjsg 	.get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
22281bb76ff1Sjsg 	.get_fan_speed_rpm = smu_v13_0_7_get_fan_speed_rpm,
22291bb76ff1Sjsg 	.set_fan_speed_pwm = smu_v13_0_set_fan_speed_pwm,
22301bb76ff1Sjsg 	.set_fan_speed_rpm = smu_v13_0_set_fan_speed_rpm,
22311bb76ff1Sjsg 	.get_fan_control_mode = smu_v13_0_get_fan_control_mode,
22321bb76ff1Sjsg 	.set_fan_control_mode = smu_v13_0_set_fan_control_mode,
22331bb76ff1Sjsg 	.enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
22341bb76ff1Sjsg 	.get_power_limit = smu_v13_0_7_get_power_limit,
22351bb76ff1Sjsg 	.set_power_limit = smu_v13_0_set_power_limit,
2236abbb18a8Sjsg 	.set_power_source = smu_v13_0_set_power_source,
22371bb76ff1Sjsg 	.get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
22381bb76ff1Sjsg 	.set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
22391bb76ff1Sjsg 	.set_tool_table_location = smu_v13_0_set_tool_table_location,
22401bb76ff1Sjsg 	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
22411bb76ff1Sjsg 	.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
22421bb76ff1Sjsg 	.baco_is_support = smu_v13_0_baco_is_support,
22431bb76ff1Sjsg 	.baco_get_state = smu_v13_0_baco_get_state,
22441bb76ff1Sjsg 	.baco_set_state = smu_v13_0_baco_set_state,
22451bb76ff1Sjsg 	.baco_enter = smu_v13_0_7_baco_enter,
22461bb76ff1Sjsg 	.baco_exit = smu_v13_0_7_baco_exit,
22471bb76ff1Sjsg 	.mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported,
22481bb76ff1Sjsg 	.mode1_reset = smu_v13_0_mode1_reset,
22491bb76ff1Sjsg 	.set_mp1_state = smu_v13_0_7_set_mp1_state,
22501bb76ff1Sjsg 	.set_df_cstate = smu_v13_0_7_set_df_cstate,
225189fd5816Sjsg 	.gpo_control = smu_v13_0_gpo_control,
22521bb76ff1Sjsg };
22531bb76ff1Sjsg 
smu_v13_0_7_set_ppt_funcs(struct smu_context * smu)22541bb76ff1Sjsg void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
22551bb76ff1Sjsg {
22561bb76ff1Sjsg 	smu->ppt_funcs = &smu_v13_0_7_ppt_funcs;
22571bb76ff1Sjsg 	smu->message_map = smu_v13_0_7_message_map;
22581bb76ff1Sjsg 	smu->clock_map = smu_v13_0_7_clk_map;
22591bb76ff1Sjsg 	smu->feature_map = smu_v13_0_7_feature_mask_map;
22601bb76ff1Sjsg 	smu->table_map = smu_v13_0_7_table_map;
22611bb76ff1Sjsg 	smu->pwr_src_map = smu_v13_0_7_pwr_src_map;
22621bb76ff1Sjsg 	smu->workload_map = smu_v13_0_7_workload_map;
2263*f005ef32Sjsg 	smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
22641bb76ff1Sjsg 	smu_v13_0_set_smu_mailbox_registers(smu);
22651bb76ff1Sjsg }
2266