Thanks Ray share the topic background and look forward more simplified model of powerplay. Thanks, Prike > -----Original Message----- > From: Huang, Ray <Ray.Huang@xxxxxxx> > Sent: Tuesday, July 02, 2019 3:07 AM > To: Liang, Prike <Prike.Liang@xxxxxxx>; amd-gfx@xxxxxxxxxxxxxxxxxxxxx > Cc: Feng, Kenneth <Kenneth.Feng@xxxxxxx>; Quan, Evan > <Evan.Quan@xxxxxxx>; Wang, Kevin(Yang) <Kevin1.Wang@xxxxxxx>; > Zhang, Hawking <Hawking.Zhang@xxxxxxx>; Deucher, Alexander > <Alexander.Deucher@xxxxxxx> > Subject: RE: [PATCH] drm/amd/powerplay:Move powerplay table implement > to pptable centralized management > > Hi Prike, > > Thanks for the update. The original plan for swSMU based driver should be > out of powerplay. So far, we don't need separate them under powerplay. > Because it will bring additional effort while we move them out. I understand > your intention, maybe we can discuss it after I come back. > > Thanks, > Ray > > -----Original Message----- > From: Liang, Prike <Prike.Liang@xxxxxxx> > Sent: Monday, July 1, 2019 4:33 AM > To: Liang, Prike <Prike.Liang@xxxxxxx>; amd-gfx@xxxxxxxxxxxxxxxxxxxxx > Cc: Feng, Kenneth <Kenneth.Feng@xxxxxxx>; Quan, Evan > <Evan.Quan@xxxxxxx>; Huang, Ray <Ray.Huang@xxxxxxx> > Subject: RE: [PATCH] drm/amd/powerplay:Move powerplay table implement > to pptable centralized management > > This is mostly a straightly move to comm place and with built configuration > changes. Any point about the idea ? > > Thanks, > Prike > > -----Original Message----- > > From: amd-gfx <amd-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx> On Behalf Of > > Prike Liang > > Sent: Thursday, June 27, 2019 6:36 PM > > To: amd-gfx@xxxxxxxxxxxxxxxxxxxxx > > Cc: Feng, Kenneth <Kenneth.Feng@xxxxxxx>; Liang, Prike > > <Prike.Liang@xxxxxxx>; Quan, Evan <Evan.Quan@xxxxxxx>; Huang, Ray > > <Ray.Huang@xxxxxxx> > > Subject: [PATCH] drm/amd/powerplay:Move powerplay table implement > to > > pptable centralized management > > > > centralized manage powerplay table related functions to avoid > > various products mess up root placement of powerplay. > > > > Change-Id: I3d23021ccb5ef5fd7ffe896a64581876d3409d5b > > Signed-off-by: Prike Liang <Prike.Liang@xxxxxxx> > > --- > > drivers/gpu/drm/amd/powerplay/Makefile | 7 +- > > drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 1514 --------- > > drivers/gpu/drm/amd/powerplay/navi10_ppt.h | 28 - > > drivers/gpu/drm/amd/powerplay/pptable/Makefile | 30 + > > drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.c | 1514 > +++++++++ > > drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.h | 28 + > > drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.c | 3302 > > ++++++++++++++++++++ > > drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.h | 179 ++ > > drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 3302 ------------------ > -- > > drivers/gpu/drm/amd/powerplay/vega20_ppt.h | 179 -- > > 10 files changed, 5057 insertions(+), 5026 deletions(-) > > delete mode 100644 drivers/gpu/drm/amd/powerplay/navi10_ppt.c > > delete mode 100644 drivers/gpu/drm/amd/powerplay/navi10_ppt.h > > create mode 100644 drivers/gpu/drm/amd/powerplay/pptable/Makefile > > create mode 100644 > > drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.c > > create mode 100644 > > drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.h > > create mode 100644 > > drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.c > > create mode 100644 > > drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.h > > delete mode 100644 drivers/gpu/drm/amd/powerplay/vega20_ppt.c > > delete mode 100644 drivers/gpu/drm/amd/powerplay/vega20_ppt.h > > > > diff --git a/drivers/gpu/drm/amd/powerplay/Makefile > > b/drivers/gpu/drm/amd/powerplay/Makefile > > index 727c5cf..c273c25 100644 > > --- a/drivers/gpu/drm/amd/powerplay/Makefile > > +++ b/drivers/gpu/drm/amd/powerplay/Makefile > > @@ -25,17 +25,18 @@ subdir-ccflags-y += \ > > -I$(FULL_AMD_PATH)/include/asic_reg \ > > -I$(FULL_AMD_PATH)/include \ > > -I$(FULL_AMD_PATH)/powerplay/smumgr\ > > - -I$(FULL_AMD_PATH)/powerplay/hwmgr > > + -I$(FULL_AMD_PATH)/powerplay/hwmgr \ > > + -I$(FULL_AMD_PATH)/powerplay/pptable > > > > AMD_PP_PATH = ../powerplay > > > > -PP_LIBS = smumgr hwmgr > > +PP_LIBS = smumgr hwmgr pptable > > > > AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix > > $(FULL_AMD_PATH)/powerplay/,$(PP_LIBS))) > > > > include $(AMD_POWERPLAY) > > > > -POWER_MGR = amd_powerplay.o amdgpu_smu.o smu_v11_0.o > > vega20_ppt.o navi10_ppt.o > > +POWER_MGR = amd_powerplay.o amdgpu_smu.o smu_v11_0.o > > > > AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR)) > > > > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > > deleted file mode 100644 > > index 99566de..0000000 > > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c > > +++ /dev/null > > @@ -1,1514 +0,0 @@ > > -/* > > - * Copyright 2019 Advanced Micro Devices, Inc. > > - * > > - * Permission is hereby granted, free of charge, to any person obtaining a > > - * copy of this software and associated documentation files (the > "Software"), > > - * to deal in the Software without restriction, including without limitation > > - * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > - * and/or sell copies of the Software, and to permit persons to whom the > > - * Software is furnished to do so, subject to the following conditions: > > - * > > - * The above copyright notice and this permission notice shall be included > in > > - * all copies or substantial portions of the Software. > > - * > > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO > > EVENT SHALL > > - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > - * OTHER DEALINGS IN THE SOFTWARE. > > - * > > - */ > > - > > -#include "pp_debug.h" > > -#include <linux/firmware.h> > > -#include "amdgpu.h" > > -#include "amdgpu_smu.h" > > -#include "atomfirmware.h" > > -#include "amdgpu_atomfirmware.h" > > -#include "smu_v11_0.h" > > -#include "smu11_driver_if_navi10.h" > > -#include "soc15_common.h" > > -#include "atom.h" > > -#include "navi10_ppt.h" > > -#include "smu_v11_0_pptable.h" > > -#include "smu_v11_0_ppsmc.h" > > - > > -#include "asic_reg/mp/mp_11_0_sh_mask.h" > > - > > -#define FEATURE_MASK(feature) (1ULL << feature) > > -#define SMC_DPM_FEATURE ( \ > > - FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ > > - FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) > > - > > -#define MSG_MAP(msg, index) \ > > - [SMU_MSG_##msg] = index > > - > > -static int navi10_message_map[SMU_MSG_MAX_COUNT] = { > > - MSG_MAP(TestMessage, > > PPSMC_MSG_TestMessage), > > - MSG_MAP(GetSmuVersion, > > PPSMC_MSG_GetSmuVersion), > > - MSG_MAP(GetDriverIfVersion, > > PPSMC_MSG_GetDriverIfVersion), > > - MSG_MAP(SetAllowedFeaturesMaskLow, > > PPSMC_MSG_SetAllowedFeaturesMaskLow), > > - MSG_MAP(SetAllowedFeaturesMaskHigh, > > PPSMC_MSG_SetAllowedFeaturesMaskHigh), > > - MSG_MAP(EnableAllSmuFeatures, > > PPSMC_MSG_EnableAllSmuFeatures), > > - MSG_MAP(DisableAllSmuFeatures, > > PPSMC_MSG_DisableAllSmuFeatures), > > - MSG_MAP(EnableSmuFeaturesLow, > > PPSMC_MSG_EnableSmuFeaturesLow), > > - MSG_MAP(EnableSmuFeaturesHigh, > > PPSMC_MSG_EnableSmuFeaturesHigh), > > - MSG_MAP(DisableSmuFeaturesLow, > > PPSMC_MSG_DisableSmuFeaturesLow), > > - MSG_MAP(DisableSmuFeaturesHigh, > > PPSMC_MSG_DisableSmuFeaturesHigh), > > - MSG_MAP(GetEnabledSmuFeaturesLow, > > PPSMC_MSG_GetEnabledSmuFeaturesLow), > > - MSG_MAP(GetEnabledSmuFeaturesHigh, > > PPSMC_MSG_GetEnabledSmuFeaturesHigh), > > - MSG_MAP(SetWorkloadMask, > > PPSMC_MSG_SetWorkloadMask), > > - MSG_MAP(SetPptLimit, > > PPSMC_MSG_SetPptLimit), > > - MSG_MAP(SetDriverDramAddrHigh, > > PPSMC_MSG_SetDriverDramAddrHigh), > > - MSG_MAP(SetDriverDramAddrLow, > > PPSMC_MSG_SetDriverDramAddrLow), > > - MSG_MAP(SetToolsDramAddrHigh, > > PPSMC_MSG_SetToolsDramAddrHigh), > > - MSG_MAP(SetToolsDramAddrLow, > > PPSMC_MSG_SetToolsDramAddrLow), > > - MSG_MAP(TransferTableSmu2Dram, > > PPSMC_MSG_TransferTableSmu2Dram), > > - MSG_MAP(TransferTableDram2Smu, > > PPSMC_MSG_TransferTableDram2Smu), > > - MSG_MAP(UseDefaultPPTable, > > PPSMC_MSG_UseDefaultPPTable), > > - MSG_MAP(UseBackupPPTable, > > PPSMC_MSG_UseBackupPPTable), > > - MSG_MAP(RunBtc, > > PPSMC_MSG_RunBtc), > > - MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco), > > - MSG_MAP(SetSoftMinByFreq, > > PPSMC_MSG_SetSoftMinByFreq), > > - MSG_MAP(SetSoftMaxByFreq, > > PPSMC_MSG_SetSoftMaxByFreq), > > - MSG_MAP(SetHardMinByFreq, > > PPSMC_MSG_SetHardMinByFreq), > > - MSG_MAP(SetHardMaxByFreq, > > PPSMC_MSG_SetHardMaxByFreq), > > - MSG_MAP(GetMinDpmFreq, > > PPSMC_MSG_GetMinDpmFreq), > > - MSG_MAP(GetMaxDpmFreq, > > PPSMC_MSG_GetMaxDpmFreq), > > - MSG_MAP(GetDpmFreqByIndex, > > PPSMC_MSG_GetDpmFreqByIndex), > > - MSG_MAP(SetMemoryChannelConfig, > > PPSMC_MSG_SetMemoryChannelConfig), > > - MSG_MAP(SetGeminiMode, > > PPSMC_MSG_SetGeminiMode), > > - MSG_MAP(SetGeminiApertureHigh, > > PPSMC_MSG_SetGeminiApertureHigh), > > - MSG_MAP(SetGeminiApertureLow, > > PPSMC_MSG_SetGeminiApertureLow), > > - MSG_MAP(OverridePcieParameters, > > PPSMC_MSG_OverridePcieParameters), > > - MSG_MAP(SetMinDeepSleepDcefclk, > > PPSMC_MSG_SetMinDeepSleepDcefclk), > > - MSG_MAP(ReenableAcDcInterrupt, > > PPSMC_MSG_ReenableAcDcInterrupt), > > - MSG_MAP(NotifyPowerSource, > > PPSMC_MSG_NotifyPowerSource), > > - MSG_MAP(SetUclkFastSwitch, > > PPSMC_MSG_SetUclkFastSwitch), > > - MSG_MAP(SetVideoFps, > > PPSMC_MSG_SetVideoFps), > > - MSG_MAP(PrepareMp1ForUnload, > > PPSMC_MSG_PrepareMp1ForUnload), > > - MSG_MAP(DramLogSetDramAddrHigh, > > PPSMC_MSG_DramLogSetDramAddrHigh), > > - MSG_MAP(DramLogSetDramAddrLow, > > PPSMC_MSG_DramLogSetDramAddrLow), > > - MSG_MAP(DramLogSetDramSize, > > PPSMC_MSG_DramLogSetDramSize), > > - MSG_MAP(ConfigureGfxDidt, > > PPSMC_MSG_ConfigureGfxDidt), > > - MSG_MAP(NumOfDisplays, > > PPSMC_MSG_NumOfDisplays), > > - MSG_MAP(SetSystemVirtualDramAddrHigh, > > PPSMC_MSG_SetSystemVirtualDramAddrHigh), > > - MSG_MAP(SetSystemVirtualDramAddrLow, > > PPSMC_MSG_SetSystemVirtualDramAddrLow), > > - MSG_MAP(AllowGfxOff, > > PPSMC_MSG_AllowGfxOff), > > - MSG_MAP(DisallowGfxOff, > > PPSMC_MSG_DisallowGfxOff), > > - MSG_MAP(GetPptLimit, > > PPSMC_MSG_GetPptLimit), > > - MSG_MAP(GetDcModeMaxDpmFreq, > > PPSMC_MSG_GetDcModeMaxDpmFreq), > > - MSG_MAP(GetDebugData, > > PPSMC_MSG_GetDebugData), > > - MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco), > > - MSG_MAP(PrepareMp1ForReset, > > PPSMC_MSG_PrepareMp1ForReset), > > - MSG_MAP(PrepareMp1ForShutdown, > > PPSMC_MSG_PrepareMp1ForShutdown), > > - MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn), > > - MSG_MAP(PowerDownVcn, > > PPSMC_MSG_PowerDownVcn), > > - MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg), > > - MSG_MAP(PowerDownJpeg, > > PPSMC_MSG_PowerDownJpeg), > > - MSG_MAP(BacoAudioD3PME, > > PPSMC_MSG_BacoAudioD3PME), > > -}; > > - > > -static int navi10_clk_map[SMU_CLK_COUNT] = { > > - CLK_MAP(GFXCLK, PPCLK_GFXCLK), > > - CLK_MAP(SCLK, PPCLK_GFXCLK), > > - CLK_MAP(SOCCLK, PPCLK_SOCCLK), > > - CLK_MAP(FCLK, PPCLK_SOCCLK), > > - CLK_MAP(UCLK, PPCLK_UCLK), > > - CLK_MAP(MCLK, PPCLK_UCLK), > > - CLK_MAP(DCLK, PPCLK_DCLK), > > - CLK_MAP(VCLK, PPCLK_VCLK), > > - CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), > > - CLK_MAP(DISPCLK, PPCLK_DISPCLK), > > - CLK_MAP(PIXCLK, PPCLK_PIXCLK), > > - CLK_MAP(PHYCLK, PPCLK_PHYCLK), > > -}; > > - > > -static int navi10_feature_mask_map[SMU_FEATURE_COUNT] = { > > - FEA_MAP(DPM_PREFETCHER), > > - FEA_MAP(DPM_GFXCLK), > > - FEA_MAP(DPM_GFX_PACE), > > - FEA_MAP(DPM_UCLK), > > - FEA_MAP(DPM_SOCCLK), > > - FEA_MAP(DPM_MP0CLK), > > - FEA_MAP(DPM_LINK), > > - FEA_MAP(DPM_DCEFCLK), > > - FEA_MAP(MEM_VDDCI_SCALING), > > - FEA_MAP(MEM_MVDD_SCALING), > > - FEA_MAP(DS_GFXCLK), > > - FEA_MAP(DS_SOCCLK), > > - FEA_MAP(DS_LCLK), > > - FEA_MAP(DS_DCEFCLK), > > - FEA_MAP(DS_UCLK), > > - FEA_MAP(GFX_ULV), > > - FEA_MAP(FW_DSTATE), > > - FEA_MAP(GFXOFF), > > - FEA_MAP(BACO), > > - FEA_MAP(VCN_PG), > > - FEA_MAP(JPEG_PG), > > - FEA_MAP(USB_PG), > > - FEA_MAP(RSMU_SMN_CG), > > - FEA_MAP(PPT), > > - FEA_MAP(TDC), > > - FEA_MAP(GFX_EDC), > > - FEA_MAP(APCC_PLUS), > > - FEA_MAP(GTHR), > > - FEA_MAP(ACDC), > > - FEA_MAP(VR0HOT), > > - FEA_MAP(VR1HOT), > > - FEA_MAP(FW_CTF), > > - FEA_MAP(FAN_CONTROL), > > - FEA_MAP(THERMAL), > > - FEA_MAP(GFX_DCS), > > - FEA_MAP(RM), > > - FEA_MAP(LED_DISPLAY), > > - FEA_MAP(GFX_SS), > > - FEA_MAP(OUT_OF_BAND_MONITOR), > > - FEA_MAP(TEMP_DEPENDENT_VMIN), > > - FEA_MAP(MMHUB_PG), > > - FEA_MAP(ATHUB_PG), > > -}; > > - > > -static int navi10_table_map[SMU_TABLE_COUNT] = { > > - TAB_MAP(PPTABLE), > > - TAB_MAP(WATERMARKS), > > - TAB_MAP(AVFS), > > - TAB_MAP(AVFS_PSM_DEBUG), > > - TAB_MAP(AVFS_FUSE_OVERRIDE), > > - TAB_MAP(PMSTATUSLOG), > > - TAB_MAP(SMU_METRICS), > > - TAB_MAP(DRIVER_SMU_CONFIG), > > - TAB_MAP(ACTIVITY_MONITOR_COEFF), > > - TAB_MAP(OVERDRIVE), > > - TAB_MAP(I2C_COMMANDS), > > - TAB_MAP(PACE), > > -}; > > - > > -static int navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { > > - PWR_MAP(AC), > > - PWR_MAP(DC), > > -}; > > - > > -static int navi10_workload_map[] = { > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, > > WORKLOAD_PPLIB_DEFAULT_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, > > WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, > > WORKLOAD_PPLIB_POWER_SAVING_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, > > WORKLOAD_PPLIB_VIDEO_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, > > WORKLOAD_PPLIB_VR_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > -}; > > - > > -static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index > SMU_MSG_MAX_COUNT) > > - return -EINVAL; > > - > > - val = navi10_message_map[index]; > > - if (val > PPSMC_Message_Count) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_CLK_COUNT) > > - return -EINVAL; > > - > > - val = navi10_clk_map[index]; > > - if (val >= PPCLK_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int navi10_get_smu_feature_index(struct smu_context *smc, > > uint32_t index) > > -{ > > - int val; > > - if (index >= SMU_FEATURE_COUNT) > > - return -EINVAL; > > - > > - val = navi10_feature_mask_map[index]; > > - if (val > 64) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_TABLE_COUNT) > > - return -EINVAL; > > - > > - val = navi10_table_map[index]; > > - if (val >= TABLE_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_POWER_SOURCE_COUNT) > > - return -EINVAL; > > - > > - val = navi10_pwr_src_map[index]; > > - if (val >= POWER_SOURCE_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > - > > -static int navi10_get_workload_type(struct smu_context *smu, enum > > PP_SMC_POWER_PROFILE profile) > > -{ > > - int val; > > - if (profile > PP_SMC_POWER_PROFILE_CUSTOM) > > - return -EINVAL; > > - > > - val = navi10_workload_map[profile]; > > - > > - return val; > > -} > > - > > -static bool is_asic_secure(struct smu_context *smu) > > -{ > > - struct amdgpu_device *adev = smu->adev; > > - bool is_secure = true; > > - uint32_t mp0_fw_intf; > > - > > - mp0_fw_intf = RREG32_PCIE(MP0_Public | > > - (smnMP0_FW_INTF & 0xffffffff)); > > - > > - if (!(mp0_fw_intf & (1 << 19))) > > - is_secure = false; > > - > > - return is_secure; > > -} > > - > > -static int > > -navi10_get_allowed_feature_mask(struct smu_context *smu, > > - uint32_t *feature_mask, uint32_t num) > > -{ > > - struct amdgpu_device *adev = smu->adev; > > - > > - if (num > 2) > > - return -EINVAL; > > - > > - memset(feature_mask, 0, sizeof(uint32_t) * num); > > - > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) > > - | FEATURE_MASK(FEATURE_DPM_LINK_BIT) > > - | FEATURE_MASK(FEATURE_GFX_ULV_BIT) > > - | > > FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) > > - | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) > > - | FEATURE_MASK(FEATURE_PPT_BIT) > > - | FEATURE_MASK(FEATURE_TDC_BIT) > > - | FEATURE_MASK(FEATURE_GFX_EDC_BIT) > > - | FEATURE_MASK(FEATURE_VR0HOT_BIT) > > - | > > FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) > > - | FEATURE_MASK(FEATURE_THERMAL_BIT) > > - | > > FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) > > - | FEATURE_MASK(FEATURE_DS_GFXCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_FW_DSTATE_BIT) > > - | FEATURE_MASK(FEATURE_BACO_BIT) > > - | FEATURE_MASK(FEATURE_ACDC_BIT); > > - > > - if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) > > - | > > FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); > > - > > - if (adev->pm.pp_feature & PP_GFXOFF_MASK) { > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_GFX_SS_BIT) > > - | FEATURE_MASK(FEATURE_GFXOFF_BIT); > > - /* TODO: remove it once fw fix the bug */ > > - *(uint64_t *)feature_mask &= > > ~FEATURE_MASK(FEATURE_FW_DSTATE_BIT); > > - } > > - > > - if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_MMHUB_PG_BIT); > > - > > - if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_ATHUB_PG_BIT); > > - > > - if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN) > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_VCN_PG_BIT); > > - > > - /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ > > - if (is_asic_secure(smu)) { > > - /* only for navi10 A0 */ > > - if ((adev->asic_type == CHIP_NAVI10) && > > - (adev->rev_id == 0)) { > > - *(uint64_t *)feature_mask &= > > - > > ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) > > - | > > FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT)); > > - *(uint64_t *)feature_mask &= > > - > > ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); > > - } > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_check_powerplay_table(struct smu_context *smu) > > -{ > > - return 0; > > -} > > - > > -static int navi10_append_powerplay_table(struct smu_context *smu) > > -{ > > - struct amdgpu_device *adev = smu->adev; > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *smc_pptable = table_context->driver_pptable; > > - struct atom_smc_dpm_info_v4_5 *smc_dpm_table; > > - int index, ret; > > - > > - index = > > get_index_into_master_table(atom_master_list_of_data_tables_v2_1, > > - smc_dpm_info); > > - > > - ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, > > - (uint8_t **)&smc_dpm_table); > > - if (ret) > > - return ret; > > - > > - memcpy(smc_pptable->I2cControllers, smc_dpm_table- > > >I2cControllers, > > - sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS); > > - > > - /* SVI2 Board Parameters */ > > - smc_pptable->MaxVoltageStepGfx = smc_dpm_table- > > >MaxVoltageStepGfx; > > - smc_pptable->MaxVoltageStepSoc = smc_dpm_table- > > >MaxVoltageStepSoc; > > - smc_pptable->VddGfxVrMapping = smc_dpm_table- > > >VddGfxVrMapping; > > - smc_pptable->VddSocVrMapping = smc_dpm_table- > > >VddSocVrMapping; > > - smc_pptable->VddMem0VrMapping = smc_dpm_table- > > >VddMem0VrMapping; > > - smc_pptable->VddMem1VrMapping = smc_dpm_table- > > >VddMem1VrMapping; > > - smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table- > > >GfxUlvPhaseSheddingMask; > > - smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table- > > >SocUlvPhaseSheddingMask; > > - smc_pptable->ExternalSensorPresent = smc_dpm_table- > > >ExternalSensorPresent; > > - smc_pptable->Padding8_V = smc_dpm_table->Padding8_V; > > - > > - /* Telemetry Settings */ > > - smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent; > > - smc_pptable->GfxOffset = smc_dpm_table->GfxOffset; > > - smc_pptable->Padding_TelemetryGfx = smc_dpm_table- > > >Padding_TelemetryGfx; > > - smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent; > > - smc_pptable->SocOffset = smc_dpm_table->SocOffset; > > - smc_pptable->Padding_TelemetrySoc = smc_dpm_table- > > >Padding_TelemetrySoc; > > - smc_pptable->Mem0MaxCurrent = smc_dpm_table- > > >Mem0MaxCurrent; > > - smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset; > > - smc_pptable->Padding_TelemetryMem0 = smc_dpm_table- > > >Padding_TelemetryMem0; > > - smc_pptable->Mem1MaxCurrent = smc_dpm_table- > > >Mem1MaxCurrent; > > - smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset; > > - smc_pptable->Padding_TelemetryMem1 = smc_dpm_table- > > >Padding_TelemetryMem1; > > - > > - /* GPIO Settings */ > > - smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio; > > - smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity; > > - smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio; > > - smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity; > > - smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio; > > - smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity; > > - smc_pptable->GthrGpio = smc_dpm_table->GthrGpio; > > - smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity; > > - > > - /* LED Display Settings */ > > - smc_pptable->LedPin0 = smc_dpm_table->LedPin0; > > - smc_pptable->LedPin1 = smc_dpm_table->LedPin1; > > - smc_pptable->LedPin2 = smc_dpm_table->LedPin2; > > - smc_pptable->padding8_4 = smc_dpm_table->padding8_4; > > - > > - /* GFXCLK PLL Spread Spectrum */ > > - smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table- > > >PllGfxclkSpreadEnabled; > > - smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table- > > >PllGfxclkSpreadPercent; > > - smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table- > > >PllGfxclkSpreadFreq; > > - > > - /* GFXCLK DFLL Spread Spectrum */ > > - smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table- > > >DfllGfxclkSpreadEnabled; > > - smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table- > > >DfllGfxclkSpreadPercent; > > - smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table- > > >DfllGfxclkSpreadFreq; > > - > > - /* UCLK Spread Spectrum */ > > - smc_pptable->UclkSpreadEnabled = smc_dpm_table- > > >UclkSpreadEnabled; > > - smc_pptable->UclkSpreadPercent = smc_dpm_table- > > >UclkSpreadPercent; > > - smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq; > > - > > - /* SOCCLK Spread Spectrum */ > > - smc_pptable->SoclkSpreadEnabled = smc_dpm_table- > > >SoclkSpreadEnabled; > > - smc_pptable->SocclkSpreadPercent = smc_dpm_table- > > >SocclkSpreadPercent; > > - smc_pptable->SocclkSpreadFreq = smc_dpm_table- > > >SocclkSpreadFreq; > > - > > - /* Total board power */ > > - smc_pptable->TotalBoardPower = smc_dpm_table- > > >TotalBoardPower; > > - smc_pptable->BoardPadding = smc_dpm_table->BoardPadding; > > - > > - /* Mvdd Svi2 Div Ratio Setting */ > > - smc_pptable->MvddRatio = smc_dpm_table->MvddRatio; > > - > > - if (adev->pm.pp_feature & PP_GFXOFF_MASK) { > > - *(uint64_t *)smc_pptable->FeaturesToRun |= > > FEATURE_MASK(FEATURE_GFX_SS_BIT) > > - | > > FEATURE_MASK(FEATURE_GFXOFF_BIT); > > - > > - /* TODO: remove it once SMU fw fix it */ > > - smc_pptable->DebugOverrides |= > > DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN; > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_store_powerplay_table(struct smu_context *smu) > > -{ > > - struct smu_11_0_powerplay_table *powerplay_table = NULL; > > - struct smu_table_context *table_context = &smu->smu_table; > > - > > - if (!table_context->power_play_table) > > - return -EINVAL; > > - > > - powerplay_table = table_context->power_play_table; > > - > > - memcpy(table_context->driver_pptable, &powerplay_table- > > >smc_pptable, > > - sizeof(PPTable_t)); > > - > > - table_context->thermal_controller_type = powerplay_table- > > >thermal_controller_type; > > - > > - return 0; > > -} > > - > > -static int navi10_tables_init(struct smu_context *smu, struct smu_table > > *tables) > > -{ > > - SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, > > sizeof(Watermarks_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, > > sizeof(SmuMetrics_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, > > sizeof(OverDriveTable_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, > > SMU11_TOOL_SIZE, > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, > > - sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, > > - AMDGPU_GEM_DOMAIN_VRAM); > > - > > - return 0; > > -} > > - > > -static int navi10_allocate_dpm_context(struct smu_context *smu) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - > > - if (smu_dpm->dpm_context) > > - return -EINVAL; > > - > > - smu_dpm->dpm_context = kzalloc(sizeof(struct > > smu_11_0_dpm_context), > > - GFP_KERNEL); > > - if (!smu_dpm->dpm_context) > > - return -ENOMEM; > > - > > - smu_dpm->dpm_context_size = sizeof(struct > > smu_11_0_dpm_context); > > - > > - return 0; > > -} > > - > > -static int navi10_set_default_dpm_table(struct smu_context *smu) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct smu_table_context *table_context = &smu->smu_table; > > - struct smu_11_0_dpm_context *dpm_context = smu_dpm- > > >dpm_context; > > - PPTable_t *driver_ppt = NULL; > > - > > - driver_ppt = table_context->driver_pptable; > > - > > - dpm_context->dpm_tables.soc_table.min = driver_ppt- > > >FreqTableSocclk[0]; > > - dpm_context->dpm_tables.soc_table.max = driver_ppt- > > >FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.gfx_table.min = driver_ppt- > > >FreqTableGfx[0]; > > - dpm_context->dpm_tables.gfx_table.max = driver_ppt- > > >FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.uclk_table.min = driver_ppt- > > >FreqTableUclk[0]; > > - dpm_context->dpm_tables.uclk_table.max = driver_ppt- > > >FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.vclk_table.min = driver_ppt- > > >FreqTableVclk[0]; > > - dpm_context->dpm_tables.vclk_table.max = driver_ppt- > > >FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.dclk_table.min = driver_ppt- > > >FreqTableDclk[0]; > > - dpm_context->dpm_tables.dclk_table.max = driver_ppt- > > >FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.dcef_table.min = driver_ppt- > > >FreqTableDcefclk[0]; > > - dpm_context->dpm_tables.dcef_table.max = driver_ppt- > > >FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.pixel_table.min = driver_ppt- > > >FreqTablePixclk[0]; > > - dpm_context->dpm_tables.pixel_table.max = driver_ppt- > > >FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.display_table.min = driver_ppt- > > >FreqTableDispclk[0]; > > - dpm_context->dpm_tables.display_table.max = driver_ppt- > > >FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1]; > > - > > - dpm_context->dpm_tables.phy_table.min = driver_ppt- > > >FreqTablePhyclk[0]; > > - dpm_context->dpm_tables.phy_table.max = driver_ppt- > > >FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1]; > > - > > - return 0; > > -} > > - > > -static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool > > enable) > > -{ > > - int ret = 0; > > - struct smu_power_context *smu_power = &smu->smu_power; > > - struct smu_power_gate *power_gate = &smu_power->power_gate; > > - > > - if (enable && power_gate->uvd_gated) { > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_PowerUpVcn, 1); > > - if (ret) > > - return ret; > > - } > > - power_gate->uvd_gated = false; > > - } else { > > - if (!enable && !power_gate->uvd_gated) { > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) { > > - ret = smu_send_smc_msg(smu, > > SMU_MSG_PowerDownVcn); > > - if (ret) > > - return ret; > > - } > > - power_gate->uvd_gated = true; > > - } > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_get_current_clk_freq_by_table(struct smu_context > *smu, > > - enum smu_clk_type clk_type, > > - uint32_t *value) > > -{ > > - static SmuMetrics_t metrics = {0}; > > - int ret = 0, clk_id = 0; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void > > *)&metrics, false); > > - if (ret) > > - return ret; > > - > > - clk_id = smu_clk_get_index(smu, clk_type); > > - if (clk_id < 0) > > - return clk_id; > > - > > - *value = metrics.CurrClock[clk_id]; > > - > > - return ret; > > -} > > - > > -static int navi10_print_clk_levels(struct smu_context *smu, > > - enum smu_clk_type clk_type, char *buf) > > -{ > > - int i, size = 0, ret = 0; > > - uint32_t cur_value = 0, value = 0, count = 0; > > - > > - switch (clk_type) { > > - case SMU_GFXCLK: > > - case SMU_SCLK: > > - case SMU_SOCCLK: > > - case SMU_MCLK: > > - case SMU_UCLK: > > - case SMU_FCLK: > > - case SMU_DCEFCLK: > > - ret = smu_get_current_clk_freq(smu, clk_type, &cur_value); > > - if (ret) > > - return size; > > - /* 10KHz -> MHz */ > > - cur_value = cur_value / 100; > > - > > - size += sprintf(buf, "current clk: %uMhz\n", cur_value); > > - > > - ret = smu_get_dpm_level_count(smu, clk_type, &count); > > - if (ret) > > - return size; > > - > > - for (i = 0; i < count; i++) { > > - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, > > &value); > > - if (ret) > > - return size; > > - > > - size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, > > - cur_value == value ? "*" : ""); > > - } > > - break; > > - default: > > - break; > > - } > > - > > - return size; > > -} > > - > > -static int navi10_force_clk_levels(struct smu_context *smu, > > - enum smu_clk_type clk_type, uint32_t > > mask) > > -{ > > - > > - int ret = 0, size = 0; > > - uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, > > max_freq = 0; > > - > > - soft_min_level = mask ? (ffs(mask) - 1) : 0; > > - soft_max_level = mask ? (fls(mask) - 1) : 0; > > - > > - switch (clk_type) { > > - case SMU_GFXCLK: > > - case SMU_SCLK: > > - case SMU_SOCCLK: > > - case SMU_MCLK: > > - case SMU_UCLK: > > - case SMU_DCEFCLK: > > - case SMU_FCLK: > > - ret = smu_get_dpm_freq_by_index(smu, clk_type, > > soft_min_level, &min_freq); > > - if (ret) > > - return size; > > - > > - ret = smu_get_dpm_freq_by_index(smu, clk_type, > > soft_max_level, &max_freq); > > - if (ret) > > - return size; > > - > > - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, > > max_freq); > > - if (ret) > > - return size; > > - break; > > - default: > > - break; > > - } > > - > > - return size; > > -} > > - > > -static int navi10_populate_umd_state_clk(struct smu_context *smu) > > -{ > > - int ret = 0; > > - uint32_t min_sclk_freq = 0; > > - > > - ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, > > NULL); > > - if (ret) > > - return ret; > > - > > - smu->pstate_sclk = min_sclk_freq * 100; > > - > > - return ret; > > -} > > - > > -static int navi10_get_clock_by_type_with_latency(struct smu_context > > *smu, > > - enum smu_clk_type > > clk_type, > > - struct > > pp_clock_levels_with_latency *clocks) > > -{ > > - int ret = 0, i = 0; > > - uint32_t level_count = 0, freq = 0; > > - > > - switch (clk_type) { > > - case SMU_GFXCLK: > > - case SMU_DCEFCLK: > > - case SMU_SOCCLK: > > - ret = smu_get_dpm_level_count(smu, clk_type, > > &level_count); > > - if (ret) > > - return ret; > > - > > - level_count = min(level_count, > > (uint32_t)MAX_NUM_CLOCKS); > > - clocks->num_levels = level_count; > > - > > - for (i = 0; i < level_count; i++) { > > - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, > > &freq); > > - if (ret) > > - return ret; > > - > > - clocks->data[i].clocks_in_khz = freq * 1000; > > - clocks->data[i].latency_in_us = 0; > > - } > > - break; > > - default: > > - break; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_pre_display_config_changed(struct smu_context *smu) > > -{ > > - int ret = 0; > > - uint32_t max_freq = 0; > > - > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_NumOfDisplays, 0); > > - if (ret) > > - return ret; > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, > > &max_freq); > > - if (ret) > > - return ret; > > - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, > > max_freq); > > - if (ret) > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_display_config_changed(struct smu_context *smu) > > -{ > > - int ret = 0; > > - > > - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { > > - ret = smu_write_watermarks_table(smu); > > - if (ret) > > - return ret; > > - > > - smu->watermarks_bitmap |= WATERMARKS_LOADED; > > - } > > - > > - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > - smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > - smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_NumOfDisplays, > > - smu->display_config- > > >num_display); > > - if (ret) > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_force_dpm_limit_value(struct smu_context *smu, bool > > highest) > > -{ > > - int ret = 0, i = 0; > > - uint32_t min_freq, max_freq, force_freq; > > - enum smu_clk_type clk_type; > > - > > - enum smu_clk_type clks[] = { > > - SMU_GFXCLK, > > - SMU_MCLK, > > - SMU_SOCCLK, > > - }; > > - > > - for (i = 0; i < ARRAY_SIZE(clks); i++) { > > - clk_type = clks[i]; > > - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, > > &max_freq); > > - if (ret) > > - return ret; > > - > > - force_freq = highest ? max_freq : min_freq; > > - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, > > force_freq); > > - if (ret) > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_unforce_dpm_levels(struct smu_context *smu) { > > - > > - int ret = 0, i = 0; > > - uint32_t min_freq, max_freq; > > - enum smu_clk_type clk_type; > > - > > - struct clk_feature_map { > > - enum smu_clk_type clk_type; > > - uint32_t feature; > > - } clk_feature_map[] = { > > - {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT}, > > - {SMU_MCLK, SMU_FEATURE_DPM_UCLK_BIT}, > > - {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, > > - }; > > - > > - for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { > > - if (!smu_feature_is_enabled(smu, > > clk_feature_map[i].feature)) > > - continue; > > - > > - clk_type = clk_feature_map[i].clk_type; > > - > > - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, > > &max_freq); > > - if (ret) > > - return ret; > > - > > - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, > > max_freq); > > - if (ret) > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_get_gpu_power(struct smu_context *smu, uint32_t > *value) > > -{ > > - int ret = 0; > > - SmuMetrics_t metrics; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void > > *)&metrics, > > - false); > > - if (ret) > > - return ret; > > - > > - *value = metrics.CurrSocketPower << 8; > > - > > - return 0; > > -} > > - > > -static int navi10_get_current_activity_percent(struct smu_context *smu, > > - uint32_t *value) > > -{ > > - int ret = 0; > > - SmuMetrics_t metrics; > > - > > - if (!value) > > - return -EINVAL; > > - > > - msleep(1); > > - > > - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > - (void *)&metrics, false); > > - if (ret) > > - return ret; > > - > > - *value = metrics.AverageGfxActivity; > > - > > - return 0; > > -} > > - > > -static bool navi10_is_dpm_running(struct smu_context *smu) > > -{ > > - int ret = 0; > > - uint32_t feature_mask[2]; > > - unsigned long feature_enabled; > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | > > - ((uint64_t)feature_mask[1] << 32)); > > - return !!(feature_enabled & SMC_DPM_FEATURE); > > -} > > - > > -static int navi10_get_fan_speed(struct smu_context *smu, uint16_t > *value) > > -{ > > - SmuMetrics_t metrics = {0}; > > - int ret = 0; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > - (void *)&metrics, false); > > - if (ret) > > - return ret; > > - > > - *value = metrics.CurrFanSpeed; > > - > > - return ret; > > -} > > - > > -static int navi10_get_fan_speed_percent(struct smu_context *smu, > > - uint32_t *speed) > > -{ > > - int ret = 0; > > - uint32_t percent = 0; > > - uint16_t current_rpm; > > - PPTable_t *pptable = smu->smu_table.driver_pptable; > > - > > - ret = navi10_get_fan_speed(smu, ¤t_rpm); > > - if (ret) > > - return ret; > > - > > - percent = current_rpm * 100 / pptable->FanMaximumRpm; > > - *speed = percent > 100 ? 100 : percent; > > - > > - return ret; > > -} > > - > > -static int navi10_get_power_profile_mode(struct smu_context *smu, > char > > *buf) > > -{ > > - DpmActivityMonitorCoeffInt_t activity_monitor; > > - uint32_t i, size = 0; > > - uint16_t workload_type = 0; > > - static const char *profile_name[] = { > > - "BOOTUP_DEFAULT", > > - "3D_FULL_SCREEN", > > - "POWER_SAVING", > > - "VIDEO", > > - "VR", > > - "COMPUTE", > > - "CUSTOM"}; > > - static const char *title[] = { > > - "PROFILE_INDEX(NAME)", > > - "CLOCK_TYPE(NAME)", > > - "FPS", > > - "MinFreqType", > > - "MinActiveFreqType", > > - "MinActiveFreq", > > - "BoosterFreqType", > > - "BoosterFreq", > > - "PD_Data_limit_c", > > - "PD_Data_error_coeff", > > - "PD_Data_error_rate_coeff"}; > > - int result = 0; > > - > > - if (!buf) > > - return -EINVAL; > > - > > - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", > > - title[0], title[1], title[2], title[3], title[4], title[5], > > - title[6], title[7], title[8], title[9], title[10]); > > - > > - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { > > - /* conv PP_SMC_POWER_PROFILE* to > > WORKLOAD_PPLIB_*_BIT */ > > - workload_type = smu_workload_get_type(smu, i); > > - result = smu_update_table(smu, > > - > > SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16, > > - (void *)(&activity_monitor), false); > > - if (result) { > > - pr_err("[%s] Failed to get activity monitor!", > > __func__); > > - return result; > > - } > > - > > - size += sprintf(buf + size, "%2d %14s%s:\n", > > - i, profile_name[i], (i == smu->power_profile_mode) ? > > "*" : " "); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 0, > > - "GFXCLK", > > - activity_monitor.Gfx_FPS, > > - activity_monitor.Gfx_MinFreqStep, > > - activity_monitor.Gfx_MinActiveFreqType, > > - activity_monitor.Gfx_MinActiveFreq, > > - activity_monitor.Gfx_BoosterFreqType, > > - activity_monitor.Gfx_BoosterFreq, > > - activity_monitor.Gfx_PD_Data_limit_c, > > - activity_monitor.Gfx_PD_Data_error_coeff, > > - activity_monitor.Gfx_PD_Data_error_rate_coeff); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 1, > > - "SOCCLK", > > - activity_monitor.Soc_FPS, > > - activity_monitor.Soc_MinFreqStep, > > - activity_monitor.Soc_MinActiveFreqType, > > - activity_monitor.Soc_MinActiveFreq, > > - activity_monitor.Soc_BoosterFreqType, > > - activity_monitor.Soc_BoosterFreq, > > - activity_monitor.Soc_PD_Data_limit_c, > > - activity_monitor.Soc_PD_Data_error_coeff, > > - activity_monitor.Soc_PD_Data_error_rate_coeff); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 2, > > - "MEMLK", > > - activity_monitor.Mem_FPS, > > - activity_monitor.Mem_MinFreqStep, > > - activity_monitor.Mem_MinActiveFreqType, > > - activity_monitor.Mem_MinActiveFreq, > > - activity_monitor.Mem_BoosterFreqType, > > - activity_monitor.Mem_BoosterFreq, > > - activity_monitor.Mem_PD_Data_limit_c, > > - activity_monitor.Mem_PD_Data_error_coeff, > > - activity_monitor.Mem_PD_Data_error_rate_coeff); > > - } > > - > > - return size; > > -} > > - > > -static int navi10_set_power_profile_mode(struct smu_context *smu, long > > *input, uint32_t size) > > -{ > > - DpmActivityMonitorCoeffInt_t activity_monitor; > > - int workload_type, ret = 0; > > - > > - smu->power_profile_mode = input[size]; > > - > > - if (smu->power_profile_mode > > > PP_SMC_POWER_PROFILE_CUSTOM) { > > - pr_err("Invalid power profile mode %d\n", smu- > > >power_profile_mode); > > - return -EINVAL; > > - } > > - > > - if (smu->power_profile_mode == > > PP_SMC_POWER_PROFILE_CUSTOM) { > > - if (size < 0) > > - return -EINVAL; > > - > > - ret = smu_update_table(smu, > > - SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > - (void *)(&activity_monitor), false); > > - if (ret) { > > - pr_err("[%s] Failed to get activity monitor!", > > __func__); > > - return ret; > > - } > > - > > - switch (input[0]) { > > - case 0: /* Gfxclk */ > > - activity_monitor.Gfx_FPS = input[1]; > > - activity_monitor.Gfx_MinFreqStep = input[2]; > > - activity_monitor.Gfx_MinActiveFreqType = input[3]; > > - activity_monitor.Gfx_MinActiveFreq = input[4]; > > - activity_monitor.Gfx_BoosterFreqType = input[5]; > > - activity_monitor.Gfx_BoosterFreq = input[6]; > > - activity_monitor.Gfx_PD_Data_limit_c = input[7]; > > - activity_monitor.Gfx_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Gfx_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - case 1: /* Socclk */ > > - activity_monitor.Soc_FPS = input[1]; > > - activity_monitor.Soc_MinFreqStep = input[2]; > > - activity_monitor.Soc_MinActiveFreqType = input[3]; > > - activity_monitor.Soc_MinActiveFreq = input[4]; > > - activity_monitor.Soc_BoosterFreqType = input[5]; > > - activity_monitor.Soc_BoosterFreq = input[6]; > > - activity_monitor.Soc_PD_Data_limit_c = input[7]; > > - activity_monitor.Soc_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Soc_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - case 2: /* Memlk */ > > - activity_monitor.Mem_FPS = input[1]; > > - activity_monitor.Mem_MinFreqStep = input[2]; > > - activity_monitor.Mem_MinActiveFreqType = > > input[3]; > > - activity_monitor.Mem_MinActiveFreq = input[4]; > > - activity_monitor.Mem_BoosterFreqType = input[5]; > > - activity_monitor.Mem_BoosterFreq = input[6]; > > - activity_monitor.Mem_PD_Data_limit_c = input[7]; > > - activity_monitor.Mem_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Mem_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - } > > - > > - ret = smu_update_table(smu, > > - SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > - (void *)(&activity_monitor), true); > > - if (ret) { > > - pr_err("[%s] Failed to set activity monitor!", > > __func__); > > - return ret; > > - } > > - } > > - > > - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ > > - workload_type = smu_workload_get_type(smu, smu- > > >power_profile_mode); > > - smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetWorkloadMask, > > - 1 << workload_type); > > - > > - return ret; > > -} > > - > > -static int navi10_get_profiling_clk_mask(struct smu_context *smu, > > - enum amd_dpm_forced_level level, > > - uint32_t *sclk_mask, > > - uint32_t *mclk_mask, > > - uint32_t *soc_mask) > > -{ > > - int ret = 0; > > - uint32_t level_count = 0; > > - > > - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > - if (sclk_mask) > > - *sclk_mask = 0; > > - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > - if (mclk_mask) > > - *mclk_mask = 0; > > - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - if(sclk_mask) { > > - ret = smu_get_dpm_level_count(smu, SMU_SCLK, > > &level_count); > > - if (ret) > > - return ret; > > - *sclk_mask = level_count - 1; > > - } > > - > > - if(mclk_mask) { > > - ret = smu_get_dpm_level_count(smu, SMU_MCLK, > > &level_count); > > - if (ret) > > - return ret; > > - *sclk_mask = level_count - 1; > > - } > > - > > - if(soc_mask) { > > - ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, > > &level_count); > > - if (ret) > > - return ret; > > - *sclk_mask = level_count - 1; > > - } > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_notify_smc_dispaly_config(struct smu_context *smu) > > -{ > > - struct smu_clocks min_clocks = {0}; > > - struct pp_display_clock_request clock_req; > > - int ret = 0; > > - > > - min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; > > - min_clocks.dcef_clock_in_sr = smu->display_config- > > >min_dcef_deep_sleep_set_clk; > > - min_clocks.memory_clock = smu->display_config- > > >min_mem_set_clock; > > - > > - if (smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - clock_req.clock_type = amd_pp_dcef_clock; > > - clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; > > - if (!smu_display_clock_voltage_request(smu, &clock_req)) { > > - if (smu_feature_is_supported(smu, > > SMU_FEATURE_DS_DCEFCLK_BIT)) { > > - ret = smu_send_smc_msg_with_param(smu, > > - > > SMU_MSG_SetMinDeepSleepDcefclk, > > - > > min_clocks.dcef_clock_in_sr/100); > > - if (ret) { > > - pr_err("Attempt to set divider for > > DCEFCLK Failed!"); > > - return ret; > > - } > > - } > > - } else { > > - pr_info("Attempt to set Hard Min for DCEFCLK > > Failed!"); > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - ret = smu_set_hard_freq_range(smu, SMU_UCLK, > > min_clocks.memory_clock/100, 0); > > - if (ret) { > > - pr_err("[%s] Set hard min uclk failed!", __func__); > > - return ret; > > - } > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_set_watermarks_table(struct smu_context *smu, > > - void *watermarks, struct > > - > > dm_pp_wm_sets_with_clock_ranges_soc15 > > - *clock_ranges) > > -{ > > - int i; > > - Watermarks_t *table = watermarks; > > - > > - if (!table || !clock_ranges) > > - return -EINVAL; > > - > > - if (clock_ranges->num_wm_dmif_sets > 4 || > > - clock_ranges->num_wm_mcif_sets > 4) > > - return -EINVAL; > > - > > - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { > > - table->WatermarkRow[1][i].MinClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MaxClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MinUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MaxUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].WmSetting = (uint8_t) > > - clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_set_id; > > - } > > - > > - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { > > - table->WatermarkRow[0][i].MinClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MaxClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MinUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MaxUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].WmSetting = (uint8_t) > > - clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_set_id; > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_read_sensor(struct smu_context *smu, > > - enum amd_pp_sensors sensor, > > - void *data, uint32_t *size) > > -{ > > - int ret = 0; > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *pptable = table_context->driver_pptable; > > - > > - switch (sensor) { > > - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: > > - *(uint32_t *)data = pptable->FanMaximumRpm; > > - *size = 4; > > - break; > > - case AMDGPU_PP_SENSOR_GPU_LOAD: > > - ret = navi10_get_current_activity_percent(smu, (uint32_t > > *)data); > > - *size = 4; > > - break; > > - case AMDGPU_PP_SENSOR_GPU_POWER: > > - ret = navi10_get_gpu_power(smu, (uint32_t *)data); > > - *size = 4; > > - break; > > - default: > > - return -EINVAL; > > - } > > - > > - return ret; > > -} > > - > > -static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t > > *clocks_in_khz, uint32_t *num_states) > > -{ > > - uint32_t num_discrete_levels = 0; > > - uint16_t *dpm_levels = NULL; > > - uint16_t i = 0; > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *driver_ppt = NULL; > > - > > - if (!clocks_in_khz || ! num_states || !table_context->driver_pptable) > > - return -EINVAL; > > - > > - driver_ppt = table_context->driver_pptable; > > - num_discrete_levels = driver_ppt- > > >DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; > > - dpm_levels = driver_ppt->FreqTableUclk; > > - > > - if (num_discrete_levels == 0 || dpm_levels == NULL) > > - return -EINVAL; > > - > > - *num_states = num_discrete_levels; > > - for (i = 0; i < num_discrete_levels; i++) { > > - /* convert to khz */ > > - *clocks_in_khz = (*dpm_levels) * 1000; > > - clocks_in_khz++; > > - dpm_levels++; > > - } > > - > > - return 0; > > -} > > - > > -static int navi10_get_ppfeature_status(struct smu_context *smu, > > - char *buf) > > -{ > > - static const char *ppfeature_name[] = { > > - "DPM_PREFETCHER", > > - "DPM_GFXCLK", > > - "DPM_GFX_PACE", > > - "DPM_UCLK", > > - "DPM_SOCCLK", > > - "DPM_MP0CLK", > > - "DPM_LINK", > > - "DPM_DCEFCLK", > > - "MEM_VDDCI_SCALING", > > - "MEM_MVDD_SCALING", > > - "DS_GFXCLK", > > - "DS_SOCCLK", > > - "DS_LCLK", > > - "DS_DCEFCLK", > > - "DS_UCLK", > > - "GFX_ULV", > > - "FW_DSTATE", > > - "GFXOFF", > > - "BACO", > > - "VCN_PG", > > - "JPEG_PG", > > - "USB_PG", > > - "RSMU_SMN_CG", > > - "PPT", > > - "TDC", > > - "GFX_EDC", > > - "APCC_PLUS", > > - "GTHR", > > - "ACDC", > > - "VR0HOT", > > - "VR1HOT", > > - "FW_CTF", > > - "FAN_CONTROL", > > - "THERMAL", > > - "GFX_DCS", > > - "RM", > > - "LED_DISPLAY", > > - "GFX_SS", > > - "OUT_OF_BAND_MONITOR", > > - "TEMP_DEPENDENT_VMIN", > > - "MMHUB_PG", > > - "ATHUB_PG"}; > > - static const char *output_title[] = { > > - "FEATURES", > > - "BITMASK", > > - "ENABLEMENT"}; > > - uint64_t features_enabled; > > - uint32_t feature_mask[2]; > > - int i; > > - int ret = 0; > > - int size = 0; > > - > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - PP_ASSERT_WITH_CODE(!ret, > > - "[GetPPfeatureStatus] Failed to get enabled smc > > features!", > > - return ret); > > - features_enabled = (uint64_t)feature_mask[0] | > > - (uint64_t)feature_mask[1] << 32; > > - > > - size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", > > features_enabled); > > - size += sprintf(buf + size, "%-19s %-22s %s\n", > > - output_title[0], > > - output_title[1], > > - output_title[2]); > > - for (i = 0; i < (sizeof(ppfeature_name) / sizeof(ppfeature_name[0])); > > i++) { > > - size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", > > - ppfeature_name[i], > > - 1ULL << i, > > - (features_enabled & (1ULL << i)) ? > > "Y" : "N"); > > - } > > - > > - return size; > > -} > > - > > -static int navi10_enable_smc_features(struct smu_context *smu, > > - bool enabled, > > - uint64_t feature_masks) > > -{ > > - struct smu_feature *feature = &smu->smu_feature; > > - uint32_t feature_low, feature_high; > > - uint32_t feature_mask[2]; > > - int ret = 0; > > - > > - feature_low = (uint32_t)(feature_masks & 0xFFFFFFFF); > > - feature_high = (uint32_t)((feature_masks & > > 0xFFFFFFFF00000000ULL) >> 32); > > - > > - if (enabled) { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesLow, > > - feature_low); > > - if (ret) > > - return ret; > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesHigh, > > - feature_high); > > - if (ret) > > - return ret; > > - } else { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesLow, > > - feature_low); > > - if (ret) > > - return ret; > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesHigh, > > - feature_high); > > - if (ret) > > - return ret; > > - } > > - > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - if (ret) > > - return ret; > > - > > - mutex_lock(&feature->mutex); > > - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, > > - feature->feature_num); > > - mutex_unlock(&feature->mutex); > > - > > - return 0; > > -} > > - > > -static int navi10_set_ppfeature_status(struct smu_context *smu, > > - uint64_t new_ppfeature_masks) > > -{ > > - uint64_t features_enabled; > > - uint32_t feature_mask[2]; > > - uint64_t features_to_enable; > > - uint64_t features_to_disable; > > - int ret = 0; > > - > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - PP_ASSERT_WITH_CODE(!ret, > > - "[SetPPfeatureStatus] Failed to get enabled smc > > features!", > > - return ret); > > - features_enabled = (uint64_t)feature_mask[0] | > > - (uint64_t)feature_mask[1] << 32; > > - > > - features_to_disable = > > - features_enabled & ~new_ppfeature_masks; > > - features_to_enable = > > - ~features_enabled & new_ppfeature_masks; > > - > > - pr_debug("features_to_disable 0x%llx\n", features_to_disable); > > - pr_debug("features_to_enable 0x%llx\n", features_to_enable); > > - > > - if (features_to_disable) { > > - ret = navi10_enable_smc_features(smu, false, > > features_to_disable); > > - PP_ASSERT_WITH_CODE(!ret, > > - "[SetPPfeatureStatus] Failed to disable smc > > features!", > > - return ret); > > - } > > - > > - if (features_to_enable) { > > - ret = navi10_enable_smc_features(smu, true, > > features_to_enable); > > - PP_ASSERT_WITH_CODE(!ret, > > - "[SetPPfeatureStatus] Failed to enable smc > > features!", > > - return ret); > > - } > > - > > - return 0; > > -} > > - > > -static const struct pptable_funcs navi10_ppt_funcs = { > > - .tables_init = navi10_tables_init, > > - .alloc_dpm_context = navi10_allocate_dpm_context, > > - .store_powerplay_table = navi10_store_powerplay_table, > > - .check_powerplay_table = navi10_check_powerplay_table, > > - .append_powerplay_table = navi10_append_powerplay_table, > > - .get_smu_msg_index = navi10_get_smu_msg_index, > > - .get_smu_clk_index = navi10_get_smu_clk_index, > > - .get_smu_feature_index = navi10_get_smu_feature_index, > > - .get_smu_table_index = navi10_get_smu_table_index, > > - .get_smu_power_index= navi10_get_pwr_src_index, > > - .get_workload_type = navi10_get_workload_type, > > - .get_allowed_feature_mask = navi10_get_allowed_feature_mask, > > - .set_default_dpm_table = navi10_set_default_dpm_table, > > - .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable, > > - .get_current_clk_freq_by_table = > > navi10_get_current_clk_freq_by_table, > > - .print_clk_levels = navi10_print_clk_levels, > > - .force_clk_levels = navi10_force_clk_levels, > > - .populate_umd_state_clk = navi10_populate_umd_state_clk, > > - .get_clock_by_type_with_latency = > > navi10_get_clock_by_type_with_latency, > > - .pre_display_config_changed = navi10_pre_display_config_changed, > > - .display_config_changed = navi10_display_config_changed, > > - .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config, > > - .force_dpm_limit_value = navi10_force_dpm_limit_value, > > - .unforce_dpm_levels = navi10_unforce_dpm_levels, > > - .is_dpm_running = navi10_is_dpm_running, > > - .get_fan_speed_percent = navi10_get_fan_speed_percent, > > - .get_power_profile_mode = navi10_get_power_profile_mode, > > - .set_power_profile_mode = navi10_set_power_profile_mode, > > - .get_profiling_clk_mask = navi10_get_profiling_clk_mask, > > - .set_watermarks_table = navi10_set_watermarks_table, > > - .read_sensor = navi10_read_sensor, > > - .get_uclk_dpm_states = navi10_get_uclk_dpm_states, > > - .get_ppfeature_status = navi10_get_ppfeature_status, > > - .set_ppfeature_status = navi10_set_ppfeature_status, > > -}; > > - > > -void navi10_set_ppt_funcs(struct smu_context *smu) > > -{ > > - struct smu_table_context *smu_table = &smu->smu_table; > > - > > - smu->ppt_funcs = &navi10_ppt_funcs; > > - smu->smc_if_version = SMU11_DRIVER_IF_VERSION; > > - smu_table->table_count = TABLE_COUNT; > > -} > > diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > > b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > > deleted file mode 100644 > > index 957288e..0000000 > > --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h > > +++ /dev/null > > @@ -1,28 +0,0 @@ > > -/* > > - * Copyright 2019 Advanced Micro Devices, Inc. > > - * > > - * Permission is hereby granted, free of charge, to any person obtaining a > > - * copy of this software and associated documentation files (the > "Software"), > > - * to deal in the Software without restriction, including without limitation > > - * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > - * and/or sell copies of the Software, and to permit persons to whom the > > - * Software is furnished to do so, subject to the following conditions: > > - * > > - * The above copyright notice and this permission notice shall be included > in > > - * all copies or substantial portions of the Software. > > - * > > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO > > EVENT SHALL > > - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > - * OTHER DEALINGS IN THE SOFTWARE. > > - * > > - */ > > -#ifndef __NAVI10_PPT_H__ > > -#define __NAVI10_PPT_H__ > > - > > -extern void navi10_set_ppt_funcs(struct smu_context *smu); > > - > > -#endif > > diff --git a/drivers/gpu/drm/amd/powerplay/pptable/Makefile > > b/drivers/gpu/drm/amd/powerplay/pptable/Makefile > > new file mode 100644 > > index 0000000..03058fa > > --- /dev/null > > +++ b/drivers/gpu/drm/amd/powerplay/pptable/Makefile > > @@ -0,0 +1,30 @@ > > +# > > +# Copyright 2017 Advanced Micro Devices, Inc. > > +# > > +# Permission is hereby granted, free of charge, to any person obtaining a > > +# copy of this software and associated documentation files (the > "Software"), > > +# to deal in the Software without restriction, including without limitation > > +# the rights to use, copy, modify, merge, publish, distribute, sublicense, > > +# and/or sell copies of the Software, and to permit persons to whom the > > +# Software is furnished to do so, subject to the following conditions: > > +# > > +# The above copyright notice and this permission notice shall be included > in > > +# all copies or substantial portions of the Software. > > +# > > +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO > > EVENT SHALL > > +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > +# OTHER DEALINGS IN THE SOFTWARE. > > +# > > +# > > +# Makefile for the 'pp table ' sub-component of powerplay. > > +# It provides the pp table function services for the driver. > > + > > +PPT_MGR = vega20_ppt.o navi10_ppt.o > > + > > +AMD_PP_PPTMGR = $(addprefix > $(AMD_PP_PATH)/pptable/,$(PPT_MGR)) > > + > > +AMD_POWERPLAY_FILES += $(AMD_PP_PPTMGR) > > diff --git a/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.c > > b/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.c > > new file mode 100644 > > index 0000000..99566de > > --- /dev/null > > +++ b/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.c > > @@ -0,0 +1,1514 @@ > > +/* > > + * Copyright 2019 Advanced Micro Devices, Inc. > > + * > > + * Permission is hereby granted, free of charge, to any person obtaining a > > + * copy of this software and associated documentation files (the > > "Software"), > > + * to deal in the Software without restriction, including without limitation > > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > + * and/or sell copies of the Software, and to permit persons to whom the > > + * Software is furnished to do so, subject to the following conditions: > > + * > > + * The above copyright notice and this permission notice shall be included > in > > + * all copies or substantial portions of the Software. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > NO > > EVENT SHALL > > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > + * OTHER DEALINGS IN THE SOFTWARE. > > + * > > + */ > > + > > +#include "pp_debug.h" > > +#include <linux/firmware.h> > > +#include "amdgpu.h" > > +#include "amdgpu_smu.h" > > +#include "atomfirmware.h" > > +#include "amdgpu_atomfirmware.h" > > +#include "smu_v11_0.h" > > +#include "smu11_driver_if_navi10.h" > > +#include "soc15_common.h" > > +#include "atom.h" > > +#include "navi10_ppt.h" > > +#include "smu_v11_0_pptable.h" > > +#include "smu_v11_0_ppsmc.h" > > + > > +#include "asic_reg/mp/mp_11_0_sh_mask.h" > > + > > +#define FEATURE_MASK(feature) (1ULL << feature) > > +#define SMC_DPM_FEATURE ( \ > > + FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ > > + FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) > > + > > +#define MSG_MAP(msg, index) \ > > + [SMU_MSG_##msg] = index > > + > > +static int navi10_message_map[SMU_MSG_MAX_COUNT] = { > > + MSG_MAP(TestMessage, > > PPSMC_MSG_TestMessage), > > + MSG_MAP(GetSmuVersion, > > PPSMC_MSG_GetSmuVersion), > > + MSG_MAP(GetDriverIfVersion, > > PPSMC_MSG_GetDriverIfVersion), > > + MSG_MAP(SetAllowedFeaturesMaskLow, > > PPSMC_MSG_SetAllowedFeaturesMaskLow), > > + MSG_MAP(SetAllowedFeaturesMaskHigh, > > PPSMC_MSG_SetAllowedFeaturesMaskHigh), > > + MSG_MAP(EnableAllSmuFeatures, > > PPSMC_MSG_EnableAllSmuFeatures), > > + MSG_MAP(DisableAllSmuFeatures, > > PPSMC_MSG_DisableAllSmuFeatures), > > + MSG_MAP(EnableSmuFeaturesLow, > > PPSMC_MSG_EnableSmuFeaturesLow), > > + MSG_MAP(EnableSmuFeaturesHigh, > > PPSMC_MSG_EnableSmuFeaturesHigh), > > + MSG_MAP(DisableSmuFeaturesLow, > > PPSMC_MSG_DisableSmuFeaturesLow), > > + MSG_MAP(DisableSmuFeaturesHigh, > > PPSMC_MSG_DisableSmuFeaturesHigh), > > + MSG_MAP(GetEnabledSmuFeaturesLow, > > PPSMC_MSG_GetEnabledSmuFeaturesLow), > > + MSG_MAP(GetEnabledSmuFeaturesHigh, > > PPSMC_MSG_GetEnabledSmuFeaturesHigh), > > + MSG_MAP(SetWorkloadMask, > > PPSMC_MSG_SetWorkloadMask), > > + MSG_MAP(SetPptLimit, > > PPSMC_MSG_SetPptLimit), > > + MSG_MAP(SetDriverDramAddrHigh, > > PPSMC_MSG_SetDriverDramAddrHigh), > > + MSG_MAP(SetDriverDramAddrLow, > > PPSMC_MSG_SetDriverDramAddrLow), > > + MSG_MAP(SetToolsDramAddrHigh, > > PPSMC_MSG_SetToolsDramAddrHigh), > > + MSG_MAP(SetToolsDramAddrLow, > > PPSMC_MSG_SetToolsDramAddrLow), > > + MSG_MAP(TransferTableSmu2Dram, > > PPSMC_MSG_TransferTableSmu2Dram), > > + MSG_MAP(TransferTableDram2Smu, > > PPSMC_MSG_TransferTableDram2Smu), > > + MSG_MAP(UseDefaultPPTable, > > PPSMC_MSG_UseDefaultPPTable), > > + MSG_MAP(UseBackupPPTable, > > PPSMC_MSG_UseBackupPPTable), > > + MSG_MAP(RunBtc, > > PPSMC_MSG_RunBtc), > > + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco), > > + MSG_MAP(SetSoftMinByFreq, > > PPSMC_MSG_SetSoftMinByFreq), > > + MSG_MAP(SetSoftMaxByFreq, > > PPSMC_MSG_SetSoftMaxByFreq), > > + MSG_MAP(SetHardMinByFreq, > > PPSMC_MSG_SetHardMinByFreq), > > + MSG_MAP(SetHardMaxByFreq, > > PPSMC_MSG_SetHardMaxByFreq), > > + MSG_MAP(GetMinDpmFreq, > > PPSMC_MSG_GetMinDpmFreq), > > + MSG_MAP(GetMaxDpmFreq, > > PPSMC_MSG_GetMaxDpmFreq), > > + MSG_MAP(GetDpmFreqByIndex, > > PPSMC_MSG_GetDpmFreqByIndex), > > + MSG_MAP(SetMemoryChannelConfig, > > PPSMC_MSG_SetMemoryChannelConfig), > > + MSG_MAP(SetGeminiMode, > > PPSMC_MSG_SetGeminiMode), > > + MSG_MAP(SetGeminiApertureHigh, > > PPSMC_MSG_SetGeminiApertureHigh), > > + MSG_MAP(SetGeminiApertureLow, > > PPSMC_MSG_SetGeminiApertureLow), > > + MSG_MAP(OverridePcieParameters, > > PPSMC_MSG_OverridePcieParameters), > > + MSG_MAP(SetMinDeepSleepDcefclk, > > PPSMC_MSG_SetMinDeepSleepDcefclk), > > + MSG_MAP(ReenableAcDcInterrupt, > > PPSMC_MSG_ReenableAcDcInterrupt), > > + MSG_MAP(NotifyPowerSource, > > PPSMC_MSG_NotifyPowerSource), > > + MSG_MAP(SetUclkFastSwitch, > > PPSMC_MSG_SetUclkFastSwitch), > > + MSG_MAP(SetVideoFps, > > PPSMC_MSG_SetVideoFps), > > + MSG_MAP(PrepareMp1ForUnload, > > PPSMC_MSG_PrepareMp1ForUnload), > > + MSG_MAP(DramLogSetDramAddrHigh, > > PPSMC_MSG_DramLogSetDramAddrHigh), > > + MSG_MAP(DramLogSetDramAddrLow, > > PPSMC_MSG_DramLogSetDramAddrLow), > > + MSG_MAP(DramLogSetDramSize, > > PPSMC_MSG_DramLogSetDramSize), > > + MSG_MAP(ConfigureGfxDidt, > > PPSMC_MSG_ConfigureGfxDidt), > > + MSG_MAP(NumOfDisplays, > > PPSMC_MSG_NumOfDisplays), > > + MSG_MAP(SetSystemVirtualDramAddrHigh, > > PPSMC_MSG_SetSystemVirtualDramAddrHigh), > > + MSG_MAP(SetSystemVirtualDramAddrLow, > > PPSMC_MSG_SetSystemVirtualDramAddrLow), > > + MSG_MAP(AllowGfxOff, > > PPSMC_MSG_AllowGfxOff), > > + MSG_MAP(DisallowGfxOff, > > PPSMC_MSG_DisallowGfxOff), > > + MSG_MAP(GetPptLimit, > > PPSMC_MSG_GetPptLimit), > > + MSG_MAP(GetDcModeMaxDpmFreq, > > PPSMC_MSG_GetDcModeMaxDpmFreq), > > + MSG_MAP(GetDebugData, > > PPSMC_MSG_GetDebugData), > > + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco), > > + MSG_MAP(PrepareMp1ForReset, > > PPSMC_MSG_PrepareMp1ForReset), > > + MSG_MAP(PrepareMp1ForShutdown, > > PPSMC_MSG_PrepareMp1ForShutdown), > > + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn), > > + MSG_MAP(PowerDownVcn, > > PPSMC_MSG_PowerDownVcn), > > + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg), > > + MSG_MAP(PowerDownJpeg, > > PPSMC_MSG_PowerDownJpeg), > > + MSG_MAP(BacoAudioD3PME, > > PPSMC_MSG_BacoAudioD3PME), > > +}; > > + > > +static int navi10_clk_map[SMU_CLK_COUNT] = { > > + CLK_MAP(GFXCLK, PPCLK_GFXCLK), > > + CLK_MAP(SCLK, PPCLK_GFXCLK), > > + CLK_MAP(SOCCLK, PPCLK_SOCCLK), > > + CLK_MAP(FCLK, PPCLK_SOCCLK), > > + CLK_MAP(UCLK, PPCLK_UCLK), > > + CLK_MAP(MCLK, PPCLK_UCLK), > > + CLK_MAP(DCLK, PPCLK_DCLK), > > + CLK_MAP(VCLK, PPCLK_VCLK), > > + CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), > > + CLK_MAP(DISPCLK, PPCLK_DISPCLK), > > + CLK_MAP(PIXCLK, PPCLK_PIXCLK), > > + CLK_MAP(PHYCLK, PPCLK_PHYCLK), > > +}; > > + > > +static int navi10_feature_mask_map[SMU_FEATURE_COUNT] = { > > + FEA_MAP(DPM_PREFETCHER), > > + FEA_MAP(DPM_GFXCLK), > > + FEA_MAP(DPM_GFX_PACE), > > + FEA_MAP(DPM_UCLK), > > + FEA_MAP(DPM_SOCCLK), > > + FEA_MAP(DPM_MP0CLK), > > + FEA_MAP(DPM_LINK), > > + FEA_MAP(DPM_DCEFCLK), > > + FEA_MAP(MEM_VDDCI_SCALING), > > + FEA_MAP(MEM_MVDD_SCALING), > > + FEA_MAP(DS_GFXCLK), > > + FEA_MAP(DS_SOCCLK), > > + FEA_MAP(DS_LCLK), > > + FEA_MAP(DS_DCEFCLK), > > + FEA_MAP(DS_UCLK), > > + FEA_MAP(GFX_ULV), > > + FEA_MAP(FW_DSTATE), > > + FEA_MAP(GFXOFF), > > + FEA_MAP(BACO), > > + FEA_MAP(VCN_PG), > > + FEA_MAP(JPEG_PG), > > + FEA_MAP(USB_PG), > > + FEA_MAP(RSMU_SMN_CG), > > + FEA_MAP(PPT), > > + FEA_MAP(TDC), > > + FEA_MAP(GFX_EDC), > > + FEA_MAP(APCC_PLUS), > > + FEA_MAP(GTHR), > > + FEA_MAP(ACDC), > > + FEA_MAP(VR0HOT), > > + FEA_MAP(VR1HOT), > > + FEA_MAP(FW_CTF), > > + FEA_MAP(FAN_CONTROL), > > + FEA_MAP(THERMAL), > > + FEA_MAP(GFX_DCS), > > + FEA_MAP(RM), > > + FEA_MAP(LED_DISPLAY), > > + FEA_MAP(GFX_SS), > > + FEA_MAP(OUT_OF_BAND_MONITOR), > > + FEA_MAP(TEMP_DEPENDENT_VMIN), > > + FEA_MAP(MMHUB_PG), > > + FEA_MAP(ATHUB_PG), > > +}; > > + > > +static int navi10_table_map[SMU_TABLE_COUNT] = { > > + TAB_MAP(PPTABLE), > > + TAB_MAP(WATERMARKS), > > + TAB_MAP(AVFS), > > + TAB_MAP(AVFS_PSM_DEBUG), > > + TAB_MAP(AVFS_FUSE_OVERRIDE), > > + TAB_MAP(PMSTATUSLOG), > > + TAB_MAP(SMU_METRICS), > > + TAB_MAP(DRIVER_SMU_CONFIG), > > + TAB_MAP(ACTIVITY_MONITOR_COEFF), > > + TAB_MAP(OVERDRIVE), > > + TAB_MAP(I2C_COMMANDS), > > + TAB_MAP(PACE), > > +}; > > + > > +static int navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { > > + PWR_MAP(AC), > > + PWR_MAP(DC), > > +}; > > + > > +static int navi10_workload_map[] = { > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, > > WORKLOAD_PPLIB_DEFAULT_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, > > WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, > > WORKLOAD_PPLIB_POWER_SAVING_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, > > WORKLOAD_PPLIB_VIDEO_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, > > WORKLOAD_PPLIB_VR_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > +}; > > + > > +static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + if (index > SMU_MSG_MAX_COUNT) > > + return -EINVAL; > > + > > + val = navi10_message_map[index]; > > + if (val > PPSMC_Message_Count) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_CLK_COUNT) > > + return -EINVAL; > > + > > + val = navi10_clk_map[index]; > > + if (val >= PPCLK_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int navi10_get_smu_feature_index(struct smu_context *smc, > > uint32_t index) > > +{ > > + int val; > > + if (index >= SMU_FEATURE_COUNT) > > + return -EINVAL; > > + > > + val = navi10_feature_mask_map[index]; > > + if (val > 64) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int navi10_get_smu_table_index(struct smu_context *smc, > uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_TABLE_COUNT) > > + return -EINVAL; > > + > > + val = navi10_table_map[index]; > > + if (val >= TABLE_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_POWER_SOURCE_COUNT) > > + return -EINVAL; > > + > > + val = navi10_pwr_src_map[index]; > > + if (val >= POWER_SOURCE_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > + > > +static int navi10_get_workload_type(struct smu_context *smu, enum > > PP_SMC_POWER_PROFILE profile) > > +{ > > + int val; > > + if (profile > PP_SMC_POWER_PROFILE_CUSTOM) > > + return -EINVAL; > > + > > + val = navi10_workload_map[profile]; > > + > > + return val; > > +} > > + > > +static bool is_asic_secure(struct smu_context *smu) > > +{ > > + struct amdgpu_device *adev = smu->adev; > > + bool is_secure = true; > > + uint32_t mp0_fw_intf; > > + > > + mp0_fw_intf = RREG32_PCIE(MP0_Public | > > + (smnMP0_FW_INTF & 0xffffffff)); > > + > > + if (!(mp0_fw_intf & (1 << 19))) > > + is_secure = false; > > + > > + return is_secure; > > +} > > + > > +static int > > +navi10_get_allowed_feature_mask(struct smu_context *smu, > > + uint32_t *feature_mask, uint32_t num) > > +{ > > + struct amdgpu_device *adev = smu->adev; > > + > > + if (num > 2) > > + return -EINVAL; > > + > > + memset(feature_mask, 0, sizeof(uint32_t) * num); > > + > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) > > + | FEATURE_MASK(FEATURE_DPM_LINK_BIT) > > + | FEATURE_MASK(FEATURE_GFX_ULV_BIT) > > + | > > FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) > > + | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) > > + | FEATURE_MASK(FEATURE_PPT_BIT) > > + | FEATURE_MASK(FEATURE_TDC_BIT) > > + | FEATURE_MASK(FEATURE_GFX_EDC_BIT) > > + | FEATURE_MASK(FEATURE_VR0HOT_BIT) > > + | > > FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) > > + | FEATURE_MASK(FEATURE_THERMAL_BIT) > > + | > > FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) > > + | FEATURE_MASK(FEATURE_DS_GFXCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_FW_DSTATE_BIT) > > + | FEATURE_MASK(FEATURE_BACO_BIT) > > + | FEATURE_MASK(FEATURE_ACDC_BIT); > > + > > + if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) > > + | > > FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); > > + > > + if (adev->pm.pp_feature & PP_GFXOFF_MASK) { > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_GFX_SS_BIT) > > + | FEATURE_MASK(FEATURE_GFXOFF_BIT); > > + /* TODO: remove it once fw fix the bug */ > > + *(uint64_t *)feature_mask &= > > ~FEATURE_MASK(FEATURE_FW_DSTATE_BIT); > > + } > > + > > + if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_MMHUB_PG_BIT); > > + > > + if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_ATHUB_PG_BIT); > > + > > + if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN) > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_VCN_PG_BIT); > > + > > + /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ > > + if (is_asic_secure(smu)) { > > + /* only for navi10 A0 */ > > + if ((adev->asic_type == CHIP_NAVI10) && > > + (adev->rev_id == 0)) { > > + *(uint64_t *)feature_mask &= > > + > > ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) > > + | > > FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT)); > > + *(uint64_t *)feature_mask &= > > + > > ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_check_powerplay_table(struct smu_context *smu) > > +{ > > + return 0; > > +} > > + > > +static int navi10_append_powerplay_table(struct smu_context *smu) > > +{ > > + struct amdgpu_device *adev = smu->adev; > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *smc_pptable = table_context->driver_pptable; > > + struct atom_smc_dpm_info_v4_5 *smc_dpm_table; > > + int index, ret; > > + > > + index = > > get_index_into_master_table(atom_master_list_of_data_tables_v2_1, > > + smc_dpm_info); > > + > > + ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, > > + (uint8_t **)&smc_dpm_table); > > + if (ret) > > + return ret; > > + > > + memcpy(smc_pptable->I2cControllers, smc_dpm_table- > > >I2cControllers, > > + sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS); > > + > > + /* SVI2 Board Parameters */ > > + smc_pptable->MaxVoltageStepGfx = smc_dpm_table- > > >MaxVoltageStepGfx; > > + smc_pptable->MaxVoltageStepSoc = smc_dpm_table- > > >MaxVoltageStepSoc; > > + smc_pptable->VddGfxVrMapping = smc_dpm_table- > > >VddGfxVrMapping; > > + smc_pptable->VddSocVrMapping = smc_dpm_table- > > >VddSocVrMapping; > > + smc_pptable->VddMem0VrMapping = smc_dpm_table- > > >VddMem0VrMapping; > > + smc_pptable->VddMem1VrMapping = smc_dpm_table- > > >VddMem1VrMapping; > > + smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table- > > >GfxUlvPhaseSheddingMask; > > + smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table- > > >SocUlvPhaseSheddingMask; > > + smc_pptable->ExternalSensorPresent = smc_dpm_table- > > >ExternalSensorPresent; > > + smc_pptable->Padding8_V = smc_dpm_table->Padding8_V; > > + > > + /* Telemetry Settings */ > > + smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent; > > + smc_pptable->GfxOffset = smc_dpm_table->GfxOffset; > > + smc_pptable->Padding_TelemetryGfx = smc_dpm_table- > > >Padding_TelemetryGfx; > > + smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent; > > + smc_pptable->SocOffset = smc_dpm_table->SocOffset; > > + smc_pptable->Padding_TelemetrySoc = smc_dpm_table- > > >Padding_TelemetrySoc; > > + smc_pptable->Mem0MaxCurrent = smc_dpm_table- > > >Mem0MaxCurrent; > > + smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset; > > + smc_pptable->Padding_TelemetryMem0 = smc_dpm_table- > > >Padding_TelemetryMem0; > > + smc_pptable->Mem1MaxCurrent = smc_dpm_table- > > >Mem1MaxCurrent; > > + smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset; > > + smc_pptable->Padding_TelemetryMem1 = smc_dpm_table- > > >Padding_TelemetryMem1; > > + > > + /* GPIO Settings */ > > + smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio; > > + smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity; > > + smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio; > > + smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity; > > + smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio; > > + smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity; > > + smc_pptable->GthrGpio = smc_dpm_table->GthrGpio; > > + smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity; > > + > > + /* LED Display Settings */ > > + smc_pptable->LedPin0 = smc_dpm_table->LedPin0; > > + smc_pptable->LedPin1 = smc_dpm_table->LedPin1; > > + smc_pptable->LedPin2 = smc_dpm_table->LedPin2; > > + smc_pptable->padding8_4 = smc_dpm_table->padding8_4; > > + > > + /* GFXCLK PLL Spread Spectrum */ > > + smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table- > > >PllGfxclkSpreadEnabled; > > + smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table- > > >PllGfxclkSpreadPercent; > > + smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table- > > >PllGfxclkSpreadFreq; > > + > > + /* GFXCLK DFLL Spread Spectrum */ > > + smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table- > > >DfllGfxclkSpreadEnabled; > > + smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table- > > >DfllGfxclkSpreadPercent; > > + smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table- > > >DfllGfxclkSpreadFreq; > > + > > + /* UCLK Spread Spectrum */ > > + smc_pptable->UclkSpreadEnabled = smc_dpm_table- > > >UclkSpreadEnabled; > > + smc_pptable->UclkSpreadPercent = smc_dpm_table- > > >UclkSpreadPercent; > > + smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq; > > + > > + /* SOCCLK Spread Spectrum */ > > + smc_pptable->SoclkSpreadEnabled = smc_dpm_table- > > >SoclkSpreadEnabled; > > + smc_pptable->SocclkSpreadPercent = smc_dpm_table- > > >SocclkSpreadPercent; > > + smc_pptable->SocclkSpreadFreq = smc_dpm_table- > > >SocclkSpreadFreq; > > + > > + /* Total board power */ > > + smc_pptable->TotalBoardPower = smc_dpm_table- > > >TotalBoardPower; > > + smc_pptable->BoardPadding = smc_dpm_table->BoardPadding; > > + > > + /* Mvdd Svi2 Div Ratio Setting */ > > + smc_pptable->MvddRatio = smc_dpm_table->MvddRatio; > > + > > + if (adev->pm.pp_feature & PP_GFXOFF_MASK) { > > + *(uint64_t *)smc_pptable->FeaturesToRun |= > > FEATURE_MASK(FEATURE_GFX_SS_BIT) > > + | > > FEATURE_MASK(FEATURE_GFXOFF_BIT); > > + > > + /* TODO: remove it once SMU fw fix it */ > > + smc_pptable->DebugOverrides |= > > DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN; > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_store_powerplay_table(struct smu_context *smu) > > +{ > > + struct smu_11_0_powerplay_table *powerplay_table = NULL; > > + struct smu_table_context *table_context = &smu->smu_table; > > + > > + if (!table_context->power_play_table) > > + return -EINVAL; > > + > > + powerplay_table = table_context->power_play_table; > > + > > + memcpy(table_context->driver_pptable, &powerplay_table- > > >smc_pptable, > > + sizeof(PPTable_t)); > > + > > + table_context->thermal_controller_type = powerplay_table- > > >thermal_controller_type; > > + > > + return 0; > > +} > > + > > +static int navi10_tables_init(struct smu_context *smu, struct smu_table > > *tables) > > +{ > > + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, > > sizeof(Watermarks_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, > > sizeof(SmuMetrics_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, > > sizeof(OverDriveTable_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, > > SMU11_TOOL_SIZE, > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, > > + sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, > > + AMDGPU_GEM_DOMAIN_VRAM); > > + > > + return 0; > > +} > > + > > +static int navi10_allocate_dpm_context(struct smu_context *smu) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + > > + if (smu_dpm->dpm_context) > > + return -EINVAL; > > + > > + smu_dpm->dpm_context = kzalloc(sizeof(struct > > smu_11_0_dpm_context), > > + GFP_KERNEL); > > + if (!smu_dpm->dpm_context) > > + return -ENOMEM; > > + > > + smu_dpm->dpm_context_size = sizeof(struct > > smu_11_0_dpm_context); > > + > > + return 0; > > +} > > + > > +static int navi10_set_default_dpm_table(struct smu_context *smu) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct smu_table_context *table_context = &smu->smu_table; > > + struct smu_11_0_dpm_context *dpm_context = smu_dpm- > > >dpm_context; > > + PPTable_t *driver_ppt = NULL; > > + > > + driver_ppt = table_context->driver_pptable; > > + > > + dpm_context->dpm_tables.soc_table.min = driver_ppt- > > >FreqTableSocclk[0]; > > + dpm_context->dpm_tables.soc_table.max = driver_ppt- > > >FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.gfx_table.min = driver_ppt- > > >FreqTableGfx[0]; > > + dpm_context->dpm_tables.gfx_table.max = driver_ppt- > > >FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.uclk_table.min = driver_ppt- > > >FreqTableUclk[0]; > > + dpm_context->dpm_tables.uclk_table.max = driver_ppt- > > >FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.vclk_table.min = driver_ppt- > > >FreqTableVclk[0]; > > + dpm_context->dpm_tables.vclk_table.max = driver_ppt- > > >FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.dclk_table.min = driver_ppt- > > >FreqTableDclk[0]; > > + dpm_context->dpm_tables.dclk_table.max = driver_ppt- > > >FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.dcef_table.min = driver_ppt- > > >FreqTableDcefclk[0]; > > + dpm_context->dpm_tables.dcef_table.max = driver_ppt- > > >FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.pixel_table.min = driver_ppt- > > >FreqTablePixclk[0]; > > + dpm_context->dpm_tables.pixel_table.max = driver_ppt- > > >FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.display_table.min = driver_ppt- > > >FreqTableDispclk[0]; > > + dpm_context->dpm_tables.display_table.max = driver_ppt- > > >FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1]; > > + > > + dpm_context->dpm_tables.phy_table.min = driver_ppt- > > >FreqTablePhyclk[0]; > > + dpm_context->dpm_tables.phy_table.max = driver_ppt- > > >FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1]; > > + > > + return 0; > > +} > > + > > +static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool > > enable) > > +{ > > + int ret = 0; > > + struct smu_power_context *smu_power = &smu->smu_power; > > + struct smu_power_gate *power_gate = &smu_power->power_gate; > > + > > + if (enable && power_gate->uvd_gated) { > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_PowerUpVcn, 1); > > + if (ret) > > + return ret; > > + } > > + power_gate->uvd_gated = false; > > + } else { > > + if (!enable && !power_gate->uvd_gated) { > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) { > > + ret = smu_send_smc_msg(smu, > > SMU_MSG_PowerDownVcn); > > + if (ret) > > + return ret; > > + } > > + power_gate->uvd_gated = true; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_get_current_clk_freq_by_table(struct smu_context > *smu, > > + enum smu_clk_type clk_type, > > + uint32_t *value) > > +{ > > + static SmuMetrics_t metrics = {0}; > > + int ret = 0, clk_id = 0; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void > > *)&metrics, false); > > + if (ret) > > + return ret; > > + > > + clk_id = smu_clk_get_index(smu, clk_type); > > + if (clk_id < 0) > > + return clk_id; > > + > > + *value = metrics.CurrClock[clk_id]; > > + > > + return ret; > > +} > > + > > +static int navi10_print_clk_levels(struct smu_context *smu, > > + enum smu_clk_type clk_type, char *buf) > > +{ > > + int i, size = 0, ret = 0; > > + uint32_t cur_value = 0, value = 0, count = 0; > > + > > + switch (clk_type) { > > + case SMU_GFXCLK: > > + case SMU_SCLK: > > + case SMU_SOCCLK: > > + case SMU_MCLK: > > + case SMU_UCLK: > > + case SMU_FCLK: > > + case SMU_DCEFCLK: > > + ret = smu_get_current_clk_freq(smu, clk_type, &cur_value); > > + if (ret) > > + return size; > > + /* 10KHz -> MHz */ > > + cur_value = cur_value / 100; > > + > > + size += sprintf(buf, "current clk: %uMhz\n", cur_value); > > + > > + ret = smu_get_dpm_level_count(smu, clk_type, &count); > > + if (ret) > > + return size; > > + > > + for (i = 0; i < count; i++) { > > + ret = smu_get_dpm_freq_by_index(smu, clk_type, i, > > &value); > > + if (ret) > > + return size; > > + > > + size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, > > + cur_value == value ? "*" : ""); > > + } > > + break; > > + default: > > + break; > > + } > > + > > + return size; > > +} > > + > > +static int navi10_force_clk_levels(struct smu_context *smu, > > + enum smu_clk_type clk_type, uint32_t > > mask) > > +{ > > + > > + int ret = 0, size = 0; > > + uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, > > max_freq = 0; > > + > > + soft_min_level = mask ? (ffs(mask) - 1) : 0; > > + soft_max_level = mask ? (fls(mask) - 1) : 0; > > + > > + switch (clk_type) { > > + case SMU_GFXCLK: > > + case SMU_SCLK: > > + case SMU_SOCCLK: > > + case SMU_MCLK: > > + case SMU_UCLK: > > + case SMU_DCEFCLK: > > + case SMU_FCLK: > > + ret = smu_get_dpm_freq_by_index(smu, clk_type, > > soft_min_level, &min_freq); > > + if (ret) > > + return size; > > + > > + ret = smu_get_dpm_freq_by_index(smu, clk_type, > > soft_max_level, &max_freq); > > + if (ret) > > + return size; > > + > > + ret = smu_set_soft_freq_range(smu, clk_type, min_freq, > > max_freq); > > + if (ret) > > + return size; > > + break; > > + default: > > + break; > > + } > > + > > + return size; > > +} > > + > > +static int navi10_populate_umd_state_clk(struct smu_context *smu) > > +{ > > + int ret = 0; > > + uint32_t min_sclk_freq = 0; > > + > > + ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, > > NULL); > > + if (ret) > > + return ret; > > + > > + smu->pstate_sclk = min_sclk_freq * 100; > > + > > + return ret; > > +} > > + > > +static int navi10_get_clock_by_type_with_latency(struct smu_context > > *smu, > > + enum smu_clk_type > > clk_type, > > + struct > > pp_clock_levels_with_latency *clocks) > > +{ > > + int ret = 0, i = 0; > > + uint32_t level_count = 0, freq = 0; > > + > > + switch (clk_type) { > > + case SMU_GFXCLK: > > + case SMU_DCEFCLK: > > + case SMU_SOCCLK: > > + ret = smu_get_dpm_level_count(smu, clk_type, > > &level_count); > > + if (ret) > > + return ret; > > + > > + level_count = min(level_count, > > (uint32_t)MAX_NUM_CLOCKS); > > + clocks->num_levels = level_count; > > + > > + for (i = 0; i < level_count; i++) { > > + ret = smu_get_dpm_freq_by_index(smu, clk_type, i, > > &freq); > > + if (ret) > > + return ret; > > + > > + clocks->data[i].clocks_in_khz = freq * 1000; > > + clocks->data[i].latency_in_us = 0; > > + } > > + break; > > + default: > > + break; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_pre_display_config_changed(struct smu_context *smu) > > +{ > > + int ret = 0; > > + uint32_t max_freq = 0; > > + > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_NumOfDisplays, 0); > > + if (ret) > > + return ret; > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, > > &max_freq); > > + if (ret) > > + return ret; > > + ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, > > max_freq); > > + if (ret) > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_display_config_changed(struct smu_context *smu) > > +{ > > + int ret = 0; > > + > > + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { > > + ret = smu_write_watermarks_table(smu); > > + if (ret) > > + return ret; > > + > > + smu->watermarks_bitmap |= WATERMARKS_LOADED; > > + } > > + > > + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > + smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > + smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_NumOfDisplays, > > + smu->display_config- > > >num_display); > > + if (ret) > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_force_dpm_limit_value(struct smu_context *smu, bool > > highest) > > +{ > > + int ret = 0, i = 0; > > + uint32_t min_freq, max_freq, force_freq; > > + enum smu_clk_type clk_type; > > + > > + enum smu_clk_type clks[] = { > > + SMU_GFXCLK, > > + SMU_MCLK, > > + SMU_SOCCLK, > > + }; > > + > > + for (i = 0; i < ARRAY_SIZE(clks); i++) { > > + clk_type = clks[i]; > > + ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, > > &max_freq); > > + if (ret) > > + return ret; > > + > > + force_freq = highest ? max_freq : min_freq; > > + ret = smu_set_soft_freq_range(smu, clk_type, force_freq, > > force_freq); > > + if (ret) > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_unforce_dpm_levels(struct smu_context *smu) { > > + > > + int ret = 0, i = 0; > > + uint32_t min_freq, max_freq; > > + enum smu_clk_type clk_type; > > + > > + struct clk_feature_map { > > + enum smu_clk_type clk_type; > > + uint32_t feature; > > + } clk_feature_map[] = { > > + {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT}, > > + {SMU_MCLK, SMU_FEATURE_DPM_UCLK_BIT}, > > + {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, > > + }; > > + > > + for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { > > + if (!smu_feature_is_enabled(smu, > > clk_feature_map[i].feature)) > > + continue; > > + > > + clk_type = clk_feature_map[i].clk_type; > > + > > + ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, > > &max_freq); > > + if (ret) > > + return ret; > > + > > + ret = smu_set_soft_freq_range(smu, clk_type, min_freq, > > max_freq); > > + if (ret) > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_get_gpu_power(struct smu_context *smu, uint32_t > > *value) > > +{ > > + int ret = 0; > > + SmuMetrics_t metrics; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, (void > > *)&metrics, > > + false); > > + if (ret) > > + return ret; > > + > > + *value = metrics.CurrSocketPower << 8; > > + > > + return 0; > > +} > > + > > +static int navi10_get_current_activity_percent(struct smu_context *smu, > > + uint32_t *value) > > +{ > > + int ret = 0; > > + SmuMetrics_t metrics; > > + > > + if (!value) > > + return -EINVAL; > > + > > + msleep(1); > > + > > + ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > + (void *)&metrics, false); > > + if (ret) > > + return ret; > > + > > + *value = metrics.AverageGfxActivity; > > + > > + return 0; > > +} > > + > > +static bool navi10_is_dpm_running(struct smu_context *smu) > > +{ > > + int ret = 0; > > + uint32_t feature_mask[2]; > > + unsigned long feature_enabled; > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | > > + ((uint64_t)feature_mask[1] << 32)); > > + return !!(feature_enabled & SMC_DPM_FEATURE); > > +} > > + > > +static int navi10_get_fan_speed(struct smu_context *smu, uint16_t > *value) > > +{ > > + SmuMetrics_t metrics = {0}; > > + int ret = 0; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > + (void *)&metrics, false); > > + if (ret) > > + return ret; > > + > > + *value = metrics.CurrFanSpeed; > > + > > + return ret; > > +} > > + > > +static int navi10_get_fan_speed_percent(struct smu_context *smu, > > + uint32_t *speed) > > +{ > > + int ret = 0; > > + uint32_t percent = 0; > > + uint16_t current_rpm; > > + PPTable_t *pptable = smu->smu_table.driver_pptable; > > + > > + ret = navi10_get_fan_speed(smu, ¤t_rpm); > > + if (ret) > > + return ret; > > + > > + percent = current_rpm * 100 / pptable->FanMaximumRpm; > > + *speed = percent > 100 ? 100 : percent; > > + > > + return ret; > > +} > > + > > +static int navi10_get_power_profile_mode(struct smu_context *smu, > char > > *buf) > > +{ > > + DpmActivityMonitorCoeffInt_t activity_monitor; > > + uint32_t i, size = 0; > > + uint16_t workload_type = 0; > > + static const char *profile_name[] = { > > + "BOOTUP_DEFAULT", > > + "3D_FULL_SCREEN", > > + "POWER_SAVING", > > + "VIDEO", > > + "VR", > > + "COMPUTE", > > + "CUSTOM"}; > > + static const char *title[] = { > > + "PROFILE_INDEX(NAME)", > > + "CLOCK_TYPE(NAME)", > > + "FPS", > > + "MinFreqType", > > + "MinActiveFreqType", > > + "MinActiveFreq", > > + "BoosterFreqType", > > + "BoosterFreq", > > + "PD_Data_limit_c", > > + "PD_Data_error_coeff", > > + "PD_Data_error_rate_coeff"}; > > + int result = 0; > > + > > + if (!buf) > > + return -EINVAL; > > + > > + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", > > + title[0], title[1], title[2], title[3], title[4], title[5], > > + title[6], title[7], title[8], title[9], title[10]); > > + > > + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { > > + /* conv PP_SMC_POWER_PROFILE* to > > WORKLOAD_PPLIB_*_BIT */ > > + workload_type = smu_workload_get_type(smu, i); > > + result = smu_update_table(smu, > > + > > SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16, > > + (void *)(&activity_monitor), false); > > + if (result) { > > + pr_err("[%s] Failed to get activity monitor!", > > __func__); > > + return result; > > + } > > + > > + size += sprintf(buf + size, "%2d %14s%s:\n", > > + i, profile_name[i], (i == smu->power_profile_mode) ? > > "*" : " "); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 0, > > + "GFXCLK", > > + activity_monitor.Gfx_FPS, > > + activity_monitor.Gfx_MinFreqStep, > > + activity_monitor.Gfx_MinActiveFreqType, > > + activity_monitor.Gfx_MinActiveFreq, > > + activity_monitor.Gfx_BoosterFreqType, > > + activity_monitor.Gfx_BoosterFreq, > > + activity_monitor.Gfx_PD_Data_limit_c, > > + activity_monitor.Gfx_PD_Data_error_coeff, > > + activity_monitor.Gfx_PD_Data_error_rate_coeff); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 1, > > + "SOCCLK", > > + activity_monitor.Soc_FPS, > > + activity_monitor.Soc_MinFreqStep, > > + activity_monitor.Soc_MinActiveFreqType, > > + activity_monitor.Soc_MinActiveFreq, > > + activity_monitor.Soc_BoosterFreqType, > > + activity_monitor.Soc_BoosterFreq, > > + activity_monitor.Soc_PD_Data_limit_c, > > + activity_monitor.Soc_PD_Data_error_coeff, > > + activity_monitor.Soc_PD_Data_error_rate_coeff); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 2, > > + "MEMLK", > > + activity_monitor.Mem_FPS, > > + activity_monitor.Mem_MinFreqStep, > > + activity_monitor.Mem_MinActiveFreqType, > > + activity_monitor.Mem_MinActiveFreq, > > + activity_monitor.Mem_BoosterFreqType, > > + activity_monitor.Mem_BoosterFreq, > > + activity_monitor.Mem_PD_Data_limit_c, > > + activity_monitor.Mem_PD_Data_error_coeff, > > + activity_monitor.Mem_PD_Data_error_rate_coeff); > > + } > > + > > + return size; > > +} > > + > > +static int navi10_set_power_profile_mode(struct smu_context *smu, > long > > *input, uint32_t size) > > +{ > > + DpmActivityMonitorCoeffInt_t activity_monitor; > > + int workload_type, ret = 0; > > + > > + smu->power_profile_mode = input[size]; > > + > > + if (smu->power_profile_mode > > > PP_SMC_POWER_PROFILE_CUSTOM) { > > + pr_err("Invalid power profile mode %d\n", smu- > > >power_profile_mode); > > + return -EINVAL; > > + } > > + > > + if (smu->power_profile_mode == > > PP_SMC_POWER_PROFILE_CUSTOM) { > > + if (size < 0) > > + return -EINVAL; > > + > > + ret = smu_update_table(smu, > > + SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > + (void *)(&activity_monitor), false); > > + if (ret) { > > + pr_err("[%s] Failed to get activity monitor!", > > __func__); > > + return ret; > > + } > > + > > + switch (input[0]) { > > + case 0: /* Gfxclk */ > > + activity_monitor.Gfx_FPS = input[1]; > > + activity_monitor.Gfx_MinFreqStep = input[2]; > > + activity_monitor.Gfx_MinActiveFreqType = input[3]; > > + activity_monitor.Gfx_MinActiveFreq = input[4]; > > + activity_monitor.Gfx_BoosterFreqType = input[5]; > > + activity_monitor.Gfx_BoosterFreq = input[6]; > > + activity_monitor.Gfx_PD_Data_limit_c = input[7]; > > + activity_monitor.Gfx_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Gfx_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + case 1: /* Socclk */ > > + activity_monitor.Soc_FPS = input[1]; > > + activity_monitor.Soc_MinFreqStep = input[2]; > > + activity_monitor.Soc_MinActiveFreqType = input[3]; > > + activity_monitor.Soc_MinActiveFreq = input[4]; > > + activity_monitor.Soc_BoosterFreqType = input[5]; > > + activity_monitor.Soc_BoosterFreq = input[6]; > > + activity_monitor.Soc_PD_Data_limit_c = input[7]; > > + activity_monitor.Soc_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Soc_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + case 2: /* Memlk */ > > + activity_monitor.Mem_FPS = input[1]; > > + activity_monitor.Mem_MinFreqStep = input[2]; > > + activity_monitor.Mem_MinActiveFreqType = > > input[3]; > > + activity_monitor.Mem_MinActiveFreq = input[4]; > > + activity_monitor.Mem_BoosterFreqType = input[5]; > > + activity_monitor.Mem_BoosterFreq = input[6]; > > + activity_monitor.Mem_PD_Data_limit_c = input[7]; > > + activity_monitor.Mem_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Mem_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + } > > + > > + ret = smu_update_table(smu, > > + SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > + (void *)(&activity_monitor), true); > > + if (ret) { > > + pr_err("[%s] Failed to set activity monitor!", > > __func__); > > + return ret; > > + } > > + } > > + > > + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ > > + workload_type = smu_workload_get_type(smu, smu- > > >power_profile_mode); > > + smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetWorkloadMask, > > + 1 << workload_type); > > + > > + return ret; > > +} > > + > > +static int navi10_get_profiling_clk_mask(struct smu_context *smu, > > + enum amd_dpm_forced_level level, > > + uint32_t *sclk_mask, > > + uint32_t *mclk_mask, > > + uint32_t *soc_mask) > > +{ > > + int ret = 0; > > + uint32_t level_count = 0; > > + > > + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > + if (sclk_mask) > > + *sclk_mask = 0; > > + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > + if (mclk_mask) > > + *mclk_mask = 0; > > + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + if(sclk_mask) { > > + ret = smu_get_dpm_level_count(smu, SMU_SCLK, > > &level_count); > > + if (ret) > > + return ret; > > + *sclk_mask = level_count - 1; > > + } > > + > > + if(mclk_mask) { > > + ret = smu_get_dpm_level_count(smu, SMU_MCLK, > > &level_count); > > + if (ret) > > + return ret; > > + *sclk_mask = level_count - 1; > > + } > > + > > + if(soc_mask) { > > + ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, > > &level_count); > > + if (ret) > > + return ret; > > + *sclk_mask = level_count - 1; > > + } > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_notify_smc_dispaly_config(struct smu_context *smu) > > +{ > > + struct smu_clocks min_clocks = {0}; > > + struct pp_display_clock_request clock_req; > > + int ret = 0; > > + > > + min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; > > + min_clocks.dcef_clock_in_sr = smu->display_config- > > >min_dcef_deep_sleep_set_clk; > > + min_clocks.memory_clock = smu->display_config- > > >min_mem_set_clock; > > + > > + if (smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + clock_req.clock_type = amd_pp_dcef_clock; > > + clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; > > + if (!smu_display_clock_voltage_request(smu, &clock_req)) { > > + if (smu_feature_is_supported(smu, > > SMU_FEATURE_DS_DCEFCLK_BIT)) { > > + ret = smu_send_smc_msg_with_param(smu, > > + > > SMU_MSG_SetMinDeepSleepDcefclk, > > + > > min_clocks.dcef_clock_in_sr/100); > > + if (ret) { > > + pr_err("Attempt to set divider for > > DCEFCLK Failed!"); > > + return ret; > > + } > > + } > > + } else { > > + pr_info("Attempt to set Hard Min for DCEFCLK > > Failed!"); > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + ret = smu_set_hard_freq_range(smu, SMU_UCLK, > > min_clocks.memory_clock/100, 0); > > + if (ret) { > > + pr_err("[%s] Set hard min uclk failed!", __func__); > > + return ret; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_set_watermarks_table(struct smu_context *smu, > > + void *watermarks, struct > > + > > dm_pp_wm_sets_with_clock_ranges_soc15 > > + *clock_ranges) > > +{ > > + int i; > > + Watermarks_t *table = watermarks; > > + > > + if (!table || !clock_ranges) > > + return -EINVAL; > > + > > + if (clock_ranges->num_wm_dmif_sets > 4 || > > + clock_ranges->num_wm_mcif_sets > 4) > > + return -EINVAL; > > + > > + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { > > + table->WatermarkRow[1][i].MinClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MaxClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MinUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MaxUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].WmSetting = (uint8_t) > > + clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_set_id; > > + } > > + > > + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { > > + table->WatermarkRow[0][i].MinClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MaxClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MinUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MaxUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].WmSetting = (uint8_t) > > + clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_set_id; > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_read_sensor(struct smu_context *smu, > > + enum amd_pp_sensors sensor, > > + void *data, uint32_t *size) > > +{ > > + int ret = 0; > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *pptable = table_context->driver_pptable; > > + > > + switch (sensor) { > > + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: > > + *(uint32_t *)data = pptable->FanMaximumRpm; > > + *size = 4; > > + break; > > + case AMDGPU_PP_SENSOR_GPU_LOAD: > > + ret = navi10_get_current_activity_percent(smu, (uint32_t > > *)data); > > + *size = 4; > > + break; > > + case AMDGPU_PP_SENSOR_GPU_POWER: > > + ret = navi10_get_gpu_power(smu, (uint32_t *)data); > > + *size = 4; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + return ret; > > +} > > + > > +static int navi10_get_uclk_dpm_states(struct smu_context *smu, > uint32_t > > *clocks_in_khz, uint32_t *num_states) > > +{ > > + uint32_t num_discrete_levels = 0; > > + uint16_t *dpm_levels = NULL; > > + uint16_t i = 0; > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *driver_ppt = NULL; > > + > > + if (!clocks_in_khz || ! num_states || !table_context->driver_pptable) > > + return -EINVAL; > > + > > + driver_ppt = table_context->driver_pptable; > > + num_discrete_levels = driver_ppt- > > >DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; > > + dpm_levels = driver_ppt->FreqTableUclk; > > + > > + if (num_discrete_levels == 0 || dpm_levels == NULL) > > + return -EINVAL; > > + > > + *num_states = num_discrete_levels; > > + for (i = 0; i < num_discrete_levels; i++) { > > + /* convert to khz */ > > + *clocks_in_khz = (*dpm_levels) * 1000; > > + clocks_in_khz++; > > + dpm_levels++; > > + } > > + > > + return 0; > > +} > > + > > +static int navi10_get_ppfeature_status(struct smu_context *smu, > > + char *buf) > > +{ > > + static const char *ppfeature_name[] = { > > + "DPM_PREFETCHER", > > + "DPM_GFXCLK", > > + "DPM_GFX_PACE", > > + "DPM_UCLK", > > + "DPM_SOCCLK", > > + "DPM_MP0CLK", > > + "DPM_LINK", > > + "DPM_DCEFCLK", > > + "MEM_VDDCI_SCALING", > > + "MEM_MVDD_SCALING", > > + "DS_GFXCLK", > > + "DS_SOCCLK", > > + "DS_LCLK", > > + "DS_DCEFCLK", > > + "DS_UCLK", > > + "GFX_ULV", > > + "FW_DSTATE", > > + "GFXOFF", > > + "BACO", > > + "VCN_PG", > > + "JPEG_PG", > > + "USB_PG", > > + "RSMU_SMN_CG", > > + "PPT", > > + "TDC", > > + "GFX_EDC", > > + "APCC_PLUS", > > + "GTHR", > > + "ACDC", > > + "VR0HOT", > > + "VR1HOT", > > + "FW_CTF", > > + "FAN_CONTROL", > > + "THERMAL", > > + "GFX_DCS", > > + "RM", > > + "LED_DISPLAY", > > + "GFX_SS", > > + "OUT_OF_BAND_MONITOR", > > + "TEMP_DEPENDENT_VMIN", > > + "MMHUB_PG", > > + "ATHUB_PG"}; > > + static const char *output_title[] = { > > + "FEATURES", > > + "BITMASK", > > + "ENABLEMENT"}; > > + uint64_t features_enabled; > > + uint32_t feature_mask[2]; > > + int i; > > + int ret = 0; > > + int size = 0; > > + > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + PP_ASSERT_WITH_CODE(!ret, > > + "[GetPPfeatureStatus] Failed to get enabled smc > > features!", > > + return ret); > > + features_enabled = (uint64_t)feature_mask[0] | > > + (uint64_t)feature_mask[1] << 32; > > + > > + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", > > features_enabled); > > + size += sprintf(buf + size, "%-19s %-22s %s\n", > > + output_title[0], > > + output_title[1], > > + output_title[2]); > > + for (i = 0; i < (sizeof(ppfeature_name) / sizeof(ppfeature_name[0])); > > i++) { > > + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", > > + ppfeature_name[i], > > + 1ULL << i, > > + (features_enabled & (1ULL << i)) ? > > "Y" : "N"); > > + } > > + > > + return size; > > +} > > + > > +static int navi10_enable_smc_features(struct smu_context *smu, > > + bool enabled, > > + uint64_t feature_masks) > > +{ > > + struct smu_feature *feature = &smu->smu_feature; > > + uint32_t feature_low, feature_high; > > + uint32_t feature_mask[2]; > > + int ret = 0; > > + > > + feature_low = (uint32_t)(feature_masks & 0xFFFFFFFF); > > + feature_high = (uint32_t)((feature_masks & > > 0xFFFFFFFF00000000ULL) >> 32); > > + > > + if (enabled) { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesLow, > > + feature_low); > > + if (ret) > > + return ret; > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesHigh, > > + feature_high); > > + if (ret) > > + return ret; > > + } else { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesLow, > > + feature_low); > > + if (ret) > > + return ret; > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesHigh, > > + feature_high); > > + if (ret) > > + return ret; > > + } > > + > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + if (ret) > > + return ret; > > + > > + mutex_lock(&feature->mutex); > > + bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, > > + feature->feature_num); > > + mutex_unlock(&feature->mutex); > > + > > + return 0; > > +} > > + > > +static int navi10_set_ppfeature_status(struct smu_context *smu, > > + uint64_t new_ppfeature_masks) > > +{ > > + uint64_t features_enabled; > > + uint32_t feature_mask[2]; > > + uint64_t features_to_enable; > > + uint64_t features_to_disable; > > + int ret = 0; > > + > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + PP_ASSERT_WITH_CODE(!ret, > > + "[SetPPfeatureStatus] Failed to get enabled smc > > features!", > > + return ret); > > + features_enabled = (uint64_t)feature_mask[0] | > > + (uint64_t)feature_mask[1] << 32; > > + > > + features_to_disable = > > + features_enabled & ~new_ppfeature_masks; > > + features_to_enable = > > + ~features_enabled & new_ppfeature_masks; > > + > > + pr_debug("features_to_disable 0x%llx\n", features_to_disable); > > + pr_debug("features_to_enable 0x%llx\n", features_to_enable); > > + > > + if (features_to_disable) { > > + ret = navi10_enable_smc_features(smu, false, > > features_to_disable); > > + PP_ASSERT_WITH_CODE(!ret, > > + "[SetPPfeatureStatus] Failed to disable smc > > features!", > > + return ret); > > + } > > + > > + if (features_to_enable) { > > + ret = navi10_enable_smc_features(smu, true, > > features_to_enable); > > + PP_ASSERT_WITH_CODE(!ret, > > + "[SetPPfeatureStatus] Failed to enable smc > > features!", > > + return ret); > > + } > > + > > + return 0; > > +} > > + > > +static const struct pptable_funcs navi10_ppt_funcs = { > > + .tables_init = navi10_tables_init, > > + .alloc_dpm_context = navi10_allocate_dpm_context, > > + .store_powerplay_table = navi10_store_powerplay_table, > > + .check_powerplay_table = navi10_check_powerplay_table, > > + .append_powerplay_table = navi10_append_powerplay_table, > > + .get_smu_msg_index = navi10_get_smu_msg_index, > > + .get_smu_clk_index = navi10_get_smu_clk_index, > > + .get_smu_feature_index = navi10_get_smu_feature_index, > > + .get_smu_table_index = navi10_get_smu_table_index, > > + .get_smu_power_index= navi10_get_pwr_src_index, > > + .get_workload_type = navi10_get_workload_type, > > + .get_allowed_feature_mask = navi10_get_allowed_feature_mask, > > + .set_default_dpm_table = navi10_set_default_dpm_table, > > + .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable, > > + .get_current_clk_freq_by_table = > > navi10_get_current_clk_freq_by_table, > > + .print_clk_levels = navi10_print_clk_levels, > > + .force_clk_levels = navi10_force_clk_levels, > > + .populate_umd_state_clk = navi10_populate_umd_state_clk, > > + .get_clock_by_type_with_latency = > > navi10_get_clock_by_type_with_latency, > > + .pre_display_config_changed = navi10_pre_display_config_changed, > > + .display_config_changed = navi10_display_config_changed, > > + .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config, > > + .force_dpm_limit_value = navi10_force_dpm_limit_value, > > + .unforce_dpm_levels = navi10_unforce_dpm_levels, > > + .is_dpm_running = navi10_is_dpm_running, > > + .get_fan_speed_percent = navi10_get_fan_speed_percent, > > + .get_power_profile_mode = navi10_get_power_profile_mode, > > + .set_power_profile_mode = navi10_set_power_profile_mode, > > + .get_profiling_clk_mask = navi10_get_profiling_clk_mask, > > + .set_watermarks_table = navi10_set_watermarks_table, > > + .read_sensor = navi10_read_sensor, > > + .get_uclk_dpm_states = navi10_get_uclk_dpm_states, > > + .get_ppfeature_status = navi10_get_ppfeature_status, > > + .set_ppfeature_status = navi10_set_ppfeature_status, > > +}; > > + > > +void navi10_set_ppt_funcs(struct smu_context *smu) > > +{ > > + struct smu_table_context *smu_table = &smu->smu_table; > > + > > + smu->ppt_funcs = &navi10_ppt_funcs; > > + smu->smc_if_version = SMU11_DRIVER_IF_VERSION; > > + smu_table->table_count = TABLE_COUNT; > > +} > > diff --git a/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.h > > b/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.h > > new file mode 100644 > > index 0000000..957288e > > --- /dev/null > > +++ b/drivers/gpu/drm/amd/powerplay/pptable/navi10_ppt.h > > @@ -0,0 +1,28 @@ > > +/* > > + * Copyright 2019 Advanced Micro Devices, Inc. > > + * > > + * Permission is hereby granted, free of charge, to any person obtaining a > > + * copy of this software and associated documentation files (the > > "Software"), > > + * to deal in the Software without restriction, including without limitation > > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > + * and/or sell copies of the Software, and to permit persons to whom the > > + * Software is furnished to do so, subject to the following conditions: > > + * > > + * The above copyright notice and this permission notice shall be included > in > > + * all copies or substantial portions of the Software. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > NO > > EVENT SHALL > > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > + * OTHER DEALINGS IN THE SOFTWARE. > > + * > > + */ > > +#ifndef __NAVI10_PPT_H__ > > +#define __NAVI10_PPT_H__ > > + > > +extern void navi10_set_ppt_funcs(struct smu_context *smu); > > + > > +#endif > > diff --git a/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.c > > b/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.c > > new file mode 100644 > > index 0000000..9a535f7 > > --- /dev/null > > +++ b/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.c > > @@ -0,0 +1,3302 @@ > > +/* > > + * Copyright 2019 Advanced Micro Devices, Inc. > > + * > > + * Permission is hereby granted, free of charge, to any person obtaining a > > + * copy of this software and associated documentation files (the > > "Software"), > > + * to deal in the Software without restriction, including without limitation > > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > + * and/or sell copies of the Software, and to permit persons to whom the > > + * Software is furnished to do so, subject to the following conditions: > > + * > > + * The above copyright notice and this permission notice shall be included > in > > + * all copies or substantial portions of the Software. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > NO > > EVENT SHALL > > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > + * OTHER DEALINGS IN THE SOFTWARE. > > + * > > + */ > > + > > +#include "pp_debug.h" > > +#include <linux/firmware.h> > > +#include "amdgpu.h" > > +#include "amdgpu_smu.h" > > +#include "atomfirmware.h" > > +#include "amdgpu_atomfirmware.h" > > +#include "smu_v11_0.h" > > +#include "smu11_driver_if.h" > > +#include "soc15_common.h" > > +#include "atom.h" > > +#include "power_state.h" > > +#include "vega20_ppt.h" > > +#include "vega20_pptable.h" > > +#include "vega20_ppsmc.h" > > +#include "nbio/nbio_7_4_sh_mask.h" > > +#include "asic_reg/thm/thm_11_0_2_offset.h" > > +#include "asic_reg/thm/thm_11_0_2_sh_mask.h" > > + > > +#define smnPCIE_LC_SPEED_CNTL 0x11140290 > > +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 > > + > > +#define CTF_OFFSET_EDGE 5 > > +#define CTF_OFFSET_HOTSPOT 5 > > +#define CTF_OFFSET_HBM 5 > > + > > +#define MSG_MAP(msg) \ > > + [SMU_MSG_##msg] = PPSMC_MSG_##msg > > + > > +#define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \ > > + FEATURE_DPM_GFXCLK_MASK | \ > > + FEATURE_DPM_UCLK_MASK | \ > > + FEATURE_DPM_SOCCLK_MASK | \ > > + FEATURE_DPM_UVD_MASK | \ > > + FEATURE_DPM_VCE_MASK | \ > > + FEATURE_DPM_MP0CLK_MASK | \ > > + FEATURE_DPM_LINK_MASK | \ > > + FEATURE_DPM_DCEFCLK_MASK) > > + > > +static int vega20_message_map[SMU_MSG_MAX_COUNT] = { > > + MSG_MAP(TestMessage), > > + MSG_MAP(GetSmuVersion), > > + MSG_MAP(GetDriverIfVersion), > > + MSG_MAP(SetAllowedFeaturesMaskLow), > > + MSG_MAP(SetAllowedFeaturesMaskHigh), > > + MSG_MAP(EnableAllSmuFeatures), > > + MSG_MAP(DisableAllSmuFeatures), > > + MSG_MAP(EnableSmuFeaturesLow), > > + MSG_MAP(EnableSmuFeaturesHigh), > > + MSG_MAP(DisableSmuFeaturesLow), > > + MSG_MAP(DisableSmuFeaturesHigh), > > + MSG_MAP(GetEnabledSmuFeaturesLow), > > + MSG_MAP(GetEnabledSmuFeaturesHigh), > > + MSG_MAP(SetWorkloadMask), > > + MSG_MAP(SetPptLimit), > > + MSG_MAP(SetDriverDramAddrHigh), > > + MSG_MAP(SetDriverDramAddrLow), > > + MSG_MAP(SetToolsDramAddrHigh), > > + MSG_MAP(SetToolsDramAddrLow), > > + MSG_MAP(TransferTableSmu2Dram), > > + MSG_MAP(TransferTableDram2Smu), > > + MSG_MAP(UseDefaultPPTable), > > + MSG_MAP(UseBackupPPTable), > > + MSG_MAP(RunBtc), > > + MSG_MAP(RequestI2CBus), > > + MSG_MAP(ReleaseI2CBus), > > + MSG_MAP(SetFloorSocVoltage), > > + MSG_MAP(SoftReset), > > + MSG_MAP(StartBacoMonitor), > > + MSG_MAP(CancelBacoMonitor), > > + MSG_MAP(EnterBaco), > > + MSG_MAP(SetSoftMinByFreq), > > + MSG_MAP(SetSoftMaxByFreq), > > + MSG_MAP(SetHardMinByFreq), > > + MSG_MAP(SetHardMaxByFreq), > > + MSG_MAP(GetMinDpmFreq), > > + MSG_MAP(GetMaxDpmFreq), > > + MSG_MAP(GetDpmFreqByIndex), > > + MSG_MAP(GetDpmClockFreq), > > + MSG_MAP(GetSsVoltageByDpm), > > + MSG_MAP(SetMemoryChannelConfig), > > + MSG_MAP(SetGeminiMode), > > + MSG_MAP(SetGeminiApertureHigh), > > + MSG_MAP(SetGeminiApertureLow), > > + MSG_MAP(SetMinLinkDpmByIndex), > > + MSG_MAP(OverridePcieParameters), > > + MSG_MAP(OverDriveSetPercentage), > > + MSG_MAP(SetMinDeepSleepDcefclk), > > + MSG_MAP(ReenableAcDcInterrupt), > > + MSG_MAP(NotifyPowerSource), > > + MSG_MAP(SetUclkFastSwitch), > > + MSG_MAP(SetUclkDownHyst), > > + MSG_MAP(GetCurrentRpm), > > + MSG_MAP(SetVideoFps), > > + MSG_MAP(SetTjMax), > > + MSG_MAP(SetFanTemperatureTarget), > > + MSG_MAP(PrepareMp1ForUnload), > > + MSG_MAP(DramLogSetDramAddrHigh), > > + MSG_MAP(DramLogSetDramAddrLow), > > + MSG_MAP(DramLogSetDramSize), > > + MSG_MAP(SetFanMaxRpm), > > + MSG_MAP(SetFanMinPwm), > > + MSG_MAP(ConfigureGfxDidt), > > + MSG_MAP(NumOfDisplays), > > + MSG_MAP(RemoveMargins), > > + MSG_MAP(ReadSerialNumTop32), > > + MSG_MAP(ReadSerialNumBottom32), > > + MSG_MAP(SetSystemVirtualDramAddrHigh), > > + MSG_MAP(SetSystemVirtualDramAddrLow), > > + MSG_MAP(WaflTest), > > + MSG_MAP(SetFclkGfxClkRatio), > > + MSG_MAP(AllowGfxOff), > > + MSG_MAP(DisallowGfxOff), > > + MSG_MAP(GetPptLimit), > > + MSG_MAP(GetDcModeMaxDpmFreq), > > + MSG_MAP(GetDebugData), > > + MSG_MAP(SetXgmiMode), > > + MSG_MAP(RunAfllBtc), > > + MSG_MAP(ExitBaco), > > + MSG_MAP(PrepareMp1ForReset), > > + MSG_MAP(PrepareMp1ForShutdown), > > + MSG_MAP(SetMGpuFanBoostLimitRpm), > > + MSG_MAP(GetAVFSVoltageByDpm), > > +}; > > + > > +static int vega20_clk_map[SMU_CLK_COUNT] = { > > + CLK_MAP(GFXCLK, PPCLK_GFXCLK), > > + CLK_MAP(VCLK, PPCLK_VCLK), > > + CLK_MAP(DCLK, PPCLK_DCLK), > > + CLK_MAP(ECLK, PPCLK_ECLK), > > + CLK_MAP(SOCCLK, PPCLK_SOCCLK), > > + CLK_MAP(UCLK, PPCLK_UCLK), > > + CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), > > + CLK_MAP(DISPCLK, PPCLK_DISPCLK), > > + CLK_MAP(PIXCLK, PPCLK_PIXCLK), > > + CLK_MAP(PHYCLK, PPCLK_PHYCLK), > > + CLK_MAP(FCLK, PPCLK_FCLK), > > +}; > > + > > +static int vega20_feature_mask_map[SMU_FEATURE_COUNT] = { > > + FEA_MAP(DPM_PREFETCHER), > > + FEA_MAP(DPM_GFXCLK), > > + FEA_MAP(DPM_UCLK), > > + FEA_MAP(DPM_SOCCLK), > > + FEA_MAP(DPM_UVD), > > + FEA_MAP(DPM_VCE), > > + FEA_MAP(ULV), > > + FEA_MAP(DPM_MP0CLK), > > + FEA_MAP(DPM_LINK), > > + FEA_MAP(DPM_DCEFCLK), > > + FEA_MAP(DS_GFXCLK), > > + FEA_MAP(DS_SOCCLK), > > + FEA_MAP(DS_LCLK), > > + FEA_MAP(PPT), > > + FEA_MAP(TDC), > > + FEA_MAP(THERMAL), > > + FEA_MAP(GFX_PER_CU_CG), > > + FEA_MAP(RM), > > + FEA_MAP(DS_DCEFCLK), > > + FEA_MAP(ACDC), > > + FEA_MAP(VR0HOT), > > + FEA_MAP(VR1HOT), > > + FEA_MAP(FW_CTF), > > + FEA_MAP(LED_DISPLAY), > > + FEA_MAP(FAN_CONTROL), > > + FEA_MAP(GFX_EDC), > > + FEA_MAP(GFXOFF), > > + FEA_MAP(CG), > > + FEA_MAP(DPM_FCLK), > > + FEA_MAP(DS_FCLK), > > + FEA_MAP(DS_MP1CLK), > > + FEA_MAP(DS_MP0CLK), > > + FEA_MAP(XGMI), > > +}; > > + > > +static int vega20_table_map[SMU_TABLE_COUNT] = { > > + TAB_MAP(PPTABLE), > > + TAB_MAP(WATERMARKS), > > + TAB_MAP(AVFS), > > + TAB_MAP(AVFS_PSM_DEBUG), > > + TAB_MAP(AVFS_FUSE_OVERRIDE), > > + TAB_MAP(PMSTATUSLOG), > > + TAB_MAP(SMU_METRICS), > > + TAB_MAP(DRIVER_SMU_CONFIG), > > + TAB_MAP(ACTIVITY_MONITOR_COEFF), > > + TAB_MAP(OVERDRIVE), > > +}; > > + > > +static int vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { > > + PWR_MAP(AC), > > + PWR_MAP(DC), > > +}; > > + > > +static int vega20_workload_map[] = { > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, > > WORKLOAD_DEFAULT_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, > > WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, > > WORKLOAD_PPLIB_POWER_SAVING_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, > > WORKLOAD_PPLIB_VIDEO_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, > > WORKLOAD_PPLIB_VR_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > +}; > > + > > +static int vega20_get_smu_table_index(struct smu_context *smc, > uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_TABLE_COUNT) > > + return -EINVAL; > > + > > + val = vega20_table_map[index]; > > + if (val >= TABLE_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_POWER_SOURCE_COUNT) > > + return -EINVAL; > > + > > + val = vega20_pwr_src_map[index]; > > + if (val >= POWER_SOURCE_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int vega20_get_smu_feature_index(struct smu_context *smc, > > uint32_t index) > > +{ > > + int val; > > + if (index >= SMU_FEATURE_COUNT) > > + return -EINVAL; > > + > > + val = vega20_feature_mask_map[index]; > > + if (val > 64) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + if (index >= SMU_CLK_COUNT) > > + return -EINVAL; > > + > > + val = vega20_clk_map[index]; > > + if (val >= PPCLK_COUNT) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t > > index) > > +{ > > + int val; > > + > > + if (index >= SMU_MSG_MAX_COUNT) > > + return -EINVAL; > > + > > + val = vega20_message_map[index]; > > + if (val > PPSMC_Message_Count) > > + return -EINVAL; > > + > > + return val; > > +} > > + > > +static int vega20_get_workload_type(struct smu_context *smu, enum > > PP_SMC_POWER_PROFILE profile) > > +{ > > + int val; > > + if (profile > PP_SMC_POWER_PROFILE_CUSTOM) > > + return -EINVAL; > > + > > + val = vega20_workload_map[profile]; > > + > > + return val; > > +} > > + > > +static int vega20_tables_init(struct smu_context *smu, struct smu_table > > *tables) > > +{ > > + struct smu_table_context *smu_table = &smu->smu_table; > > + > > + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, > > sizeof(Watermarks_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, > > sizeof(SmuMetrics_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, > > sizeof(OverDriveTable_t), > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, > > SMU11_TOOL_SIZE, > > + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, > > + sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, > > + AMDGPU_GEM_DOMAIN_VRAM); > > + > > + smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), > > GFP_KERNEL); > > + if (smu_table->metrics_table) > > + return -ENOMEM; > > + smu_table->metrics_time = 0; > > + > > + return 0; > > +} > > + > > +static int vega20_allocate_dpm_context(struct smu_context *smu) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + > > + if (smu_dpm->dpm_context) > > + return -EINVAL; > > + > > + smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table), > > + GFP_KERNEL); > > + if (!smu_dpm->dpm_context) > > + return -ENOMEM; > > + > > + if (smu_dpm->golden_dpm_context) > > + return -EINVAL; > > + > > + smu_dpm->golden_dpm_context = kzalloc(sizeof(struct > > vega20_dpm_table), > > + GFP_KERNEL); > > + if (!smu_dpm->golden_dpm_context) > > + return -ENOMEM; > > + > > + smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table); > > + > > + smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct > > smu_power_state), > > + GFP_KERNEL); > > + if (!smu_dpm->dpm_current_power_state) > > + return -ENOMEM; > > + > > + smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct > > smu_power_state), > > + GFP_KERNEL); > > + if (!smu_dpm->dpm_request_power_state) > > + return -ENOMEM; > > + > > + return 0; > > +} > > + > > +static int vega20_setup_od8_information(struct smu_context *smu) > > +{ > > + ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > + struct smu_table_context *table_context = &smu->smu_table; > > + struct vega20_od8_settings *od8_settings = (struct > > vega20_od8_settings *)smu->od_settings; > > + > > + uint32_t od_feature_count, od_feature_array_size, > > + od_setting_count, od_setting_array_size; > > + > > + if (!table_context->power_play_table) > > + return -EINVAL; > > + > > + powerplay_table = table_context->power_play_table; > > + > > + if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { > > + /* Setup correct ODFeatureCount, and store ODFeatureArray > > from > > + * powerplay table to od_feature_capabilities */ > > + od_feature_count = > > + (le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODFeatureCount) > > > + ATOM_VEGA20_ODFEATURE_COUNT) ? > > + ATOM_VEGA20_ODFEATURE_COUNT : > > + le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODFeatureCount); > > + > > + od_feature_array_size = sizeof(uint8_t) * od_feature_count; > > + > > + if (od8_settings->od_feature_capabilities) > > + return -EINVAL; > > + > > + od8_settings->od_feature_capabilities = > > kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities, > > + > > od_feature_array_size, > > + > > GFP_KERNEL); > > + if (!od8_settings->od_feature_capabilities) > > + return -ENOMEM; > > + > > + /* Setup correct ODSettingCount, and store ODSettingArray > > from > > + * powerplay table to od_settings_max and od_setting_min > > */ > > + od_setting_count = > > + (le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingCount) > > > + ATOM_VEGA20_ODSETTING_COUNT) ? > > + ATOM_VEGA20_ODSETTING_COUNT : > > + le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingCount); > > + > > + od_setting_array_size = sizeof(uint32_t) * od_setting_count; > > + > > + if (od8_settings->od_settings_max) > > + return -EINVAL; > > + > > + od8_settings->od_settings_max = > > kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax, > > + > > od_setting_array_size, > > + GFP_KERNEL); > > + > > + if (!od8_settings->od_settings_max) { > > + kfree(od8_settings->od_feature_capabilities); > > + od8_settings->od_feature_capabilities = NULL; > > + return -ENOMEM; > > + } > > + > > + if (od8_settings->od_settings_min) > > + return -EINVAL; > > + > > + od8_settings->od_settings_min = > > kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin, > > + > > od_setting_array_size, > > + GFP_KERNEL); > > + > > + if (!od8_settings->od_settings_min) { > > + kfree(od8_settings->od_feature_capabilities); > > + od8_settings->od_feature_capabilities = NULL; > > + kfree(od8_settings->od_settings_max); > > + od8_settings->od_settings_max = NULL; > > + return -ENOMEM; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_store_powerplay_table(struct smu_context *smu) > > +{ > > + ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > + struct smu_table_context *table_context = &smu->smu_table; > > + int ret; > > + > > + if (!table_context->power_play_table) > > + return -EINVAL; > > + > > + powerplay_table = table_context->power_play_table; > > + > > + memcpy(table_context->driver_pptable, &powerplay_table- > > >smcPPTable, > > + sizeof(PPTable_t)); > > + > > + table_context->software_shutdown_temp = powerplay_table- > > >usSoftwareShutdownTemp; > > + table_context->thermal_controller_type = powerplay_table- > > >ucThermalControllerType; > > + table_context->TDPODLimit = le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPE > R > > CENTAGE]); > > + > > + ret = vega20_setup_od8_information(smu); > > + > > + return ret; > > +} > > + > > +static int vega20_append_powerplay_table(struct smu_context *smu) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *smc_pptable = table_context->driver_pptable; > > + struct atom_smc_dpm_info_v4_4 *smc_dpm_table; > > + int index, i, ret; > > + > > + index = > > get_index_into_master_table(atom_master_list_of_data_tables_v2_1, > > + smc_dpm_info); > > + > > + ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, > > + (uint8_t **)&smc_dpm_table); > > + if (ret) > > + return ret; > > + > > + smc_pptable->MaxVoltageStepGfx = smc_dpm_table- > > >maxvoltagestepgfx; > > + smc_pptable->MaxVoltageStepSoc = smc_dpm_table- > > >maxvoltagestepsoc; > > + > > + smc_pptable->VddGfxVrMapping = smc_dpm_table- > > >vddgfxvrmapping; > > + smc_pptable->VddSocVrMapping = smc_dpm_table- > > >vddsocvrmapping; > > + smc_pptable->VddMem0VrMapping = smc_dpm_table- > > >vddmem0vrmapping; > > + smc_pptable->VddMem1VrMapping = smc_dpm_table- > > >vddmem1vrmapping; > > + > > + smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table- > > >gfxulvphasesheddingmask; > > + smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table- > > >soculvphasesheddingmask; > > + smc_pptable->ExternalSensorPresent = smc_dpm_table- > > >externalsensorpresent; > > + > > + smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent; > > + smc_pptable->GfxOffset = smc_dpm_table->gfxoffset; > > + smc_pptable->Padding_TelemetryGfx = smc_dpm_table- > > >padding_telemetrygfx; > > + > > + smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent; > > + smc_pptable->SocOffset = smc_dpm_table->socoffset; > > + smc_pptable->Padding_TelemetrySoc = smc_dpm_table- > > >padding_telemetrysoc; > > + > > + smc_pptable->Mem0MaxCurrent = smc_dpm_table- > > >mem0maxcurrent; > > + smc_pptable->Mem0Offset = smc_dpm_table->mem0offset; > > + smc_pptable->Padding_TelemetryMem0 = smc_dpm_table- > > >padding_telemetrymem0; > > + > > + smc_pptable->Mem1MaxCurrent = smc_dpm_table- > > >mem1maxcurrent; > > + smc_pptable->Mem1Offset = smc_dpm_table->mem1offset; > > + smc_pptable->Padding_TelemetryMem1 = smc_dpm_table- > > >padding_telemetrymem1; > > + > > + smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio; > > + smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity; > > + smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio; > > + smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity; > > + > > + smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio; > > + smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity; > > + smc_pptable->Padding1 = smc_dpm_table->padding1; > > + smc_pptable->Padding2 = smc_dpm_table->padding2; > > + > > + smc_pptable->LedPin0 = smc_dpm_table->ledpin0; > > + smc_pptable->LedPin1 = smc_dpm_table->ledpin1; > > + smc_pptable->LedPin2 = smc_dpm_table->ledpin2; > > + > > + smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table- > > >pllgfxclkspreadenabled; > > + smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table- > > >pllgfxclkspreadpercent; > > + smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table- > > >pllgfxclkspreadfreq; > > + > > + smc_pptable->UclkSpreadEnabled = 0; > > + smc_pptable->UclkSpreadPercent = smc_dpm_table- > > >uclkspreadpercent; > > + smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq; > > + > > + smc_pptable->FclkSpreadEnabled = smc_dpm_table- > > >fclkspreadenabled; > > + smc_pptable->FclkSpreadPercent = smc_dpm_table- > > >fclkspreadpercent; > > + smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq; > > + > > + smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table- > > >fllgfxclkspreadenabled; > > + smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table- > > >fllgfxclkspreadpercent; > > + smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table- > > >fllgfxclkspreadfreq; > > + > > + for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { > > + smc_pptable->I2cControllers[i].Enabled = > > + smc_dpm_table->i2ccontrollers[i].enabled; > > + smc_pptable->I2cControllers[i].SlaveAddress = > > + smc_dpm_table->i2ccontrollers[i].slaveaddress; > > + smc_pptable->I2cControllers[i].ControllerPort = > > + smc_dpm_table->i2ccontrollers[i].controllerport; > > + smc_pptable->I2cControllers[i].ThermalThrottler = > > + smc_dpm_table->i2ccontrollers[i].thermalthrottler; > > + smc_pptable->I2cControllers[i].I2cProtocol = > > + smc_dpm_table->i2ccontrollers[i].i2cprotocol; > > + smc_pptable->I2cControllers[i].I2cSpeed = > > + smc_dpm_table->i2ccontrollers[i].i2cspeed; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_check_powerplay_table(struct smu_context *smu) > > +{ > > + ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > + struct smu_table_context *table_context = &smu->smu_table; > > + > > + powerplay_table = table_context->power_play_table; > > + > > + if (powerplay_table->sHeader.format_revision < > > ATOM_VEGA20_TABLE_REVISION_VEGA20) { > > + pr_err("Unsupported PPTable format!"); > > + return -EINVAL; > > + } > > + > > + if (!powerplay_table->sHeader.structuresize) { > > + pr_err("Invalid PowerPlay Table!"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_run_btc_afll(struct smu_context *smu) > > +{ > > + return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc); > > +} > > + > > +#define FEATURE_MASK(feature) (1ULL << feature) > > +static int > > +vega20_get_allowed_feature_mask(struct smu_context *smu, > > + uint32_t *feature_mask, uint32_t num) > > +{ > > + if (num > 2) > > + return -EINVAL; > > + > > + memset(feature_mask, 0, sizeof(uint32_t) * num); > > + > > + *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) > > + | FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) > > + | FEATURE_MASK(FEATURE_DPM_UVD_BIT) > > + | FEATURE_MASK(FEATURE_DPM_VCE_BIT) > > + | FEATURE_MASK(FEATURE_ULV_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) > > + | FEATURE_MASK(FEATURE_DPM_LINK_BIT) > > + | > > FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) > > + | FEATURE_MASK(FEATURE_PPT_BIT) > > + | FEATURE_MASK(FEATURE_TDC_BIT) > > + | FEATURE_MASK(FEATURE_THERMAL_BIT) > > + | > > FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT) > > + | FEATURE_MASK(FEATURE_RM_BIT) > > + | FEATURE_MASK(FEATURE_ACDC_BIT) > > + | FEATURE_MASK(FEATURE_VR0HOT_BIT) > > + | FEATURE_MASK(FEATURE_VR1HOT_BIT) > > + | FEATURE_MASK(FEATURE_FW_CTF_BIT) > > + | > > FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) > > + | > > FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) > > + | FEATURE_MASK(FEATURE_GFX_EDC_BIT) > > + | FEATURE_MASK(FEATURE_GFXOFF_BIT) > > + | FEATURE_MASK(FEATURE_CG_BIT) > > + | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) > > + | FEATURE_MASK(FEATURE_XGMI_BIT); > > + return 0; > > +} > > + > > +static enum > > +amd_pm_state_type vega20_get_current_power_state(struct > > smu_context *smu) > > +{ > > + enum amd_pm_state_type pm_type; > > + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > + > > + if (!smu_dpm_ctx->dpm_context || > > + !smu_dpm_ctx->dpm_current_power_state) > > + return -EINVAL; > > + > > + mutex_lock(&(smu->mutex)); > > + switch (smu_dpm_ctx->dpm_current_power_state- > > >classification.ui_label) { > > + case SMU_STATE_UI_LABEL_BATTERY: > > + pm_type = POWER_STATE_TYPE_BATTERY; > > + break; > > + case SMU_STATE_UI_LABEL_BALLANCED: > > + pm_type = POWER_STATE_TYPE_BALANCED; > > + break; > > + case SMU_STATE_UI_LABEL_PERFORMANCE: > > + pm_type = POWER_STATE_TYPE_PERFORMANCE; > > + break; > > + default: > > + if (smu_dpm_ctx->dpm_current_power_state- > > >classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) > > + pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; > > + else > > + pm_type = POWER_STATE_TYPE_DEFAULT; > > + break; > > + } > > + mutex_unlock(&(smu->mutex)); > > + > > + return pm_type; > > +} > > + > > +static int > > +vega20_set_single_dpm_table(struct smu_context *smu, > > + struct vega20_single_dpm_table > > *single_dpm_table, > > + PPCLK_e clk_id) > > +{ > > + int ret = 0; > > + uint32_t i, num_of_levels = 0, clk; > > + > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_GetDpmFreqByIndex, > > + (clk_id << 16 | 0xFF)); > > + if (ret) { > > + pr_err("[GetNumOfDpmLevel] failed to get dpm levels!"); > > + return ret; > > + } > > + > > + smu_read_smc_arg(smu, &num_of_levels); > > + if (!num_of_levels) { > > + pr_err("[GetNumOfDpmLevel] number of clk levels is > > invalid!"); > > + return -EINVAL; > > + } > > + > > + single_dpm_table->count = num_of_levels; > > + > > + for (i = 0; i < num_of_levels; i++) { > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_GetDpmFreqByIndex, > > + (clk_id << 16 | i)); > > + if (ret) { > > + pr_err("[GetDpmFreqByIndex] failed to get dpm freq > > by index!"); > > + return ret; > > + } > > + smu_read_smc_arg(smu, &clk); > > + if (!clk) { > > + pr_err("[GetDpmFreqByIndex] clk value is invalid!"); > > + return -EINVAL; > > + } > > + single_dpm_table->dpm_levels[i].value = clk; > > + single_dpm_table->dpm_levels[i].enabled = true; > > + } > > + return 0; > > +} > > + > > +static void vega20_init_single_dpm_state(struct vega20_dpm_state > > *dpm_state) > > +{ > > + dpm_state->soft_min_level = 0x0; > > + dpm_state->soft_max_level = 0xffff; > > + dpm_state->hard_min_level = 0x0; > > + dpm_state->hard_max_level = 0xffff; > > +} > > + > > +static int vega20_set_default_dpm_table(struct smu_context *smu) > > +{ > > + int ret; > > + > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_single_dpm_table *single_dpm_table; > > + > > + dpm_table = smu_dpm->dpm_context; > > + > > + /* socclk */ > > + single_dpm_table = &(dpm_table->soc_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_SOCCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get socclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.socclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* gfxclk */ > > + single_dpm_table = &(dpm_table->gfx_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_GFXCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get gfxclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.gfxclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* memclk */ > > + single_dpm_table = &(dpm_table->mem_table); > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_UCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get > > memclk dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.uclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* eclk */ > > + single_dpm_table = &(dpm_table->eclk_table); > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_ECLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get eclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.eclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* vclk */ > > + single_dpm_table = &(dpm_table->vclk_table); > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_VCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get vclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.vclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* dclk */ > > + single_dpm_table = &(dpm_table->dclk_table); > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_DCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get dclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.dclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* dcefclk */ > > + single_dpm_table = &(dpm_table->dcef_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_DCEFCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get dcefclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.dcefclk / 100; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* pixclk */ > > + single_dpm_table = &(dpm_table->pixel_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_PIXCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get pixclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 0; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* dispclk */ > > + single_dpm_table = &(dpm_table->display_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_DISPCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get dispclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 0; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* phyclk */ > > + single_dpm_table = &(dpm_table->phy_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_PHYCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get phyclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 0; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + /* fclk */ > > + single_dpm_table = &(dpm_table->fclk_table); > > + > > + if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + PPCLK_FCLK); > > + if (ret) { > > + pr_err("[SetupDefaultDpmTable] failed to get fclk > > dpm levels!"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 0; > > + } > > + vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > + > > + memcpy(smu_dpm->golden_dpm_context, dpm_table, > > + sizeof(struct vega20_dpm_table)); > > + > > + return 0; > > +} > > + > > +static int vega20_populate_umd_state_clk(struct smu_context *smu) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_single_dpm_table *gfx_table = NULL; > > + struct vega20_single_dpm_table *mem_table = NULL; > > + > > + dpm_table = smu_dpm->dpm_context; > > + gfx_table = &(dpm_table->gfx_table); > > + mem_table = &(dpm_table->mem_table); > > + > > + smu->pstate_sclk = gfx_table->dpm_levels[0].value; > > + smu->pstate_mclk = mem_table->dpm_levels[0].value; > > + > > + if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && > > + mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { > > + smu->pstate_sclk = gfx_table- > > >dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > + smu->pstate_mclk = mem_table- > > >dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > + } > > + > > + smu->pstate_sclk = smu->pstate_sclk * 100; > > + smu->pstate_mclk = smu->pstate_mclk * 100; > > + > > + return 0; > > +} > > + > > +static int vega20_get_clk_table(struct smu_context *smu, > > + struct pp_clock_levels_with_latency *clocks, > > + struct vega20_single_dpm_table *dpm_table) > > +{ > > + int i, count; > > + > > + count = (dpm_table->count > MAX_NUM_CLOCKS) ? > > MAX_NUM_CLOCKS : dpm_table->count; > > + clocks->num_levels = count; > > + > > + for (i = 0; i < count; i++) { > > + clocks->data[i].clocks_in_khz = > > + dpm_table->dpm_levels[i].value * 1000; > > + clocks->data[i].latency_in_us = 0; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_print_clk_levels(struct smu_context *smu, > > + enum smu_clk_type type, char *buf) > > +{ > > + int i, now, size = 0; > > + int ret = 0; > > + uint32_t gen_speed, lane_width; > > + struct amdgpu_device *adev = smu->adev; > > + struct pp_clock_levels_with_latency clocks; > > + struct vega20_single_dpm_table *single_dpm_table; > > + struct smu_table_context *table_context = &smu->smu_table; > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_od8_settings *od8_settings = > > + (struct vega20_od8_settings *)smu->od_settings; > > + OverDriveTable_t *od_table = > > + (OverDriveTable_t *)(table_context->overdrive_table); > > + PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; > > + > > + dpm_table = smu_dpm->dpm_context; > > + > > + switch (type) { > > + case SMU_SCLK: > > + ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now); > > + if (ret) { > > + pr_err("Attempt to get current gfx clk Failed!"); > > + return ret; > > + } > > + > > + single_dpm_table = &(dpm_table->gfx_table); > > + ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get gfx clk levels Failed!"); > > + return ret; > > + } > > + > > + for (i = 0; i < clocks.num_levels; i++) > > + size += sprintf(buf + size, "%d: %uMhz %s\n", i, > > + clocks.data[i].clocks_in_khz / 1000, > > + (clocks.data[i].clocks_in_khz == now > > * 10) > > + ? "*" : ""); > > + break; > > + > > + case SMU_MCLK: > > + ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now); > > + if (ret) { > > + pr_err("Attempt to get current mclk Failed!"); > > + return ret; > > + } > > + > > + single_dpm_table = &(dpm_table->mem_table); > > + ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get memory clk levels Failed!"); > > + return ret; > > + } > > + > > + for (i = 0; i < clocks.num_levels; i++) > > + size += sprintf(buf + size, "%d: %uMhz %s\n", > > + i, clocks.data[i].clocks_in_khz / 1000, > > + (clocks.data[i].clocks_in_khz == now * 10) > > + ? "*" : ""); > > + break; > > + > > + case SMU_SOCCLK: > > + ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, > > &now); > > + if (ret) { > > + pr_err("Attempt to get current socclk Failed!"); > > + return ret; > > + } > > + > > + single_dpm_table = &(dpm_table->soc_table); > > + ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get socclk levels Failed!"); > > + return ret; > > + } > > + > > + for (i = 0; i < clocks.num_levels; i++) > > + size += sprintf(buf + size, "%d: %uMhz %s\n", > > + i, clocks.data[i].clocks_in_khz / 1000, > > + (clocks.data[i].clocks_in_khz == now * 10) > > + ? "*" : ""); > > + break; > > + > > + case SMU_FCLK: > > + ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now); > > + if (ret) { > > + pr_err("Attempt to get current fclk Failed!"); > > + return ret; > > + } > > + > > + single_dpm_table = &(dpm_table->fclk_table); > > + for (i = 0; i < single_dpm_table->count; i++) > > + size += sprintf(buf + size, "%d: %uMhz %s\n", > > + i, single_dpm_table->dpm_levels[i].value, > > + (single_dpm_table->dpm_levels[i].value == > > now / 100) > > + ? "*" : ""); > > + break; > > + > > + case SMU_DCEFCLK: > > + ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, > > &now); > > + if (ret) { > > + pr_err("Attempt to get current dcefclk Failed!"); > > + return ret; > > + } > > + > > + single_dpm_table = &(dpm_table->dcef_table); > > + ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get dcefclk levels Failed!"); > > + return ret; > > + } > > + > > + for (i = 0; i < clocks.num_levels; i++) > > + size += sprintf(buf + size, "%d: %uMhz %s\n", > > + i, clocks.data[i].clocks_in_khz / 1000, > > + (clocks.data[i].clocks_in_khz == now * 10) ? > > "*" : ""); > > + break; > > + > > + case SMU_PCIE: > > + gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & > > + > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) > > + >> > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; > > + lane_width = > > (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & > > + > > PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) > > + >> > > PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; > > + for (i = 0; i < NUM_LINK_LEVELS; i++) > > + size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, > > + (pptable->PcieGenSpeed[i] == 0) ? > > "2.5GT/s," : > > + (pptable->PcieGenSpeed[i] == 1) ? > > "5.0GT/s," : > > + (pptable->PcieGenSpeed[i] == 2) ? > > "8.0GT/s," : > > + (pptable->PcieGenSpeed[i] == 3) ? > > "16.0GT/s," : "", > > + (pptable->PcieLaneCount[i] == 1) ? > > "x1" : > > + (pptable->PcieLaneCount[i] == 2) ? > > "x2" : > > + (pptable->PcieLaneCount[i] == 3) ? > > "x4" : > > + (pptable->PcieLaneCount[i] == 4) ? > > "x8" : > > + (pptable->PcieLaneCount[i] == 5) ? > > "x12" : > > + (pptable->PcieLaneCount[i] == 6) ? > > "x16" : "", > > + pptable->LclkFreq[i], > > + (gen_speed == pptable- > > >PcieGenSpeed[i]) && > > + (lane_width == pptable- > > >PcieLaneCount[i]) ? > > + "*" : ""); > > + break; > > + > > + case SMU_OD_SCLK: > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { > > + size = sprintf(buf, "%s:\n", "OD_SCLK"); > > + size += sprintf(buf + size, "0: %10uMhz\n", > > + od_table->GfxclkFmin); > > + size += sprintf(buf + size, "1: %10uMhz\n", > > + od_table->GfxclkFmax); > > + } > > + > > + break; > > + > > + case SMU_OD_MCLK: > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > + size = sprintf(buf, "%s:\n", "OD_MCLK"); > > + size += sprintf(buf + size, "1: %10uMhz\n", > > + od_table->UclkFmax); > > + } > > + > > + break; > > + > > + case SMU_OD_VDDC_CURVE: > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { > > + size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); > > + size += sprintf(buf + size, "0: %10uMhz %10dmV\n", > > + od_table->GfxclkFreq1, > > + od_table->GfxclkVolt1 / > > VOLTAGE_SCALE); > > + size += sprintf(buf + size, "1: %10uMhz %10dmV\n", > > + od_table->GfxclkFreq2, > > + od_table->GfxclkVolt2 / > > VOLTAGE_SCALE); > > + size += sprintf(buf + size, "2: %10uMhz %10dmV\n", > > + od_table->GfxclkFreq3, > > + od_table->GfxclkVolt3 / > > VOLTAGE_SCALE); > > + } > > + > > + break; > > + > > + case SMU_OD_RANGE: > > + size = sprintf(buf, "%s:\n", "OD_RANGE"); > > + > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { > > + size += sprintf(buf + size, > > "SCLK: %7uMhz %10uMhz\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); > > + } > > + > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > + single_dpm_table = &(dpm_table->mem_table); > > + ret = vega20_get_clk_table(smu, &clocks, > > single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get memory clk levels > > Failed!"); > > + return ret; > > + } > > + > > + size += sprintf(buf + size, > > "MCLK: %7uMhz %10uMhz\n", > > + clocks.data[0].clocks_in_khz / 1000, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); > > + } > > + > > + if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { > > + size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value); > > + size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); > > + size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value); > > + size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); > > + size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value); > > + size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); > > + } > > + > > + break; > > + > > + default: > > + break; > > + } > > + return size; > > +} > > + > > +static int vega20_upload_dpm_level(struct smu_context *smu, bool max, > > + uint32_t feature_mask) > > +{ > > + struct vega20_dpm_table *dpm_table; > > + struct vega20_single_dpm_table *single_dpm_table; > > + uint32_t freq; > > + int ret = 0; > > + > > + dpm_table = smu->smu_dpm.dpm_context; > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) > > && > > + (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { > > + single_dpm_table = &(dpm_table->gfx_table); > > + freq = max ? single_dpm_table->dpm_state.soft_max_level : > > + single_dpm_table->dpm_state.soft_min_level; > > + ret = smu_send_smc_msg_with_param(smu, > > + (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > + (PPCLK_GFXCLK << 16) | (freq & 0xffff)); > > + if (ret) { > > + pr_err("Failed to set soft %s gfxclk !\n", > > + max ? "max" : "min"); > > + return ret; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) > > && > > + (feature_mask & FEATURE_DPM_UCLK_MASK)) { > > + single_dpm_table = &(dpm_table->mem_table); > > + freq = max ? single_dpm_table->dpm_state.soft_max_level : > > + single_dpm_table->dpm_state.soft_min_level; > > + ret = smu_send_smc_msg_with_param(smu, > > + (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > + (PPCLK_UCLK << 16) | (freq & 0xffff)); > > + if (ret) { > > + pr_err("Failed to set soft %s memclk !\n", > > + max ? "max" : "min"); > > + return ret; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) > > && > > + (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { > > + single_dpm_table = &(dpm_table->soc_table); > > + freq = max ? single_dpm_table->dpm_state.soft_max_level : > > + single_dpm_table->dpm_state.soft_min_level; > > + ret = smu_send_smc_msg_with_param(smu, > > + (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > + (PPCLK_SOCCLK << 16) | (freq & 0xffff)); > > + if (ret) { > > + pr_err("Failed to set soft %s socclk !\n", > > + max ? "max" : "min"); > > + return ret; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) > > && > > + (feature_mask & FEATURE_DPM_FCLK_MASK)) { > > + single_dpm_table = &(dpm_table->fclk_table); > > + freq = max ? single_dpm_table->dpm_state.soft_max_level : > > + single_dpm_table->dpm_state.soft_min_level; > > + ret = smu_send_smc_msg_with_param(smu, > > + (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > + (PPCLK_FCLK << 16) | (freq & 0xffff)); > > + if (ret) { > > + pr_err("Failed to set soft %s fclk !\n", > > + max ? "max" : "min"); > > + return ret; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > + (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { > > + single_dpm_table = &(dpm_table->dcef_table); > > + freq = single_dpm_table->dpm_state.hard_min_level; > > + if (!max) { > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_SetHardMinByFreq, > > + (PPCLK_DCEFCLK << 16) | (freq & 0xffff)); > > + if (ret) { > > + pr_err("Failed to set hard min dcefclk !\n"); > > + return ret; > > + } > > + } > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_force_clk_levels(struct smu_context *smu, > > + enum smu_clk_type clk_type, uint32_t mask) > > +{ > > + struct vega20_dpm_table *dpm_table; > > + struct vega20_single_dpm_table *single_dpm_table; > > + uint32_t soft_min_level, soft_max_level, hard_min_level; > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + int ret = 0; > > + > > + if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { > > + pr_info("force clock level is for dpm manual mode only.\n"); > > + return -EINVAL; > > + } > > + > > + mutex_lock(&(smu->mutex)); > > + > > + soft_min_level = mask ? (ffs(mask) - 1) : 0; > > + soft_max_level = mask ? (fls(mask) - 1) : 0; > > + > > + dpm_table = smu->smu_dpm.dpm_context; > > + > > + switch (clk_type) { > > + case SMU_SCLK: > > + single_dpm_table = &(dpm_table->gfx_table); > > + > > + if (soft_max_level >= single_dpm_table->count) { > > + pr_err("Clock level specified %d is over max > > allowed %d\n", > > + soft_max_level, single_dpm_table- > > >count - 1); > > + ret = -EINVAL; > > + break; > > + } > > + > > + single_dpm_table->dpm_state.soft_min_level = > > + single_dpm_table- > > >dpm_levels[soft_min_level].value; > > + single_dpm_table->dpm_state.soft_max_level = > > + single_dpm_table- > > >dpm_levels[soft_max_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_GFXCLK_MASK); > > + if (ret) { > > + pr_err("Failed to upload boot level to lowest!\n"); > > + break; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_GFXCLK_MASK); > > + if (ret) > > + pr_err("Failed to upload dpm max level to > > highest!\n"); > > + > > + break; > > + > > + case SMU_MCLK: > > + single_dpm_table = &(dpm_table->mem_table); > > + > > + if (soft_max_level >= single_dpm_table->count) { > > + pr_err("Clock level specified %d is over max > > allowed %d\n", > > + soft_max_level, single_dpm_table- > > >count - 1); > > + ret = -EINVAL; > > + break; > > + } > > + > > + single_dpm_table->dpm_state.soft_min_level = > > + single_dpm_table- > > >dpm_levels[soft_min_level].value; > > + single_dpm_table->dpm_state.soft_max_level = > > + single_dpm_table- > > >dpm_levels[soft_max_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_UCLK_MASK); > > + if (ret) { > > + pr_err("Failed to upload boot level to lowest!\n"); > > + break; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_UCLK_MASK); > > + if (ret) > > + pr_err("Failed to upload dpm max level to > > highest!\n"); > > + > > + break; > > + > > + case SMU_SOCCLK: > > + single_dpm_table = &(dpm_table->soc_table); > > + > > + if (soft_max_level >= single_dpm_table->count) { > > + pr_err("Clock level specified %d is over max > > allowed %d\n", > > + soft_max_level, single_dpm_table- > > >count - 1); > > + ret = -EINVAL; > > + break; > > + } > > + > > + single_dpm_table->dpm_state.soft_min_level = > > + single_dpm_table- > > >dpm_levels[soft_min_level].value; > > + single_dpm_table->dpm_state.soft_max_level = > > + single_dpm_table- > > >dpm_levels[soft_max_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_SOCCLK_MASK); > > + if (ret) { > > + pr_err("Failed to upload boot level to lowest!\n"); > > + break; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_SOCCLK_MASK); > > + if (ret) > > + pr_err("Failed to upload dpm max level to > > highest!\n"); > > + > > + break; > > + > > + case SMU_FCLK: > > + single_dpm_table = &(dpm_table->fclk_table); > > + > > + if (soft_max_level >= single_dpm_table->count) { > > + pr_err("Clock level specified %d is over max > > allowed %d\n", > > + soft_max_level, single_dpm_table- > > >count - 1); > > + ret = -EINVAL; > > + break; > > + } > > + > > + single_dpm_table->dpm_state.soft_min_level = > > + single_dpm_table- > > >dpm_levels[soft_min_level].value; > > + single_dpm_table->dpm_state.soft_max_level = > > + single_dpm_table- > > >dpm_levels[soft_max_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_FCLK_MASK); > > + if (ret) { > > + pr_err("Failed to upload boot level to lowest!\n"); > > + break; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_FCLK_MASK); > > + if (ret) > > + pr_err("Failed to upload dpm max level to > > highest!\n"); > > + > > + break; > > + > > + case SMU_DCEFCLK: > > + hard_min_level = soft_min_level; > > + single_dpm_table = &(dpm_table->dcef_table); > > + > > + if (hard_min_level >= single_dpm_table->count) { > > + pr_err("Clock level specified %d is over max > > allowed %d\n", > > + hard_min_level, single_dpm_table- > > >count - 1); > > + ret = -EINVAL; > > + break; > > + } > > + > > + single_dpm_table->dpm_state.hard_min_level = > > + single_dpm_table- > > >dpm_levels[hard_min_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_DCEFCLK_MASK); > > + if (ret) > > + pr_err("Failed to upload boot level to lowest!\n"); > > + > > + break; > > + > > + case SMU_PCIE: > > + if (soft_min_level >= NUM_LINK_LEVELS || > > + soft_max_level >= NUM_LINK_LEVELS) { > > + ret = -EINVAL; > > + break; > > + } > > + > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_SetMinLinkDpmByIndex, > > soft_min_level); > > + if (ret) > > + pr_err("Failed to set min link dpm level!\n"); > > + > > + break; > > + > > + default: > > + break; > > + } > > + > > + mutex_unlock(&(smu->mutex)); > > + return ret; > > +} > > + > > +static int vega20_get_clock_by_type_with_latency(struct smu_context > > *smu, > > + enum smu_clk_type > > clk_type, > > + struct > > pp_clock_levels_with_latency *clocks) > > +{ > > + int ret; > > + struct vega20_single_dpm_table *single_dpm_table; > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + > > + dpm_table = smu_dpm->dpm_context; > > + > > + mutex_lock(&smu->mutex); > > + > > + switch (clk_type) { > > + case SMU_GFXCLK: > > + single_dpm_table = &(dpm_table->gfx_table); > > + ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > + break; > > + case SMU_MCLK: > > + single_dpm_table = &(dpm_table->mem_table); > > + ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > + break; > > + case SMU_DCEFCLK: > > + single_dpm_table = &(dpm_table->dcef_table); > > + ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > + break; > > + case SMU_SOCCLK: > > + single_dpm_table = &(dpm_table->soc_table); > > + ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > + break; > > + default: > > + ret = -EINVAL; > > + } > > + > > + mutex_unlock(&smu->mutex); > > + return ret; > > +} > > + > > +static int vega20_overdrive_get_gfx_clk_base_voltage(struct > smu_context > > *smu, > > + uint32_t *voltage, > > + uint32_t freq) > > +{ > > + int ret; > > + > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_GetAVFSVoltageByDpm, > > + ((AVFS_CURVE << 24) | > > (OD8_HOTCURVE_TEMPERATURE << 16) | freq)); > > + if (ret) { > > + pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage > > from SMU!"); > > + return ret; > > + } > > + > > + smu_read_smc_arg(smu, voltage); > > + *voltage = *voltage / VOLTAGE_SCALE; > > + > > + return 0; > > +} > > + > > +static int vega20_set_default_od8_setttings(struct smu_context *smu) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context- > > >overdrive_table); > > + struct vega20_od8_settings *od8_settings = NULL; > > + PPTable_t *smc_pptable = table_context->driver_pptable; > > + int i, ret; > > + > > + if (smu->od_settings) > > + return -EINVAL; > > + > > + od8_settings = kzalloc(sizeof(struct vega20_od8_settings), > > GFP_KERNEL); > > + > > + if (od8_settings) > > + return -ENOMEM; > > + > > + smu->od_settings = (void *)od8_settings; > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] > && > > + od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && > > + od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_FMIN])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = > > + OD8_GFXCLK_LIMITS; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = > > + OD8_GFXCLK_LIMITS; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = > > + od_table->GfxclkFmin; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = > > + od_table->GfxclkFmax; > > + } > > + > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] > && > > + (od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= > > + smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= > > + smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) && > > + (od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <= > > + od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = > > + OD8_GFXCLK_CURVE; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = > > + OD8_GFXCLK_CURVE; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = > > + OD8_GFXCLK_CURVE; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = > > + OD8_GFXCLK_CURVE; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = > > + OD8_GFXCLK_CURVE; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = > > + OD8_GFXCLK_CURVE; > > + > > + od_table->GfxclkFreq1 = od_table->GfxclkFmin; > > + od_table->GfxclkFreq2 = (od_table->GfxclkFmin + > > od_table->GfxclkFmax) / 2; > > + od_table->GfxclkFreq3 = od_table->GfxclkFmax; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = > > + od_table->GfxclkFreq1; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = > > + od_table->GfxclkFreq2; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = > > + od_table->GfxclkFreq3; > > + > > + ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > + &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value, > > + od_table->GfxclkFreq1); > > + if (ret) > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = > 0; > > + od_table->GfxclkVolt1 = > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value > > + * VOLTAGE_SCALE; > > + ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > + &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value, > > + od_table->GfxclkFreq2); > > + if (ret) > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = > 0; > > + od_table->GfxclkVolt2 = > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value > > + * VOLTAGE_SCALE; > > + ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > + &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value, > > + od_table->GfxclkFreq3); > > + if (ret) > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = > 0; > > + od_table->GfxclkVolt3 = > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value > > + * VOLTAGE_SCALE; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && > > + od8_settings- > > >od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_UCLK_FMAX] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_UCLK_FMAX])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = > > + OD8_UCLK_MAX; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = > > + od_table->UclkFmax; > > + } > > + } > > + > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] > && > > + od8_settings- > > >od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && > > + od8_settings- > > >od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = > > + OD8_POWER_LIMIT; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value > = > > + od_table->OverDrivePct; > > + } > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_FAN_CONTROL_BIT)) { > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LI > > MIT] && > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = > > + OD8_ACOUSTIC_LIMIT_SCLK; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value > = > > + od_table->FanMaximumRpm; > > + } > > + > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] > > && > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = > > + OD8_FAN_SPEED_MIN; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = > > + od_table->FanMinimumPwm * smc_pptable- > > >FanMaximumRpm / 100; > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) { > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FA > N] > > && > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = > > + OD8_TEMPERATURE_FAN; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = > > + od_table->FanTargetTemperature; > > + } > > + > > + if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SY > S > > TEM] && > > + od8_settings- > > >od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && > > + od8_settings- > > >od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && > > + (od8_settings- > > >od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= > > + od8_settings- > > >od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) { > > + od8_settings- > > >od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id > = > > + OD8_TEMPERATURE_SYSTEM; > > + od8_settings- > > >od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_val > u > > e = > > + od_table->MaxOpTemp; > > + } > > + } > > + > > + for (i = 0; i < OD8_SETTING_COUNT; i++) { > > + if (od8_settings->od8_settings_array[i].feature_id) { > > + od8_settings->od8_settings_array[i].min_value = > > + od8_settings->od_settings_min[i]; > > + od8_settings->od8_settings_array[i].max_value = > > + od8_settings->od_settings_max[i]; > > + od8_settings->od8_settings_array[i].current_value = > > + od8_settings- > > >od8_settings_array[i].default_value; > > + } else { > > + od8_settings->od8_settings_array[i].min_value = 0; > > + od8_settings->od8_settings_array[i].max_value = 0; > > + od8_settings->od8_settings_array[i].current_value = > > 0; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_get_metrics_table(struct smu_context *smu, > > + SmuMetrics_t *metrics_table) > > +{ > > + struct smu_table_context *smu_table= &smu->smu_table; > > + int ret = 0; > > + > > + if (!smu_table->metrics_time || time_after(jiffies, smu_table- > > >metrics_time + HZ / 1000)) { > > + ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > + (void *)smu_table->metrics_table, false); > > + if (ret) { > > + pr_info("Failed to export SMU metrics table!\n"); > > + return ret; > > + } > > + smu_table->metrics_time = jiffies; > > + } > > + > > + memcpy(metrics_table, smu_table->metrics_table, > > sizeof(SmuMetrics_t)); > > + > > + return ret; > > +} > > + > > +static int vega20_set_default_od_settings(struct smu_context *smu, > > + bool initialize) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + int ret; > > + > > + if (initialize) { > > + if (table_context->overdrive_table) > > + return -EINVAL; > > + > > + table_context->overdrive_table = > > kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL); > > + > > + if (!table_context->overdrive_table) > > + return -ENOMEM; > > + > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > + table_context->overdrive_table, false); > > + if (ret) { > > + pr_err("Failed to export over drive table!\n"); > > + return ret; > > + } > > + > > + ret = vega20_set_default_od8_setttings(smu); > > + if (ret) > > + return ret; > > + } > > + > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > + table_context->overdrive_table, true); > > + if (ret) { > > + pr_err("Failed to import over drive table!\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_get_od_percentage(struct smu_context *smu, > > + enum smu_clk_type clk_type) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_dpm_table *golden_table = NULL; > > + struct vega20_single_dpm_table *single_dpm_table; > > + struct vega20_single_dpm_table *golden_dpm_table; > > + int value, golden_value; > > + > > + dpm_table = smu_dpm->dpm_context; > > + golden_table = smu_dpm->golden_dpm_context; > > + > > + switch (clk_type) { > > + case SMU_OD_SCLK: > > + single_dpm_table = &(dpm_table->gfx_table); > > + golden_dpm_table = &(golden_table->gfx_table); > > + break; > > + case SMU_OD_MCLK: > > + single_dpm_table = &(dpm_table->mem_table); > > + golden_dpm_table = &(golden_table->mem_table); > > + break; > > + default: > > + return -EINVAL; > > + break; > > + } > > + > > + value = single_dpm_table->dpm_levels[single_dpm_table->count - > > 1].value; > > + golden_value = golden_dpm_table- > > >dpm_levels[golden_dpm_table->count - 1].value; > > + > > + value -= golden_value; > > + value = DIV_ROUND_UP(value * 100, golden_value); > > + > > + return value; > > +} > > + > > +static int vega20_get_power_profile_mode(struct smu_context *smu, > char > > *buf) > > +{ > > + DpmActivityMonitorCoeffInt_t activity_monitor; > > + uint32_t i, size = 0; > > + uint16_t workload_type = 0; > > + static const char *profile_name[] = { > > + "BOOTUP_DEFAULT", > > + "3D_FULL_SCREEN", > > + "POWER_SAVING", > > + "VIDEO", > > + "VR", > > + "COMPUTE", > > + "CUSTOM"}; > > + static const char *title[] = { > > + "PROFILE_INDEX(NAME)", > > + "CLOCK_TYPE(NAME)", > > + "FPS", > > + "UseRlcBusy", > > + "MinActiveFreqType", > > + "MinActiveFreq", > > + "BoosterFreqType", > > + "BoosterFreq", > > + "PD_Data_limit_c", > > + "PD_Data_error_coeff", > > + "PD_Data_error_rate_coeff"}; > > + int result = 0; > > + > > + if (!smu->pm_enabled || !buf) > > + return -EINVAL; > > + > > + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", > > + title[0], title[1], title[2], title[3], title[4], title[5], > > + title[6], title[7], title[8], title[9], title[10]); > > + > > + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { > > + /* conv PP_SMC_POWER_PROFILE* to > > WORKLOAD_PPLIB_*_BIT */ > > + workload_type = smu_workload_get_type(smu, i); > > + result = smu_update_table(smu, > > + > > SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16, > > + (void *)(&activity_monitor), false); > > + if (result) { > > + pr_err("[%s] Failed to get activity monitor!", > > __func__); > > + return result; > > + } > > + > > + size += sprintf(buf + size, "%2d %14s%s:\n", > > + i, profile_name[i], (i == smu->power_profile_mode) ? > > "*" : " "); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 0, > > + "GFXCLK", > > + activity_monitor.Gfx_FPS, > > + activity_monitor.Gfx_UseRlcBusy, > > + activity_monitor.Gfx_MinActiveFreqType, > > + activity_monitor.Gfx_MinActiveFreq, > > + activity_monitor.Gfx_BoosterFreqType, > > + activity_monitor.Gfx_BoosterFreq, > > + activity_monitor.Gfx_PD_Data_limit_c, > > + activity_monitor.Gfx_PD_Data_error_coeff, > > + activity_monitor.Gfx_PD_Data_error_rate_coeff); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 1, > > + "SOCCLK", > > + activity_monitor.Soc_FPS, > > + activity_monitor.Soc_UseRlcBusy, > > + activity_monitor.Soc_MinActiveFreqType, > > + activity_monitor.Soc_MinActiveFreq, > > + activity_monitor.Soc_BoosterFreqType, > > + activity_monitor.Soc_BoosterFreq, > > + activity_monitor.Soc_PD_Data_limit_c, > > + activity_monitor.Soc_PD_Data_error_coeff, > > + activity_monitor.Soc_PD_Data_error_rate_coeff); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 2, > > + "UCLK", > > + activity_monitor.Mem_FPS, > > + activity_monitor.Mem_UseRlcBusy, > > + activity_monitor.Mem_MinActiveFreqType, > > + activity_monitor.Mem_MinActiveFreq, > > + activity_monitor.Mem_BoosterFreqType, > > + activity_monitor.Mem_BoosterFreq, > > + activity_monitor.Mem_PD_Data_limit_c, > > + activity_monitor.Mem_PD_Data_error_coeff, > > + activity_monitor.Mem_PD_Data_error_rate_coeff); > > + > > + size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > + " ", > > + 3, > > + "FCLK", > > + activity_monitor.Fclk_FPS, > > + activity_monitor.Fclk_UseRlcBusy, > > + activity_monitor.Fclk_MinActiveFreqType, > > + activity_monitor.Fclk_MinActiveFreq, > > + activity_monitor.Fclk_BoosterFreqType, > > + activity_monitor.Fclk_BoosterFreq, > > + activity_monitor.Fclk_PD_Data_limit_c, > > + activity_monitor.Fclk_PD_Data_error_coeff, > > + activity_monitor.Fclk_PD_Data_error_rate_coeff); > > + } > > + > > + return size; > > +} > > + > > +static int vega20_set_power_profile_mode(struct smu_context *smu, > long > > *input, uint32_t size) > > +{ > > + DpmActivityMonitorCoeffInt_t activity_monitor; > > + int workload_type = 0, ret = 0; > > + > > + smu->power_profile_mode = input[size]; > > + > > + if (!smu->pm_enabled) > > + return ret; > > + if (smu->power_profile_mode > > > PP_SMC_POWER_PROFILE_CUSTOM) { > > + pr_err("Invalid power profile mode %d\n", smu- > > >power_profile_mode); > > + return -EINVAL; > > + } > > + > > + if (smu->power_profile_mode == > > PP_SMC_POWER_PROFILE_CUSTOM) { > > + ret = smu_update_table(smu, > > + SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > + (void *)(&activity_monitor), false); > > + if (ret) { > > + pr_err("[%s] Failed to get activity monitor!", > > __func__); > > + return ret; > > + } > > + > > + switch (input[0]) { > > + case 0: /* Gfxclk */ > > + activity_monitor.Gfx_FPS = input[1]; > > + activity_monitor.Gfx_UseRlcBusy = input[2]; > > + activity_monitor.Gfx_MinActiveFreqType = input[3]; > > + activity_monitor.Gfx_MinActiveFreq = input[4]; > > + activity_monitor.Gfx_BoosterFreqType = input[5]; > > + activity_monitor.Gfx_BoosterFreq = input[6]; > > + activity_monitor.Gfx_PD_Data_limit_c = input[7]; > > + activity_monitor.Gfx_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Gfx_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + case 1: /* Socclk */ > > + activity_monitor.Soc_FPS = input[1]; > > + activity_monitor.Soc_UseRlcBusy = input[2]; > > + activity_monitor.Soc_MinActiveFreqType = input[3]; > > + activity_monitor.Soc_MinActiveFreq = input[4]; > > + activity_monitor.Soc_BoosterFreqType = input[5]; > > + activity_monitor.Soc_BoosterFreq = input[6]; > > + activity_monitor.Soc_PD_Data_limit_c = input[7]; > > + activity_monitor.Soc_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Soc_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + case 2: /* Uclk */ > > + activity_monitor.Mem_FPS = input[1]; > > + activity_monitor.Mem_UseRlcBusy = input[2]; > > + activity_monitor.Mem_MinActiveFreqType = > > input[3]; > > + activity_monitor.Mem_MinActiveFreq = input[4]; > > + activity_monitor.Mem_BoosterFreqType = input[5]; > > + activity_monitor.Mem_BoosterFreq = input[6]; > > + activity_monitor.Mem_PD_Data_limit_c = input[7]; > > + activity_monitor.Mem_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Mem_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + case 3: /* Fclk */ > > + activity_monitor.Fclk_FPS = input[1]; > > + activity_monitor.Fclk_UseRlcBusy = input[2]; > > + activity_monitor.Fclk_MinActiveFreqType = input[3]; > > + activity_monitor.Fclk_MinActiveFreq = input[4]; > > + activity_monitor.Fclk_BoosterFreqType = input[5]; > > + activity_monitor.Fclk_BoosterFreq = input[6]; > > + activity_monitor.Fclk_PD_Data_limit_c = input[7]; > > + activity_monitor.Fclk_PD_Data_error_coeff = > > input[8]; > > + activity_monitor.Fclk_PD_Data_error_rate_coeff = > > input[9]; > > + break; > > + } > > + > > + ret = smu_update_table(smu, > > + SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > + (void *)(&activity_monitor), true); > > + if (ret) { > > + pr_err("[%s] Failed to set activity monitor!", > > __func__); > > + return ret; > > + } > > + } > > + > > + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ > > + workload_type = smu_workload_get_type(smu, smu- > > >power_profile_mode); > > + smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetWorkloadMask, > > + 1 << workload_type); > > + > > + return ret; > > +} > > + > > +static int > > +vega20_get_profiling_clk_mask(struct smu_context *smu, > > + enum amd_dpm_forced_level level, > > + uint32_t *sclk_mask, > > + uint32_t *mclk_mask, > > + uint32_t *soc_mask) > > +{ > > + struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table > > *)smu->smu_dpm.dpm_context; > > + struct vega20_single_dpm_table *gfx_dpm_table; > > + struct vega20_single_dpm_table *mem_dpm_table; > > + struct vega20_single_dpm_table *soc_dpm_table; > > + > > + if (!smu->smu_dpm.dpm_context) > > + return -EINVAL; > > + > > + gfx_dpm_table = &dpm_table->gfx_table; > > + mem_dpm_table = &dpm_table->mem_table; > > + soc_dpm_table = &dpm_table->soc_table; > > + > > + *sclk_mask = 0; > > + *mclk_mask = 0; > > + *soc_mask = 0; > > + > > + if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL > > && > > + mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL > > && > > + soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { > > + *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; > > + *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; > > + *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; > > + } > > + > > + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > + *sclk_mask = 0; > > + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > + *mclk_mask = 0; > > + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + *sclk_mask = gfx_dpm_table->count - 1; > > + *mclk_mask = mem_dpm_table->count - 1; > > + *soc_mask = soc_dpm_table->count - 1; > > + } > > + > > + return 0; > > +} > > + > > +static int > > +vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu, > > + struct vega20_single_dpm_table > > *dpm_table) > > +{ > > + int ret = 0; > > + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > + if (!smu_dpm_ctx->dpm_context) > > + return -EINVAL; > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + if (dpm_table->count <= 0) { > > + pr_err("[%s] Dpm table has no entry!", __func__); > > + return -EINVAL; > > + } > > + > > + if (dpm_table->count > NUM_UCLK_DPM_LEVELS) { > > + pr_err("[%s] Dpm table has too many entries!", > > __func__); > > + return -EINVAL; > > + } > > + > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + ret = smu_send_smc_msg_with_param(smu, > > + SMU_MSG_SetHardMinByFreq, > > + (PPCLK_UCLK << 16) | dpm_table- > > >dpm_state.hard_min_level); > > + if (ret) { > > + pr_err("[%s] Set hard min uclk failed!", __func__); > > + return ret; > > + } > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_pre_display_config_changed(struct smu_context *smu) > > +{ > > + int ret = 0; > > + struct vega20_dpm_table *dpm_table = smu- > > >smu_dpm.dpm_context; > > + > > + if (!smu->smu_dpm.dpm_context) > > + return -EINVAL; > > + > > + smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, > > 0); > > + ret = vega20_set_uclk_to_highest_dpm_level(smu, > > + &dpm_table->mem_table); > > + if (ret) > > + pr_err("Failed to set uclk to highest dpm level"); > > + return ret; > > +} > > + > > +static int vega20_display_config_changed(struct smu_context *smu) > > +{ > > + int ret = 0; > > + > > + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { > > + ret = smu_write_watermarks_table(smu); > > + if (ret) { > > + pr_err("Failed to update WMTABLE!"); > > + return ret; > > + } > > + smu->watermarks_bitmap |= WATERMARKS_LOADED; > > + } > > + > > + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > + smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > + smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > + smu_send_smc_msg_with_param(smu, > > + SMU_MSG_NumOfDisplays, > > + smu->display_config- > > >num_display); > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_apply_clocks_adjust_rules(struct smu_context *smu) > > +{ > > + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > + struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table > > *)(smu_dpm_ctx->dpm_context); > > + struct vega20_single_dpm_table *dpm_table; > > + bool vblank_too_short = false; > > + bool disable_mclk_switching; > > + uint32_t i, latency; > > + > > + disable_mclk_switching = ((1 < smu->display_config->num_display) > > && > > + !smu->display_config- > > >multi_monitor_in_sync) || vblank_too_short; > > + latency = smu->display_config- > > >dce_tolerable_mclk_in_active_latency; > > + > > + /* gfxclk */ > > + dpm_table = &(dpm_ctx->gfx_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table- > > >count) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[0].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + > > + /* memclk */ > > + dpm_table = &(dpm_ctx->mem_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) > > { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[0].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + > > + /* honour DAL's UCLK Hardmin */ > > + if (dpm_table->dpm_state.hard_min_level < (smu->display_config- > > >min_mem_set_clock / 100)) > > + dpm_table->dpm_state.hard_min_level = smu- > > >display_config->min_mem_set_clock / 100; > > + > > + /* Hardmin is dependent on displayconfig */ > > + if (disable_mclk_switching) { > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; > > i++) { > > + if (smu_dpm_ctx->mclk_latency_table- > > >entries[i].latency <= latency) { > > + if (dpm_table->dpm_levels[i].value >= (smu- > > >display_config->min_mem_set_clock / 100)) { > > + dpm_table- > > >dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; > > + break; > > + } > > + } > > + } > > + } > > + > > + if (smu->display_config->nb_pstate_switch_disable) > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + /* vclk */ > > + dpm_table = &(dpm_ctx->vclk_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table- > > >count) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + > > + /* dclk */ > > + dpm_table = &(dpm_ctx->dclk_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table- > > >count) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + > > + /* socclk */ > > + dpm_table = &(dpm_ctx->soc_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table- > > >count) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + > > + /* eclk */ > > + dpm_table = &(dpm_ctx->eclk_table); > > + dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > + dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > + > > + if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table- > > >count) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; > > + } > > + > > + if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > + dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > + } > > + return 0; > > +} > > + > > +static int > > +vega20_notify_smc_dispaly_config(struct smu_context *smu) > > +{ > > + struct vega20_dpm_table *dpm_table = smu- > > >smu_dpm.dpm_context; > > + struct vega20_single_dpm_table *memtable = &dpm_table- > > >mem_table; > > + struct smu_clocks min_clocks = {0}; > > + struct pp_display_clock_request clock_req; > > + int ret = 0; > > + > > + min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; > > + min_clocks.dcef_clock_in_sr = smu->display_config- > > >min_dcef_deep_sleep_set_clk; > > + min_clocks.memory_clock = smu->display_config- > > >min_mem_set_clock; > > + > > + if (smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > + clock_req.clock_type = amd_pp_dcef_clock; > > + clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; > > + if (!smu->funcs->display_clock_voltage_request(smu, > > &clock_req)) { > > + if (smu_feature_is_supported(smu, > > SMU_FEATURE_DS_DCEFCLK_BIT)) { > > + ret = smu_send_smc_msg_with_param(smu, > > + > > SMU_MSG_SetMinDeepSleepDcefclk, > > + > > min_clocks.dcef_clock_in_sr/100); > > + if (ret) { > > + pr_err("Attempt to set divider for > > DCEFCLK Failed!"); > > + return ret; > > + } > > + } > > + } else { > > + pr_info("Attempt to set Hard Min for DCEFCLK > > Failed!"); > > + } > > + } > > + > > + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > + memtable->dpm_state.hard_min_level = > > min_clocks.memory_clock/100; > > + ret = smu_send_smc_msg_with_param(smu, > > + > > SMU_MSG_SetHardMinByFreq, > > + (PPCLK_UCLK << 16) | > > memtable->dpm_state.hard_min_level); > > + if (ret) { > > + pr_err("[%s] Set hard min uclk failed!", __func__); > > + return ret; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static uint32_t vega20_find_lowest_dpm_level(struct > > vega20_single_dpm_table *table) > > +{ > > + uint32_t i; > > + > > + for (i = 0; i < table->count; i++) { > > + if (table->dpm_levels[i].enabled) > > + break; > > + } > > + if (i >= table->count) { > > + i = 0; > > + table->dpm_levels[i].enabled = true; > > + } > > + > > + return i; > > +} > > + > > +static uint32_t vega20_find_highest_dpm_level(struct > > vega20_single_dpm_table *table) > > +{ > > + int i = 0; > > + > > + if (!table) { > > + pr_err("[%s] DPM Table does not exist!", __func__); > > + return 0; > > + } > > + if (table->count <= 0) { > > + pr_err("[%s] DPM Table has no entry!", __func__); > > + return 0; > > + } > > + if (table->count > MAX_REGULAR_DPM_NUMBER) { > > + pr_err("[%s] DPM Table has too many entries!", __func__); > > + return MAX_REGULAR_DPM_NUMBER - 1; > > + } > > + > > + for (i = table->count - 1; i >= 0; i--) { > > + if (table->dpm_levels[i].enabled) > > + break; > > + } > > + if (i < 0) { > > + i = 0; > > + table->dpm_levels[i].enabled = true; > > + } > > + > > + return i; > > +} > > + > > +static int vega20_force_dpm_limit_value(struct smu_context *smu, bool > > highest) > > +{ > > + uint32_t soft_level; > > + int ret = 0; > > + struct vega20_dpm_table *dpm_table = > > + (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; > > + > > + if (highest) > > + soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >gfx_table)); > > + else > > + soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >gfx_table)); > > + > > + dpm_table->gfx_table.dpm_state.soft_min_level = > > + dpm_table->gfx_table.dpm_state.soft_max_level = > > + dpm_table->gfx_table.dpm_levels[soft_level].value; > > + > > + if (highest) > > + soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >mem_table)); > > + else > > + soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >mem_table)); > > + > > + dpm_table->mem_table.dpm_state.soft_min_level = > > + dpm_table->mem_table.dpm_state.soft_max_level = > > + dpm_table->mem_table.dpm_levels[soft_level].value; > > + > > + if (highest) > > + soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >soc_table)); > > + else > > + soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >soc_table)); > > + > > + dpm_table->soc_table.dpm_state.soft_min_level = > > + dpm_table->soc_table.dpm_state.soft_max_level = > > + dpm_table->soc_table.dpm_levels[soft_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); > > + if (ret) { > > + pr_err("Failed to upload boot level to %s!\n", > > + highest ? "highest" : "lowest"); > > + return ret; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); > > + if (ret) { > > + pr_err("Failed to upload dpm max level to %s!\n!", > > + highest ? "highest" : "lowest"); > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_unforce_dpm_levels(struct smu_context *smu) > > +{ > > + uint32_t soft_min_level, soft_max_level; > > + int ret = 0; > > + struct vega20_dpm_table *dpm_table = > > + (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; > > + > > + soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >gfx_table)); > > + soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >gfx_table)); > > + dpm_table->gfx_table.dpm_state.soft_min_level = > > + dpm_table->gfx_table.dpm_levels[soft_min_level].value; > > + dpm_table->gfx_table.dpm_state.soft_max_level = > > + dpm_table->gfx_table.dpm_levels[soft_max_level].value; > > + > > + soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >mem_table)); > > + soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >mem_table)); > > + dpm_table->mem_table.dpm_state.soft_min_level = > > + dpm_table->gfx_table.dpm_levels[soft_min_level].value; > > + dpm_table->mem_table.dpm_state.soft_max_level = > > + dpm_table->gfx_table.dpm_levels[soft_max_level].value; > > + > > + soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >soc_table)); > > + soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >soc_table)); > > + dpm_table->soc_table.dpm_state.soft_min_level = > > + dpm_table->soc_table.dpm_levels[soft_min_level].value; > > + dpm_table->soc_table.dpm_state.soft_max_level = > > + dpm_table->soc_table.dpm_levels[soft_max_level].value; > > + > > + ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); > > + if (ret) { > > + pr_err("Failed to upload DPM Bootup Levels!"); > > + return ret; > > + } > > + > > + ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); > > + if (ret) { > > + pr_err("Failed to upload DPM Max Levels!"); > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_update_specified_od8_value(struct smu_context *smu, > > + uint32_t index, > > + uint32_t value) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + OverDriveTable_t *od_table = > > + (OverDriveTable_t *)(table_context->overdrive_table); > > + struct vega20_od8_settings *od8_settings = > > + (struct vega20_od8_settings *)smu->od_settings; > > + > > + switch (index) { > > + case OD8_SETTING_GFXCLK_FMIN: > > + od_table->GfxclkFmin = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_FMAX: > > + if (value < od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value || > > + value > od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) > > + return -EINVAL; > > + od_table->GfxclkFmax = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_FREQ1: > > + od_table->GfxclkFreq1 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_VOLTAGE1: > > + od_table->GfxclkVolt1 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_FREQ2: > > + od_table->GfxclkFreq2 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_VOLTAGE2: > > + od_table->GfxclkVolt2 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_FREQ3: > > + od_table->GfxclkFreq3 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_GFXCLK_VOLTAGE3: > > + od_table->GfxclkVolt3 = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_UCLK_FMAX: > > + if (value < od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value || > > + value > od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) > > + return -EINVAL; > > + od_table->UclkFmax = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_POWER_PERCENTAGE: > > + od_table->OverDrivePct = (int16_t)value; > > + break; > > + > > + case OD8_SETTING_FAN_ACOUSTIC_LIMIT: > > + od_table->FanMaximumRpm = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_FAN_MIN_SPEED: > > + od_table->FanMinimumPwm = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_FAN_TARGET_TEMP: > > + od_table->FanTargetTemperature = (uint16_t)value; > > + break; > > + > > + case OD8_SETTING_OPERATING_TEMP_MAX: > > + od_table->MaxOpTemp = (uint16_t)value; > > + break; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_update_od8_settings(struct smu_context *smu, > > + uint32_t index, > > + uint32_t value) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + int ret; > > + > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > + table_context->overdrive_table, false); > > + if (ret) { > > + pr_err("Failed to export over drive table!\n"); > > + return ret; > > + } > > + > > + ret = vega20_update_specified_od8_value(smu, index, value); > > + if (ret) > > + return ret; > > + > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > + table_context->overdrive_table, true); > > + if (ret) { > > + pr_err("Failed to import over drive table!\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_set_od_percentage(struct smu_context *smu, > > + enum smu_clk_type clk_type, > > + uint32_t value) > > +{ > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_dpm_table *golden_table = NULL; > > + struct vega20_single_dpm_table *single_dpm_table; > > + struct vega20_single_dpm_table *golden_dpm_table; > > + uint32_t od_clk, index; > > + int ret = 0; > > + int feature_enabled; > > + PPCLK_e clk_id; > > + > > + mutex_lock(&(smu->mutex)); > > + > > + dpm_table = smu_dpm->dpm_context; > > + golden_table = smu_dpm->golden_dpm_context; > > + > > + switch (clk_type) { > > + case SMU_OD_SCLK: > > + single_dpm_table = &(dpm_table->gfx_table); > > + golden_dpm_table = &(golden_table->gfx_table); > > + feature_enabled = smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT); > > + clk_id = PPCLK_GFXCLK; > > + index = OD8_SETTING_GFXCLK_FMAX; > > + break; > > + case SMU_OD_MCLK: > > + single_dpm_table = &(dpm_table->mem_table); > > + golden_dpm_table = &(golden_table->mem_table); > > + feature_enabled = smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UCLK_BIT); > > + clk_id = PPCLK_UCLK; > > + index = OD8_SETTING_UCLK_FMAX; > > + break; > > + default: > > + ret = -EINVAL; > > + break; > > + } > > + > > + if (ret) > > + goto set_od_failed; > > + > > + od_clk = golden_dpm_table->dpm_levels[golden_dpm_table- > > >count - 1].value * value; > > + od_clk /= 100; > > + od_clk += golden_dpm_table->dpm_levels[golden_dpm_table- > > >count - 1].value; > > + > > + ret = vega20_update_od8_settings(smu, index, od_clk); > > + if (ret) { > > + pr_err("[Setoverdrive] failed to set od clk!\n"); > > + goto set_od_failed; > > + } > > + > > + if (feature_enabled) { > > + ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > + clk_id); > > + if (ret) { > > + pr_err("[Setoverdrive] failed to refresh dpm > > table!\n"); > > + goto set_od_failed; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.gfxclk / 100; > > + } > > + > > + ret = smu_handle_task(smu, smu_dpm->dpm_level, > > + AMD_PP_TASK_READJUST_POWER_STATE); > > + > > +set_od_failed: > > + mutex_unlock(&(smu->mutex)); > > + > > + return ret; > > +} > > + > > +static int vega20_odn_edit_dpm_table(struct smu_context *smu, > > + enum PP_OD_DPM_TABLE_COMMAND > > type, > > + long *input, uint32_t size) > > +{ > > + struct smu_table_context *table_context = &smu->smu_table; > > + OverDriveTable_t *od_table = > > + (OverDriveTable_t *)(table_context->overdrive_table); > > + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > + struct vega20_dpm_table *dpm_table = NULL; > > + struct vega20_single_dpm_table *single_dpm_table; > > + struct vega20_od8_settings *od8_settings = > > + (struct vega20_od8_settings *)smu->od_settings; > > + struct pp_clock_levels_with_latency clocks; > > + int32_t input_index, input_clk, input_vol, i; > > + int od8_id; > > + int ret = 0; > > + > > + dpm_table = smu_dpm->dpm_context; > > + > > + if (!input) { > > + pr_warn("NULL user input for clock and voltage\n"); > > + return -EINVAL; > > + } > > + > > + switch (type) { > > + case PP_OD_EDIT_SCLK_VDDC_TABLE: > > + if (!(od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) { > > + pr_info("Sclk min/max frequency overdrive not > > supported\n"); > > + return -EOPNOTSUPP; > > + } > > + > > + for (i = 0; i < size; i += 2) { > > + if (i + 2 > size) { > > + pr_info("invalid number of input > > parameters %d\n", size); > > + return -EINVAL; > > + } > > + > > + input_index = input[i]; > > + input_clk = input[i + 1]; > > + > > + if (input_index != 0 && input_index != 1) { > > + pr_info("Invalid index %d\n", input_index); > > + pr_info("Support min/max sclk frequency > > settingonly which index by 0/1\n"); > > + return -EINVAL; > > + } > > + > > + if (input_clk < od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value || > > + input_clk > od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) { > > + pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > + input_clk, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); > > + return -EINVAL; > > + } > > + > > + if (input_index == 0 && od_table->GfxclkFmin != > > input_clk) { > > + od_table->GfxclkFmin = input_clk; > > + od8_settings->od_gfxclk_update = true; > > + } else if (input_index == 1 && od_table- > > >GfxclkFmax != input_clk) { > > + od_table->GfxclkFmax = input_clk; > > + od8_settings->od_gfxclk_update = true; > > + } > > + } > > + > > + break; > > + > > + case PP_OD_EDIT_MCLK_VDDC_TABLE: > > + if (!od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > + pr_info("Mclk max frequency overdrive not > > supported\n"); > > + return -EOPNOTSUPP; > > + } > > + > > + single_dpm_table = &(dpm_table->mem_table); > > + ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > + if (ret) { > > + pr_err("Attempt to get memory clk levels Failed!"); > > + return ret; > > + } > > + > > + for (i = 0; i < size; i += 2) { > > + if (i + 2 > size) { > > + pr_info("invalid number of input > > parameters %d\n", > > + size); > > + return -EINVAL; > > + } > > + > > + input_index = input[i]; > > + input_clk = input[i + 1]; > > + > > + if (input_index != 1) { > > + pr_info("Invalid index %d\n", input_index); > > + pr_info("Support max Mclk frequency setting > > only which index by 1\n"); > > + return -EINVAL; > > + } > > + > > + if (input_clk < clocks.data[0].clocks_in_khz / 1000 || > > + input_clk > od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) { > > + pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > + input_clk, > > + clocks.data[0].clocks_in_khz / 1000, > > + od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); > > + return -EINVAL; > > + } > > + > > + if (input_index == 1 && od_table->UclkFmax != > > input_clk) { > > + od8_settings->od_gfxclk_update = true; > > + od_table->UclkFmax = input_clk; > > + } > > + } > > + > > + break; > > + > > + case PP_OD_EDIT_VDDC_CURVE: > > + if (!(od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > + od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { > > + pr_info("Voltage curve calibrate not supported\n"); > > + return -EOPNOTSUPP; > > + } > > + > > + for (i = 0; i < size; i += 3) { > > + if (i + 3 > size) { > > + pr_info("invalid number of input > > parameters %d\n", > > + size); > > + return -EINVAL; > > + } > > + > > + input_index = input[i]; > > + input_clk = input[i + 1]; > > + input_vol = input[i + 2]; > > + > > + if (input_index > 2) { > > + pr_info("Setting for point %d is not > > supported\n", > > + input_index + 1); > > + pr_info("Three supported points index by 0, > > 1, 2\n"); > > + return -EINVAL; > > + } > > + > > + od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * > > input_index; > > + if (input_clk < od8_settings- > > >od8_settings_array[od8_id].min_value || > > + input_clk > od8_settings- > > >od8_settings_array[od8_id].max_value) { > > + pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > + input_clk, > > + od8_settings- > > >od8_settings_array[od8_id].min_value, > > + od8_settings- > > >od8_settings_array[od8_id].max_value); > > + return -EINVAL; > > + } > > + > > + od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * > > input_index; > > + if (input_vol < od8_settings- > > >od8_settings_array[od8_id].min_value || > > + input_vol > od8_settings- > > >od8_settings_array[od8_id].max_value) { > > + pr_info("clock voltage %d is not within > > allowed range [%d- %d]\n", > > + input_vol, > > + od8_settings- > > >od8_settings_array[od8_id].min_value, > > + od8_settings- > > >od8_settings_array[od8_id].max_value); > > + return -EINVAL; > > + } > > + > > + switch (input_index) { > > + case 0: > > + od_table->GfxclkFreq1 = input_clk; > > + od_table->GfxclkVolt1 = input_vol * > > VOLTAGE_SCALE; > > + break; > > + case 1: > > + od_table->GfxclkFreq2 = input_clk; > > + od_table->GfxclkVolt2 = input_vol * > > VOLTAGE_SCALE; > > + break; > > + case 2: > > + od_table->GfxclkFreq3 = input_clk; > > + od_table->GfxclkVolt3 = input_vol * > > VOLTAGE_SCALE; > > + break; > > + } > > + } > > + > > + break; > > + > > + case PP_OD_RESTORE_DEFAULT_TABLE: > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > table_context->overdrive_table, false); > > + if (ret) { > > + pr_err("Failed to export over drive table!\n"); > > + return ret; > > + } > > + > > + break; > > + > > + case PP_OD_COMMIT_DPM_TABLE: > > + ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > table_context->overdrive_table, true); > > + if (ret) { > > + pr_err("Failed to import over drive table!\n"); > > + return ret; > > + } > > + > > + /* retrieve updated gfxclk table */ > > + if (od8_settings->od_gfxclk_update) { > > + od8_settings->od_gfxclk_update = false; > > + single_dpm_table = &(dpm_table->gfx_table); > > + > > + if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT)) { > > + ret = vega20_set_single_dpm_table(smu, > > single_dpm_table, > > + > > PPCLK_GFXCLK); > > + if (ret) { > > + pr_err("[Setoverdrive] failed to > > refresh dpm table!\n"); > > + return ret; > > + } > > + } else { > > + single_dpm_table->count = 1; > > + single_dpm_table->dpm_levels[0].value = > > smu->smu_table.boot_values.gfxclk / 100; > > + } > > + } > > + > > + break; > > + > > + default: > > + return -EINVAL; > > + } > > + > > + if (type == PP_OD_COMMIT_DPM_TABLE) { > > + mutex_lock(&(smu->mutex)); > > + ret = smu_handle_task(smu, smu_dpm->dpm_level, > > + > > AMD_PP_TASK_READJUST_POWER_STATE); > > + mutex_unlock(&(smu->mutex)); > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool > > enable) > > +{ > > + if (!smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_UVD_BIT)) > > + return 0; > > + > > + if (enable == smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) > > + return 0; > > + > > + return smu_feature_set_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT, enable); > > +} > > + > > +static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool > > enable) > > +{ > > + if (!smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_VCE_BIT)) > > + return 0; > > + > > + if (enable == smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_VCE_BIT)) > > + return 0; > > + > > + return smu_feature_set_enabled(smu, > > SMU_FEATURE_DPM_VCE_BIT, enable); > > +} > > + > > +static int vega20_get_enabled_smc_features(struct smu_context *smu, > > + uint64_t *features_enabled) > > +{ > > + uint32_t feature_mask[2] = {0, 0}; > > + int ret = 0; > > + > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + if (ret) > > + return ret; > > + > > + *features_enabled = ((((uint64_t)feature_mask[0] << > > SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | > > + (((uint64_t)feature_mask[1] << > > SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); > > + > > + return ret; > > +} > > + > > +static int vega20_enable_smc_features(struct smu_context *smu, > > + bool enable, uint64_t feature_mask) > > +{ > > + uint32_t smu_features_low, smu_features_high; > > + int ret = 0; > > + > > + smu_features_low = (uint32_t)((feature_mask & > > SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); > > + smu_features_high = (uint32_t)((feature_mask & > > SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); > > + > > + if (enable) { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesLow, > > + smu_features_low); > > + if (ret) > > + return ret; > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesHigh, > > + smu_features_high); > > + if (ret) > > + return ret; > > + } else { > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesLow, > > + smu_features_low); > > + if (ret) > > + return ret; > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesHigh, > > + smu_features_high); > > + if (ret) > > + return ret; > > + } > > + > > + return 0; > > + > > +} > > + > > +static int vega20_get_ppfeature_status(struct smu_context *smu, char > > *buf) > > +{ > > + static const char *ppfeature_name[] = { > > + "DPM_PREFETCHER", > > + "GFXCLK_DPM", > > + "UCLK_DPM", > > + "SOCCLK_DPM", > > + "UVD_DPM", > > + "VCE_DPM", > > + "ULV", > > + "MP0CLK_DPM", > > + "LINK_DPM", > > + "DCEFCLK_DPM", > > + "GFXCLK_DS", > > + "SOCCLK_DS", > > + "LCLK_DS", > > + "PPT", > > + "TDC", > > + "THERMAL", > > + "GFX_PER_CU_CG", > > + "RM", > > + "DCEFCLK_DS", > > + "ACDC", > > + "VR0HOT", > > + "VR1HOT", > > + "FW_CTF", > > + "LED_DISPLAY", > > + "FAN_CONTROL", > > + "GFX_EDC", > > + "GFXOFF", > > + "CG", > > + "FCLK_DPM", > > + "FCLK_DS", > > + "MP1CLK_DS", > > + "MP0CLK_DS", > > + "XGMI", > > + "ECC"}; > > + static const char *output_title[] = { > > + "FEATURES", > > + "BITMASK", > > + "ENABLEMENT"}; > > + uint64_t features_enabled; > > + int i; > > + int ret = 0; > > + int size = 0; > > + > > + ret = vega20_get_enabled_smc_features(smu, &features_enabled); > > + if (ret) > > + return ret; > > + > > + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", > > features_enabled); > > + size += sprintf(buf + size, "%-19s %-22s %s\n", > > + output_title[0], > > + output_title[1], > > + output_title[2]); > > + for (i = 0; i < GNLD_FEATURES_MAX; i++) { > > + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", > > + ppfeature_name[i], > > + 1ULL << i, > > + (features_enabled & (1ULL << i)) ? > > "Y" : "N"); > > + } > > + > > + return size; > > +} > > + > > +static int vega20_set_ppfeature_status(struct smu_context *smu, > uint64_t > > new_ppfeature_masks) > > +{ > > + uint64_t features_enabled; > > + uint64_t features_to_enable; > > + uint64_t features_to_disable; > > + int ret = 0; > > + > > + if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) > > + return -EINVAL; > > + > > + ret = vega20_get_enabled_smc_features(smu, &features_enabled); > > + if (ret) > > + return ret; > > + > > + features_to_disable = > > + features_enabled & ~new_ppfeature_masks; > > + features_to_enable = > > + ~features_enabled & new_ppfeature_masks; > > + > > + pr_debug("features_to_disable 0x%llx\n", features_to_disable); > > + pr_debug("features_to_enable 0x%llx\n", features_to_enable); > > + > > + if (features_to_disable) { > > + ret = vega20_enable_smc_features(smu, false, > > features_to_disable); > > + if (ret) > > + return ret; > > + } > > + > > + if (features_to_enable) { > > + ret = vega20_enable_smc_features(smu, true, > > features_to_enable); > > + if (ret) > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static bool vega20_is_dpm_running(struct smu_context *smu) > > +{ > > + int ret = 0; > > + uint32_t feature_mask[2]; > > + unsigned long feature_enabled; > > + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > + feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | > > + ((uint64_t)feature_mask[1] << 32)); > > + return !!(feature_enabled & SMC_DPM_FEATURE); > > +} > > + > > +static int vega20_set_thermal_fan_table(struct smu_context *smu) > > +{ > > + int ret; > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *pptable = table_context->driver_pptable; > > + > > + ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetFanTemperatureTarget, > > + (uint32_t)pptable->FanTargetTemperature); > > + > > + return ret; > > +} > > + > > +static int vega20_get_fan_speed_percent(struct smu_context *smu, > > + uint32_t *speed) > > +{ > > + int ret = 0; > > + uint32_t percent = 0; > > + uint32_t current_rpm; > > + PPTable_t *pptable = smu->smu_table.driver_pptable; > > + > > + ret = smu_get_current_rpm(smu, ¤t_rpm); > > + percent = current_rpm * 100 / pptable->FanMaximumRpm; > > + *speed = percent > 100 ? 100 : percent; > > + > > + return ret; > > +} > > + > > +static int vega20_get_gpu_power(struct smu_context *smu, uint32_t > > *value) > > +{ > > + int ret = 0; > > + SmuMetrics_t metrics; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = vega20_get_metrics_table(smu, &metrics); > > + if (ret) > > + return ret; > > + > > + *value = metrics.CurrSocketPower << 8; > > + > > + return 0; > > +} > > + > > +static int vega20_get_current_activity_percent(struct smu_context *smu, > > + enum amd_pp_sensors sensor, > > + uint32_t *value) > > +{ > > + int ret = 0; > > + SmuMetrics_t metrics; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = vega20_get_metrics_table(smu, &metrics); > > + if (ret) > > + return ret; > > + > > + switch (sensor) { > > + case AMDGPU_PP_SENSOR_GPU_LOAD: > > + *value = metrics.AverageGfxActivity; > > + break; > > + case AMDGPU_PP_SENSOR_MEM_LOAD: > > + *value = metrics.AverageUclkActivity; > > + break; > > + default: > > + pr_err("Invalid sensor for retrieving clock activity\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int vega20_thermal_get_temperature(struct smu_context *smu, > > + enum amd_pp_sensors sensor, > > + uint32_t *value) > > +{ > > + struct amdgpu_device *adev = smu->adev; > > + SmuMetrics_t metrics; > > + uint32_t temp = 0; > > + int ret = 0; > > + > > + if (!value) > > + return -EINVAL; > > + > > + ret = vega20_get_metrics_table(smu, &metrics); > > + if (ret) > > + return ret; > > + > > + switch (sensor) { > > + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: > > + temp = RREG32_SOC15(THM, 0, > > mmCG_MULT_THERMAL_STATUS); > > + temp = (temp & > > CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> > > + > > CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; > > + > > + temp = temp & 0x1ff; > > + temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + > > + *value = temp; > > + break; > > + case AMDGPU_PP_SENSOR_EDGE_TEMP: > > + *value = metrics.TemperatureEdge * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + break; > > + case AMDGPU_PP_SENSOR_MEM_TEMP: > > + *value = metrics.TemperatureHBM * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + break; > > + default: > > + pr_err("Invalid sensor for retrieving temp\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > +static int vega20_read_sensor(struct smu_context *smu, > > + enum amd_pp_sensors sensor, > > + void *data, uint32_t *size) > > +{ > > + int ret = 0; > > + struct smu_table_context *table_context = &smu->smu_table; > > + PPTable_t *pptable = table_context->driver_pptable; > > + > > + switch (sensor) { > > + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: > > + *(uint32_t *)data = pptable->FanMaximumRpm; > > + *size = 4; > > + break; > > + case AMDGPU_PP_SENSOR_MEM_LOAD: > > + case AMDGPU_PP_SENSOR_GPU_LOAD: > > + ret = vega20_get_current_activity_percent(smu, > > + sensor, > > + (uint32_t *)data); > > + *size = 4; > > + break; > > + case AMDGPU_PP_SENSOR_GPU_POWER: > > + ret = vega20_get_gpu_power(smu, (uint32_t *)data); > > + *size = 4; > > + break; > > + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: > > + case AMDGPU_PP_SENSOR_EDGE_TEMP: > > + case AMDGPU_PP_SENSOR_MEM_TEMP: > > + ret = vega20_thermal_get_temperature(smu, sensor, > > (uint32_t *)data); > > + *size = 4; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + return ret; > > +} > > + > > +static int vega20_set_watermarks_table(struct smu_context *smu, > > + void *watermarks, struct > > + > > dm_pp_wm_sets_with_clock_ranges_soc15 > > + *clock_ranges) > > +{ > > + int i; > > + Watermarks_t *table = watermarks; > > + > > + if (!table || !clock_ranges) > > + return -EINVAL; > > + > > + if (clock_ranges->num_wm_dmif_sets > 4 || > > + clock_ranges->num_wm_mcif_sets > 4) > > + return -EINVAL; > > + > > + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { > > + table->WatermarkRow[1][i].MinClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MaxClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MinUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].MaxUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[1][i].WmSetting = (uint8_t) > > + clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_set_id; > > + } > > + > > + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { > > + table->WatermarkRow[0][i].MinClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MaxClock = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MinUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].MaxUclk = > > + cpu_to_le16((uint16_t) > > + (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > + 1000)); > > + table->WatermarkRow[0][i].WmSetting = (uint8_t) > > + clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_set_id; > > + } > > + > > + return 0; > > +} > > + > > +static const struct smu_temperature_range vega20_thermal_policy[] = > > +{ > > + {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, > > + { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, > > 120000}, > > +}; > > + > > +static int vega20_get_thermal_temperature_range(struct smu_context > > *smu, > > + struct > > smu_temperature_range*range) > > +{ > > + > > + PPTable_t *pptable = smu->smu_table.driver_pptable; > > + > > + if (!range) > > + return -EINVAL; > > + > > + memcpy(range, &vega20_thermal_policy[0], sizeof(struct > > smu_temperature_range)); > > + > > + range->max = pptable->TedgeLimit * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + range->edge_emergency_max = (pptable->TedgeLimit + > > CTF_OFFSET_EDGE) * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + range->hotspot_crit_max = pptable->ThotspotLimit * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + range->hotspot_emergency_max = (pptable->ThotspotLimit + > > CTF_OFFSET_HOTSPOT) * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + range->mem_crit_max = pptable->ThbmLimit * > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + range->mem_emergency_max = (pptable->ThbmLimit + > > CTF_OFFSET_HBM)* > > + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > + > > + > > + return 0; > > +} > > + > > +static const struct pptable_funcs vega20_ppt_funcs = { > > + .tables_init = vega20_tables_init, > > + .alloc_dpm_context = vega20_allocate_dpm_context, > > + .store_powerplay_table = vega20_store_powerplay_table, > > + .check_powerplay_table = vega20_check_powerplay_table, > > + .append_powerplay_table = vega20_append_powerplay_table, > > + .get_smu_msg_index = vega20_get_smu_msg_index, > > + .get_smu_clk_index = vega20_get_smu_clk_index, > > + .get_smu_feature_index = vega20_get_smu_feature_index, > > + .get_smu_table_index = vega20_get_smu_table_index, > > + .get_smu_power_index = vega20_get_pwr_src_index, > > + .get_workload_type = vega20_get_workload_type, > > + .run_afll_btc = vega20_run_btc_afll, > > + .get_allowed_feature_mask = vega20_get_allowed_feature_mask, > > + .get_current_power_state = vega20_get_current_power_state, > > + .set_default_dpm_table = vega20_set_default_dpm_table, > > + .set_power_state = NULL, > > + .populate_umd_state_clk = vega20_populate_umd_state_clk, > > + .print_clk_levels = vega20_print_clk_levels, > > + .force_clk_levels = vega20_force_clk_levels, > > + .get_clock_by_type_with_latency = > > vega20_get_clock_by_type_with_latency, > > + .get_od_percentage = vega20_get_od_percentage, > > + .get_power_profile_mode = vega20_get_power_profile_mode, > > + .set_power_profile_mode = vega20_set_power_profile_mode, > > + .set_od_percentage = vega20_set_od_percentage, > > + .set_default_od_settings = vega20_set_default_od_settings, > > + .od_edit_dpm_table = vega20_odn_edit_dpm_table, > > + .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable, > > + .dpm_set_vce_enable = vega20_dpm_set_vce_enable, > > + .read_sensor = vega20_read_sensor, > > + .pre_display_config_changed = vega20_pre_display_config_changed, > > + .display_config_changed = vega20_display_config_changed, > > + .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, > > + .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config, > > + .force_dpm_limit_value = vega20_force_dpm_limit_value, > > + .unforce_dpm_levels = vega20_unforce_dpm_levels, > > + .get_profiling_clk_mask = vega20_get_profiling_clk_mask, > > + .set_ppfeature_status = vega20_set_ppfeature_status, > > + .get_ppfeature_status = vega20_get_ppfeature_status, > > + .is_dpm_running = vega20_is_dpm_running, > > + .set_thermal_fan_table = vega20_set_thermal_fan_table, > > + .get_fan_speed_percent = vega20_get_fan_speed_percent, > > + .set_watermarks_table = vega20_set_watermarks_table, > > + .get_thermal_temperature_range = > > vega20_get_thermal_temperature_range > > +}; > > + > > +void vega20_set_ppt_funcs(struct smu_context *smu) > > +{ > > + struct smu_table_context *smu_table = &smu->smu_table; > > + > > + smu->ppt_funcs = &vega20_ppt_funcs; > > + smu->smc_if_version = SMU11_DRIVER_IF_VERSION; > > + smu_table->table_count = TABLE_COUNT; > > +} > > diff --git a/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.h > > b/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.h > > new file mode 100644 > > index 0000000..2dc10e4 > > --- /dev/null > > +++ b/drivers/gpu/drm/amd/powerplay/pptable/vega20_ppt.h > > @@ -0,0 +1,179 @@ > > +/* > > + * Copyright 2019 Advanced Micro Devices, Inc. > > + * > > + * Permission is hereby granted, free of charge, to any person obtaining a > > + * copy of this software and associated documentation files (the > > "Software"), > > + * to deal in the Software without restriction, including without limitation > > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > + * and/or sell copies of the Software, and to permit persons to whom the > > + * Software is furnished to do so, subject to the following conditions: > > + * > > + * The above copyright notice and this permission notice shall be included > in > > + * all copies or substantial portions of the Software. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > NO > > EVENT SHALL > > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > + * OTHER DEALINGS IN THE SOFTWARE. > > + * > > + */ > > +#ifndef __VEGA20_PPT_H__ > > +#define __VEGA20_PPT_H__ > > + > > +#define VEGA20_UMD_PSTATE_GFXCLK_LEVEL 0x3 > > +#define VEGA20_UMD_PSTATE_SOCCLK_LEVEL 0x3 > > +#define VEGA20_UMD_PSTATE_MCLK_LEVEL 0x2 > > +#define VEGA20_UMD_PSTATE_UVDCLK_LEVEL 0x3 > > +#define VEGA20_UMD_PSTATE_VCEMCLK_LEVEL 0x3 > > + > > +#define MAX_REGULAR_DPM_NUMBER 16 > > +#define MAX_PCIE_CONF 2 > > + > > +#define VOLTAGE_SCALE 4 > > +#define AVFS_CURVE 0 > > +#define OD8_HOTCURVE_TEMPERATURE 85 > > + > > +#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF > > +#define SMU_FEATURES_LOW_SHIFT 0 > > +#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 > > +#define SMU_FEATURES_HIGH_SHIFT 32 > > + > > +enum { > > + GNLD_DPM_PREFETCHER = 0, > > + GNLD_DPM_GFXCLK, > > + GNLD_DPM_UCLK, > > + GNLD_DPM_SOCCLK, > > + GNLD_DPM_UVD, > > + GNLD_DPM_VCE, > > + GNLD_ULV, > > + GNLD_DPM_MP0CLK, > > + GNLD_DPM_LINK, > > + GNLD_DPM_DCEFCLK, > > + GNLD_DS_GFXCLK, > > + GNLD_DS_SOCCLK, > > + GNLD_DS_LCLK, > > + GNLD_PPT, > > + GNLD_TDC, > > + GNLD_THERMAL, > > + GNLD_GFX_PER_CU_CG, > > + GNLD_RM, > > + GNLD_DS_DCEFCLK, > > + GNLD_ACDC, > > + GNLD_VR0HOT, > > + GNLD_VR1HOT, > > + GNLD_FW_CTF, > > + GNLD_LED_DISPLAY, > > + GNLD_FAN_CONTROL, > > + GNLD_DIDT, > > + GNLD_GFXOFF, > > + GNLD_CG, > > + GNLD_DPM_FCLK, > > + GNLD_DS_FCLK, > > + GNLD_DS_MP1CLK, > > + GNLD_DS_MP0CLK, > > + GNLD_XGMI, > > + GNLD_ECC, > > + > > + GNLD_FEATURES_MAX > > +}; > > + > > +struct vega20_dpm_level { > > + bool enabled; > > + uint32_t value; > > + uint32_t param1; > > +}; > > + > > +struct vega20_dpm_state { > > + uint32_t soft_min_level; > > + uint32_t soft_max_level; > > + uint32_t hard_min_level; > > + uint32_t hard_max_level; > > +}; > > + > > +struct vega20_single_dpm_table { > > + uint32_t count; > > + struct vega20_dpm_state dpm_state; > > + struct vega20_dpm_level > dpm_levels[MAX_REGULAR_DPM_NUMBER]; > > +}; > > + > > +struct vega20_pcie_table { > > + uint16_t count; > > + uint8_t pcie_gen[MAX_PCIE_CONF]; > > + uint8_t pcie_lane[MAX_PCIE_CONF]; > > + uint32_t lclk[MAX_PCIE_CONF]; > > +}; > > + > > +struct vega20_dpm_table { > > + struct vega20_single_dpm_table soc_table; > > + struct vega20_single_dpm_table gfx_table; > > + struct vega20_single_dpm_table mem_table; > > + struct vega20_single_dpm_table eclk_table; > > + struct vega20_single_dpm_table vclk_table; > > + struct vega20_single_dpm_table dclk_table; > > + struct vega20_single_dpm_table dcef_table; > > + struct vega20_single_dpm_table pixel_table; > > + struct vega20_single_dpm_table display_table; > > + struct vega20_single_dpm_table phy_table; > > + struct vega20_single_dpm_table fclk_table; > > + struct vega20_pcie_table pcie_table; > > +}; > > + > > +enum OD8_FEATURE_ID > > +{ > > + OD8_GFXCLK_LIMITS = 1 << 0, > > + OD8_GFXCLK_CURVE = 1 << 1, > > + OD8_UCLK_MAX = 1 << 2, > > + OD8_POWER_LIMIT = 1 << 3, > > + OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm > > + OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm > > + OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature > > + OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp > > + OD8_MEMORY_TIMING_TUNE = 1 << 8, > > + OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 > > +}; > > + > > +enum OD8_SETTING_ID > > +{ > > + OD8_SETTING_GFXCLK_FMIN = 0, > > + OD8_SETTING_GFXCLK_FMAX, > > + OD8_SETTING_GFXCLK_FREQ1, > > + OD8_SETTING_GFXCLK_VOLTAGE1, > > + OD8_SETTING_GFXCLK_FREQ2, > > + OD8_SETTING_GFXCLK_VOLTAGE2, > > + OD8_SETTING_GFXCLK_FREQ3, > > + OD8_SETTING_GFXCLK_VOLTAGE3, > > + OD8_SETTING_UCLK_FMAX, > > + OD8_SETTING_POWER_PERCENTAGE, > > + OD8_SETTING_FAN_ACOUSTIC_LIMIT, > > + OD8_SETTING_FAN_MIN_SPEED, > > + OD8_SETTING_FAN_TARGET_TEMP, > > + OD8_SETTING_OPERATING_TEMP_MAX, > > + OD8_SETTING_AC_TIMING, > > + OD8_SETTING_FAN_ZERO_RPM_CONTROL, > > + OD8_SETTING_COUNT > > +}; > > + > > +struct vega20_od8_single_setting { > > + uint32_t feature_id; > > + int32_t min_value; > > + int32_t max_value; > > + int32_t current_value; > > + int32_t default_value; > > +}; > > + > > +struct vega20_od8_settings { > > + struct vega20_od8_single_setting > > od8_settings_array[OD8_SETTING_COUNT]; > > + uint8_t *od_feature_capabilities; > > + uint32_t *od_settings_max; > > + uint32_t *od_settings_min; > > + void *od8_settings; > > + bool od_gfxclk_update; > > + bool od_memclk_update; > > +}; > > + > > +extern void vega20_set_ppt_funcs(struct smu_context *smu); > > + > > +#endif > > diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c > > b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c > > deleted file mode 100644 > > index 9a535f7..0000000 > > --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c > > +++ /dev/null > > @@ -1,3302 +0,0 @@ > > -/* > > - * Copyright 2019 Advanced Micro Devices, Inc. > > - * > > - * Permission is hereby granted, free of charge, to any person obtaining a > > - * copy of this software and associated documentation files (the > "Software"), > > - * to deal in the Software without restriction, including without limitation > > - * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > - * and/or sell copies of the Software, and to permit persons to whom the > > - * Software is furnished to do so, subject to the following conditions: > > - * > > - * The above copyright notice and this permission notice shall be included > in > > - * all copies or substantial portions of the Software. > > - * > > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO > > EVENT SHALL > > - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > - * OTHER DEALINGS IN THE SOFTWARE. > > - * > > - */ > > - > > -#include "pp_debug.h" > > -#include <linux/firmware.h> > > -#include "amdgpu.h" > > -#include "amdgpu_smu.h" > > -#include "atomfirmware.h" > > -#include "amdgpu_atomfirmware.h" > > -#include "smu_v11_0.h" > > -#include "smu11_driver_if.h" > > -#include "soc15_common.h" > > -#include "atom.h" > > -#include "power_state.h" > > -#include "vega20_ppt.h" > > -#include "vega20_pptable.h" > > -#include "vega20_ppsmc.h" > > -#include "nbio/nbio_7_4_sh_mask.h" > > -#include "asic_reg/thm/thm_11_0_2_offset.h" > > -#include "asic_reg/thm/thm_11_0_2_sh_mask.h" > > - > > -#define smnPCIE_LC_SPEED_CNTL 0x11140290 > > -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 > > - > > -#define CTF_OFFSET_EDGE 5 > > -#define CTF_OFFSET_HOTSPOT 5 > > -#define CTF_OFFSET_HBM 5 > > - > > -#define MSG_MAP(msg) \ > > - [SMU_MSG_##msg] = PPSMC_MSG_##msg > > - > > -#define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \ > > - FEATURE_DPM_GFXCLK_MASK | \ > > - FEATURE_DPM_UCLK_MASK | \ > > - FEATURE_DPM_SOCCLK_MASK | \ > > - FEATURE_DPM_UVD_MASK | \ > > - FEATURE_DPM_VCE_MASK | \ > > - FEATURE_DPM_MP0CLK_MASK | \ > > - FEATURE_DPM_LINK_MASK | \ > > - FEATURE_DPM_DCEFCLK_MASK) > > - > > -static int vega20_message_map[SMU_MSG_MAX_COUNT] = { > > - MSG_MAP(TestMessage), > > - MSG_MAP(GetSmuVersion), > > - MSG_MAP(GetDriverIfVersion), > > - MSG_MAP(SetAllowedFeaturesMaskLow), > > - MSG_MAP(SetAllowedFeaturesMaskHigh), > > - MSG_MAP(EnableAllSmuFeatures), > > - MSG_MAP(DisableAllSmuFeatures), > > - MSG_MAP(EnableSmuFeaturesLow), > > - MSG_MAP(EnableSmuFeaturesHigh), > > - MSG_MAP(DisableSmuFeaturesLow), > > - MSG_MAP(DisableSmuFeaturesHigh), > > - MSG_MAP(GetEnabledSmuFeaturesLow), > > - MSG_MAP(GetEnabledSmuFeaturesHigh), > > - MSG_MAP(SetWorkloadMask), > > - MSG_MAP(SetPptLimit), > > - MSG_MAP(SetDriverDramAddrHigh), > > - MSG_MAP(SetDriverDramAddrLow), > > - MSG_MAP(SetToolsDramAddrHigh), > > - MSG_MAP(SetToolsDramAddrLow), > > - MSG_MAP(TransferTableSmu2Dram), > > - MSG_MAP(TransferTableDram2Smu), > > - MSG_MAP(UseDefaultPPTable), > > - MSG_MAP(UseBackupPPTable), > > - MSG_MAP(RunBtc), > > - MSG_MAP(RequestI2CBus), > > - MSG_MAP(ReleaseI2CBus), > > - MSG_MAP(SetFloorSocVoltage), > > - MSG_MAP(SoftReset), > > - MSG_MAP(StartBacoMonitor), > > - MSG_MAP(CancelBacoMonitor), > > - MSG_MAP(EnterBaco), > > - MSG_MAP(SetSoftMinByFreq), > > - MSG_MAP(SetSoftMaxByFreq), > > - MSG_MAP(SetHardMinByFreq), > > - MSG_MAP(SetHardMaxByFreq), > > - MSG_MAP(GetMinDpmFreq), > > - MSG_MAP(GetMaxDpmFreq), > > - MSG_MAP(GetDpmFreqByIndex), > > - MSG_MAP(GetDpmClockFreq), > > - MSG_MAP(GetSsVoltageByDpm), > > - MSG_MAP(SetMemoryChannelConfig), > > - MSG_MAP(SetGeminiMode), > > - MSG_MAP(SetGeminiApertureHigh), > > - MSG_MAP(SetGeminiApertureLow), > > - MSG_MAP(SetMinLinkDpmByIndex), > > - MSG_MAP(OverridePcieParameters), > > - MSG_MAP(OverDriveSetPercentage), > > - MSG_MAP(SetMinDeepSleepDcefclk), > > - MSG_MAP(ReenableAcDcInterrupt), > > - MSG_MAP(NotifyPowerSource), > > - MSG_MAP(SetUclkFastSwitch), > > - MSG_MAP(SetUclkDownHyst), > > - MSG_MAP(GetCurrentRpm), > > - MSG_MAP(SetVideoFps), > > - MSG_MAP(SetTjMax), > > - MSG_MAP(SetFanTemperatureTarget), > > - MSG_MAP(PrepareMp1ForUnload), > > - MSG_MAP(DramLogSetDramAddrHigh), > > - MSG_MAP(DramLogSetDramAddrLow), > > - MSG_MAP(DramLogSetDramSize), > > - MSG_MAP(SetFanMaxRpm), > > - MSG_MAP(SetFanMinPwm), > > - MSG_MAP(ConfigureGfxDidt), > > - MSG_MAP(NumOfDisplays), > > - MSG_MAP(RemoveMargins), > > - MSG_MAP(ReadSerialNumTop32), > > - MSG_MAP(ReadSerialNumBottom32), > > - MSG_MAP(SetSystemVirtualDramAddrHigh), > > - MSG_MAP(SetSystemVirtualDramAddrLow), > > - MSG_MAP(WaflTest), > > - MSG_MAP(SetFclkGfxClkRatio), > > - MSG_MAP(AllowGfxOff), > > - MSG_MAP(DisallowGfxOff), > > - MSG_MAP(GetPptLimit), > > - MSG_MAP(GetDcModeMaxDpmFreq), > > - MSG_MAP(GetDebugData), > > - MSG_MAP(SetXgmiMode), > > - MSG_MAP(RunAfllBtc), > > - MSG_MAP(ExitBaco), > > - MSG_MAP(PrepareMp1ForReset), > > - MSG_MAP(PrepareMp1ForShutdown), > > - MSG_MAP(SetMGpuFanBoostLimitRpm), > > - MSG_MAP(GetAVFSVoltageByDpm), > > -}; > > - > > -static int vega20_clk_map[SMU_CLK_COUNT] = { > > - CLK_MAP(GFXCLK, PPCLK_GFXCLK), > > - CLK_MAP(VCLK, PPCLK_VCLK), > > - CLK_MAP(DCLK, PPCLK_DCLK), > > - CLK_MAP(ECLK, PPCLK_ECLK), > > - CLK_MAP(SOCCLK, PPCLK_SOCCLK), > > - CLK_MAP(UCLK, PPCLK_UCLK), > > - CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), > > - CLK_MAP(DISPCLK, PPCLK_DISPCLK), > > - CLK_MAP(PIXCLK, PPCLK_PIXCLK), > > - CLK_MAP(PHYCLK, PPCLK_PHYCLK), > > - CLK_MAP(FCLK, PPCLK_FCLK), > > -}; > > - > > -static int vega20_feature_mask_map[SMU_FEATURE_COUNT] = { > > - FEA_MAP(DPM_PREFETCHER), > > - FEA_MAP(DPM_GFXCLK), > > - FEA_MAP(DPM_UCLK), > > - FEA_MAP(DPM_SOCCLK), > > - FEA_MAP(DPM_UVD), > > - FEA_MAP(DPM_VCE), > > - FEA_MAP(ULV), > > - FEA_MAP(DPM_MP0CLK), > > - FEA_MAP(DPM_LINK), > > - FEA_MAP(DPM_DCEFCLK), > > - FEA_MAP(DS_GFXCLK), > > - FEA_MAP(DS_SOCCLK), > > - FEA_MAP(DS_LCLK), > > - FEA_MAP(PPT), > > - FEA_MAP(TDC), > > - FEA_MAP(THERMAL), > > - FEA_MAP(GFX_PER_CU_CG), > > - FEA_MAP(RM), > > - FEA_MAP(DS_DCEFCLK), > > - FEA_MAP(ACDC), > > - FEA_MAP(VR0HOT), > > - FEA_MAP(VR1HOT), > > - FEA_MAP(FW_CTF), > > - FEA_MAP(LED_DISPLAY), > > - FEA_MAP(FAN_CONTROL), > > - FEA_MAP(GFX_EDC), > > - FEA_MAP(GFXOFF), > > - FEA_MAP(CG), > > - FEA_MAP(DPM_FCLK), > > - FEA_MAP(DS_FCLK), > > - FEA_MAP(DS_MP1CLK), > > - FEA_MAP(DS_MP0CLK), > > - FEA_MAP(XGMI), > > -}; > > - > > -static int vega20_table_map[SMU_TABLE_COUNT] = { > > - TAB_MAP(PPTABLE), > > - TAB_MAP(WATERMARKS), > > - TAB_MAP(AVFS), > > - TAB_MAP(AVFS_PSM_DEBUG), > > - TAB_MAP(AVFS_FUSE_OVERRIDE), > > - TAB_MAP(PMSTATUSLOG), > > - TAB_MAP(SMU_METRICS), > > - TAB_MAP(DRIVER_SMU_CONFIG), > > - TAB_MAP(ACTIVITY_MONITOR_COEFF), > > - TAB_MAP(OVERDRIVE), > > -}; > > - > > -static int vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { > > - PWR_MAP(AC), > > - PWR_MAP(DC), > > -}; > > - > > -static int vega20_workload_map[] = { > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, > > WORKLOAD_DEFAULT_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, > > WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, > > WORKLOAD_PPLIB_POWER_SAVING_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, > > WORKLOAD_PPLIB_VIDEO_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, > > WORKLOAD_PPLIB_VR_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, > > WORKLOAD_PPLIB_CUSTOM_BIT), > > -}; > > - > > -static int vega20_get_smu_table_index(struct smu_context *smc, > uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_TABLE_COUNT) > > - return -EINVAL; > > - > > - val = vega20_table_map[index]; > > - if (val >= TABLE_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_POWER_SOURCE_COUNT) > > - return -EINVAL; > > - > > - val = vega20_pwr_src_map[index]; > > - if (val >= POWER_SOURCE_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int vega20_get_smu_feature_index(struct smu_context *smc, > > uint32_t index) > > -{ > > - int val; > > - if (index >= SMU_FEATURE_COUNT) > > - return -EINVAL; > > - > > - val = vega20_feature_mask_map[index]; > > - if (val > 64) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - if (index >= SMU_CLK_COUNT) > > - return -EINVAL; > > - > > - val = vega20_clk_map[index]; > > - if (val >= PPCLK_COUNT) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t > > index) > > -{ > > - int val; > > - > > - if (index >= SMU_MSG_MAX_COUNT) > > - return -EINVAL; > > - > > - val = vega20_message_map[index]; > > - if (val > PPSMC_Message_Count) > > - return -EINVAL; > > - > > - return val; > > -} > > - > > -static int vega20_get_workload_type(struct smu_context *smu, enum > > PP_SMC_POWER_PROFILE profile) > > -{ > > - int val; > > - if (profile > PP_SMC_POWER_PROFILE_CUSTOM) > > - return -EINVAL; > > - > > - val = vega20_workload_map[profile]; > > - > > - return val; > > -} > > - > > -static int vega20_tables_init(struct smu_context *smu, struct smu_table > > *tables) > > -{ > > - struct smu_table_context *smu_table = &smu->smu_table; > > - > > - SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, > > sizeof(Watermarks_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, > > sizeof(SmuMetrics_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, > > sizeof(OverDriveTable_t), > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, > > SMU11_TOOL_SIZE, > > - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); > > - SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, > > - sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, > > - AMDGPU_GEM_DOMAIN_VRAM); > > - > > - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), > > GFP_KERNEL); > > - if (smu_table->metrics_table) > > - return -ENOMEM; > > - smu_table->metrics_time = 0; > > - > > - return 0; > > -} > > - > > -static int vega20_allocate_dpm_context(struct smu_context *smu) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - > > - if (smu_dpm->dpm_context) > > - return -EINVAL; > > - > > - smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table), > > - GFP_KERNEL); > > - if (!smu_dpm->dpm_context) > > - return -ENOMEM; > > - > > - if (smu_dpm->golden_dpm_context) > > - return -EINVAL; > > - > > - smu_dpm->golden_dpm_context = kzalloc(sizeof(struct > > vega20_dpm_table), > > - GFP_KERNEL); > > - if (!smu_dpm->golden_dpm_context) > > - return -ENOMEM; > > - > > - smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table); > > - > > - smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct > > smu_power_state), > > - GFP_KERNEL); > > - if (!smu_dpm->dpm_current_power_state) > > - return -ENOMEM; > > - > > - smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct > > smu_power_state), > > - GFP_KERNEL); > > - if (!smu_dpm->dpm_request_power_state) > > - return -ENOMEM; > > - > > - return 0; > > -} > > - > > -static int vega20_setup_od8_information(struct smu_context *smu) > > -{ > > - ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > - struct smu_table_context *table_context = &smu->smu_table; > > - struct vega20_od8_settings *od8_settings = (struct > > vega20_od8_settings *)smu->od_settings; > > - > > - uint32_t od_feature_count, od_feature_array_size, > > - od_setting_count, od_setting_array_size; > > - > > - if (!table_context->power_play_table) > > - return -EINVAL; > > - > > - powerplay_table = table_context->power_play_table; > > - > > - if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { > > - /* Setup correct ODFeatureCount, and store ODFeatureArray > > from > > - * powerplay table to od_feature_capabilities */ > > - od_feature_count = > > - (le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODFeatureCount) > > > - ATOM_VEGA20_ODFEATURE_COUNT) ? > > - ATOM_VEGA20_ODFEATURE_COUNT : > > - le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODFeatureCount); > > - > > - od_feature_array_size = sizeof(uint8_t) * od_feature_count; > > - > > - if (od8_settings->od_feature_capabilities) > > - return -EINVAL; > > - > > - od8_settings->od_feature_capabilities = > > kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities, > > - > > od_feature_array_size, > > - > > GFP_KERNEL); > > - if (!od8_settings->od_feature_capabilities) > > - return -ENOMEM; > > - > > - /* Setup correct ODSettingCount, and store ODSettingArray > > from > > - * powerplay table to od_settings_max and od_setting_min > > */ > > - od_setting_count = > > - (le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingCount) > > > - ATOM_VEGA20_ODSETTING_COUNT) ? > > - ATOM_VEGA20_ODSETTING_COUNT : > > - le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingCount); > > - > > - od_setting_array_size = sizeof(uint32_t) * od_setting_count; > > - > > - if (od8_settings->od_settings_max) > > - return -EINVAL; > > - > > - od8_settings->od_settings_max = > > kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax, > > - > > od_setting_array_size, > > - GFP_KERNEL); > > - > > - if (!od8_settings->od_settings_max) { > > - kfree(od8_settings->od_feature_capabilities); > > - od8_settings->od_feature_capabilities = NULL; > > - return -ENOMEM; > > - } > > - > > - if (od8_settings->od_settings_min) > > - return -EINVAL; > > - > > - od8_settings->od_settings_min = > > kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin, > > - > > od_setting_array_size, > > - GFP_KERNEL); > > - > > - if (!od8_settings->od_settings_min) { > > - kfree(od8_settings->od_feature_capabilities); > > - od8_settings->od_feature_capabilities = NULL; > > - kfree(od8_settings->od_settings_max); > > - od8_settings->od_settings_max = NULL; > > - return -ENOMEM; > > - } > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_store_powerplay_table(struct smu_context *smu) > > -{ > > - ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > - struct smu_table_context *table_context = &smu->smu_table; > > - int ret; > > - > > - if (!table_context->power_play_table) > > - return -EINVAL; > > - > > - powerplay_table = table_context->power_play_table; > > - > > - memcpy(table_context->driver_pptable, &powerplay_table- > > >smcPPTable, > > - sizeof(PPTable_t)); > > - > > - table_context->software_shutdown_temp = powerplay_table- > > >usSoftwareShutdownTemp; > > - table_context->thermal_controller_type = powerplay_table- > > >ucThermalControllerType; > > - table_context->TDPODLimit = le32_to_cpu(powerplay_table- > > >OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPE > R > > CENTAGE]); > > - > > - ret = vega20_setup_od8_information(smu); > > - > > - return ret; > > -} > > - > > -static int vega20_append_powerplay_table(struct smu_context *smu) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *smc_pptable = table_context->driver_pptable; > > - struct atom_smc_dpm_info_v4_4 *smc_dpm_table; > > - int index, i, ret; > > - > > - index = > > get_index_into_master_table(atom_master_list_of_data_tables_v2_1, > > - smc_dpm_info); > > - > > - ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, > > - (uint8_t **)&smc_dpm_table); > > - if (ret) > > - return ret; > > - > > - smc_pptable->MaxVoltageStepGfx = smc_dpm_table- > > >maxvoltagestepgfx; > > - smc_pptable->MaxVoltageStepSoc = smc_dpm_table- > > >maxvoltagestepsoc; > > - > > - smc_pptable->VddGfxVrMapping = smc_dpm_table- > > >vddgfxvrmapping; > > - smc_pptable->VddSocVrMapping = smc_dpm_table- > > >vddsocvrmapping; > > - smc_pptable->VddMem0VrMapping = smc_dpm_table- > > >vddmem0vrmapping; > > - smc_pptable->VddMem1VrMapping = smc_dpm_table- > > >vddmem1vrmapping; > > - > > - smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table- > > >gfxulvphasesheddingmask; > > - smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table- > > >soculvphasesheddingmask; > > - smc_pptable->ExternalSensorPresent = smc_dpm_table- > > >externalsensorpresent; > > - > > - smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent; > > - smc_pptable->GfxOffset = smc_dpm_table->gfxoffset; > > - smc_pptable->Padding_TelemetryGfx = smc_dpm_table- > > >padding_telemetrygfx; > > - > > - smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent; > > - smc_pptable->SocOffset = smc_dpm_table->socoffset; > > - smc_pptable->Padding_TelemetrySoc = smc_dpm_table- > > >padding_telemetrysoc; > > - > > - smc_pptable->Mem0MaxCurrent = smc_dpm_table- > > >mem0maxcurrent; > > - smc_pptable->Mem0Offset = smc_dpm_table->mem0offset; > > - smc_pptable->Padding_TelemetryMem0 = smc_dpm_table- > > >padding_telemetrymem0; > > - > > - smc_pptable->Mem1MaxCurrent = smc_dpm_table- > > >mem1maxcurrent; > > - smc_pptable->Mem1Offset = smc_dpm_table->mem1offset; > > - smc_pptable->Padding_TelemetryMem1 = smc_dpm_table- > > >padding_telemetrymem1; > > - > > - smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio; > > - smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity; > > - smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio; > > - smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity; > > - > > - smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio; > > - smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity; > > - smc_pptable->Padding1 = smc_dpm_table->padding1; > > - smc_pptable->Padding2 = smc_dpm_table->padding2; > > - > > - smc_pptable->LedPin0 = smc_dpm_table->ledpin0; > > - smc_pptable->LedPin1 = smc_dpm_table->ledpin1; > > - smc_pptable->LedPin2 = smc_dpm_table->ledpin2; > > - > > - smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table- > > >pllgfxclkspreadenabled; > > - smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table- > > >pllgfxclkspreadpercent; > > - smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table- > > >pllgfxclkspreadfreq; > > - > > - smc_pptable->UclkSpreadEnabled = 0; > > - smc_pptable->UclkSpreadPercent = smc_dpm_table- > > >uclkspreadpercent; > > - smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq; > > - > > - smc_pptable->FclkSpreadEnabled = smc_dpm_table- > > >fclkspreadenabled; > > - smc_pptable->FclkSpreadPercent = smc_dpm_table- > > >fclkspreadpercent; > > - smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq; > > - > > - smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table- > > >fllgfxclkspreadenabled; > > - smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table- > > >fllgfxclkspreadpercent; > > - smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table- > > >fllgfxclkspreadfreq; > > - > > - for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { > > - smc_pptable->I2cControllers[i].Enabled = > > - smc_dpm_table->i2ccontrollers[i].enabled; > > - smc_pptable->I2cControllers[i].SlaveAddress = > > - smc_dpm_table->i2ccontrollers[i].slaveaddress; > > - smc_pptable->I2cControllers[i].ControllerPort = > > - smc_dpm_table->i2ccontrollers[i].controllerport; > > - smc_pptable->I2cControllers[i].ThermalThrottler = > > - smc_dpm_table->i2ccontrollers[i].thermalthrottler; > > - smc_pptable->I2cControllers[i].I2cProtocol = > > - smc_dpm_table->i2ccontrollers[i].i2cprotocol; > > - smc_pptable->I2cControllers[i].I2cSpeed = > > - smc_dpm_table->i2ccontrollers[i].i2cspeed; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_check_powerplay_table(struct smu_context *smu) > > -{ > > - ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; > > - struct smu_table_context *table_context = &smu->smu_table; > > - > > - powerplay_table = table_context->power_play_table; > > - > > - if (powerplay_table->sHeader.format_revision < > > ATOM_VEGA20_TABLE_REVISION_VEGA20) { > > - pr_err("Unsupported PPTable format!"); > > - return -EINVAL; > > - } > > - > > - if (!powerplay_table->sHeader.structuresize) { > > - pr_err("Invalid PowerPlay Table!"); > > - return -EINVAL; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_run_btc_afll(struct smu_context *smu) > > -{ > > - return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc); > > -} > > - > > -#define FEATURE_MASK(feature) (1ULL << feature) > > -static int > > -vega20_get_allowed_feature_mask(struct smu_context *smu, > > - uint32_t *feature_mask, uint32_t num) > > -{ > > - if (num > 2) > > - return -EINVAL; > > - > > - memset(feature_mask, 0, sizeof(uint32_t) * num); > > - > > - *(uint64_t *)feature_mask |= > > FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) > > - | FEATURE_MASK(FEATURE_DPM_UCLK_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) > > - | FEATURE_MASK(FEATURE_DPM_UVD_BIT) > > - | FEATURE_MASK(FEATURE_DPM_VCE_BIT) > > - | FEATURE_MASK(FEATURE_ULV_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) > > - | FEATURE_MASK(FEATURE_DPM_LINK_BIT) > > - | > > FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) > > - | FEATURE_MASK(FEATURE_PPT_BIT) > > - | FEATURE_MASK(FEATURE_TDC_BIT) > > - | FEATURE_MASK(FEATURE_THERMAL_BIT) > > - | > > FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT) > > - | FEATURE_MASK(FEATURE_RM_BIT) > > - | FEATURE_MASK(FEATURE_ACDC_BIT) > > - | FEATURE_MASK(FEATURE_VR0HOT_BIT) > > - | FEATURE_MASK(FEATURE_VR1HOT_BIT) > > - | FEATURE_MASK(FEATURE_FW_CTF_BIT) > > - | > > FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) > > - | > > FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) > > - | FEATURE_MASK(FEATURE_GFX_EDC_BIT) > > - | FEATURE_MASK(FEATURE_GFXOFF_BIT) > > - | FEATURE_MASK(FEATURE_CG_BIT) > > - | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) > > - | FEATURE_MASK(FEATURE_XGMI_BIT); > > - return 0; > > -} > > - > > -static enum > > -amd_pm_state_type vega20_get_current_power_state(struct > > smu_context *smu) > > -{ > > - enum amd_pm_state_type pm_type; > > - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > - > > - if (!smu_dpm_ctx->dpm_context || > > - !smu_dpm_ctx->dpm_current_power_state) > > - return -EINVAL; > > - > > - mutex_lock(&(smu->mutex)); > > - switch (smu_dpm_ctx->dpm_current_power_state- > > >classification.ui_label) { > > - case SMU_STATE_UI_LABEL_BATTERY: > > - pm_type = POWER_STATE_TYPE_BATTERY; > > - break; > > - case SMU_STATE_UI_LABEL_BALLANCED: > > - pm_type = POWER_STATE_TYPE_BALANCED; > > - break; > > - case SMU_STATE_UI_LABEL_PERFORMANCE: > > - pm_type = POWER_STATE_TYPE_PERFORMANCE; > > - break; > > - default: > > - if (smu_dpm_ctx->dpm_current_power_state- > > >classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) > > - pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; > > - else > > - pm_type = POWER_STATE_TYPE_DEFAULT; > > - break; > > - } > > - mutex_unlock(&(smu->mutex)); > > - > > - return pm_type; > > -} > > - > > -static int > > -vega20_set_single_dpm_table(struct smu_context *smu, > > - struct vega20_single_dpm_table > > *single_dpm_table, > > - PPCLK_e clk_id) > > -{ > > - int ret = 0; > > - uint32_t i, num_of_levels = 0, clk; > > - > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_GetDpmFreqByIndex, > > - (clk_id << 16 | 0xFF)); > > - if (ret) { > > - pr_err("[GetNumOfDpmLevel] failed to get dpm levels!"); > > - return ret; > > - } > > - > > - smu_read_smc_arg(smu, &num_of_levels); > > - if (!num_of_levels) { > > - pr_err("[GetNumOfDpmLevel] number of clk levels is > > invalid!"); > > - return -EINVAL; > > - } > > - > > - single_dpm_table->count = num_of_levels; > > - > > - for (i = 0; i < num_of_levels; i++) { > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_GetDpmFreqByIndex, > > - (clk_id << 16 | i)); > > - if (ret) { > > - pr_err("[GetDpmFreqByIndex] failed to get dpm freq > > by index!"); > > - return ret; > > - } > > - smu_read_smc_arg(smu, &clk); > > - if (!clk) { > > - pr_err("[GetDpmFreqByIndex] clk value is invalid!"); > > - return -EINVAL; > > - } > > - single_dpm_table->dpm_levels[i].value = clk; > > - single_dpm_table->dpm_levels[i].enabled = true; > > - } > > - return 0; > > -} > > - > > -static void vega20_init_single_dpm_state(struct vega20_dpm_state > > *dpm_state) > > -{ > > - dpm_state->soft_min_level = 0x0; > > - dpm_state->soft_max_level = 0xffff; > > - dpm_state->hard_min_level = 0x0; > > - dpm_state->hard_max_level = 0xffff; > > -} > > - > > -static int vega20_set_default_dpm_table(struct smu_context *smu) > > -{ > > - int ret; > > - > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_single_dpm_table *single_dpm_table; > > - > > - dpm_table = smu_dpm->dpm_context; > > - > > - /* socclk */ > > - single_dpm_table = &(dpm_table->soc_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_SOCCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get socclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.socclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* gfxclk */ > > - single_dpm_table = &(dpm_table->gfx_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_GFXCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get gfxclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.gfxclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* memclk */ > > - single_dpm_table = &(dpm_table->mem_table); > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_UCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get > > memclk dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.uclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* eclk */ > > - single_dpm_table = &(dpm_table->eclk_table); > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_ECLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get eclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.eclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* vclk */ > > - single_dpm_table = &(dpm_table->vclk_table); > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_VCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get vclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.vclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* dclk */ > > - single_dpm_table = &(dpm_table->dclk_table); > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > PPCLK_DCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get dclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.dclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* dcefclk */ > > - single_dpm_table = &(dpm_table->dcef_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_DCEFCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get dcefclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.dcefclk / 100; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* pixclk */ > > - single_dpm_table = &(dpm_table->pixel_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_PIXCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get pixclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 0; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* dispclk */ > > - single_dpm_table = &(dpm_table->display_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_DISPCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get dispclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 0; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* phyclk */ > > - single_dpm_table = &(dpm_table->phy_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_PHYCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get phyclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 0; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - /* fclk */ > > - single_dpm_table = &(dpm_table->fclk_table); > > - > > - if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - PPCLK_FCLK); > > - if (ret) { > > - pr_err("[SetupDefaultDpmTable] failed to get fclk > > dpm levels!"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 0; > > - } > > - vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); > > - > > - memcpy(smu_dpm->golden_dpm_context, dpm_table, > > - sizeof(struct vega20_dpm_table)); > > - > > - return 0; > > -} > > - > > -static int vega20_populate_umd_state_clk(struct smu_context *smu) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_single_dpm_table *gfx_table = NULL; > > - struct vega20_single_dpm_table *mem_table = NULL; > > - > > - dpm_table = smu_dpm->dpm_context; > > - gfx_table = &(dpm_table->gfx_table); > > - mem_table = &(dpm_table->mem_table); > > - > > - smu->pstate_sclk = gfx_table->dpm_levels[0].value; > > - smu->pstate_mclk = mem_table->dpm_levels[0].value; > > - > > - if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && > > - mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { > > - smu->pstate_sclk = gfx_table- > > >dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > - smu->pstate_mclk = mem_table- > > >dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > - } > > - > > - smu->pstate_sclk = smu->pstate_sclk * 100; > > - smu->pstate_mclk = smu->pstate_mclk * 100; > > - > > - return 0; > > -} > > - > > -static int vega20_get_clk_table(struct smu_context *smu, > > - struct pp_clock_levels_with_latency *clocks, > > - struct vega20_single_dpm_table *dpm_table) > > -{ > > - int i, count; > > - > > - count = (dpm_table->count > MAX_NUM_CLOCKS) ? > > MAX_NUM_CLOCKS : dpm_table->count; > > - clocks->num_levels = count; > > - > > - for (i = 0; i < count; i++) { > > - clocks->data[i].clocks_in_khz = > > - dpm_table->dpm_levels[i].value * 1000; > > - clocks->data[i].latency_in_us = 0; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_print_clk_levels(struct smu_context *smu, > > - enum smu_clk_type type, char *buf) > > -{ > > - int i, now, size = 0; > > - int ret = 0; > > - uint32_t gen_speed, lane_width; > > - struct amdgpu_device *adev = smu->adev; > > - struct pp_clock_levels_with_latency clocks; > > - struct vega20_single_dpm_table *single_dpm_table; > > - struct smu_table_context *table_context = &smu->smu_table; > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_od8_settings *od8_settings = > > - (struct vega20_od8_settings *)smu->od_settings; > > - OverDriveTable_t *od_table = > > - (OverDriveTable_t *)(table_context->overdrive_table); > > - PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; > > - > > - dpm_table = smu_dpm->dpm_context; > > - > > - switch (type) { > > - case SMU_SCLK: > > - ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now); > > - if (ret) { > > - pr_err("Attempt to get current gfx clk Failed!"); > > - return ret; > > - } > > - > > - single_dpm_table = &(dpm_table->gfx_table); > > - ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get gfx clk levels Failed!"); > > - return ret; > > - } > > - > > - for (i = 0; i < clocks.num_levels; i++) > > - size += sprintf(buf + size, "%d: %uMhz %s\n", i, > > - clocks.data[i].clocks_in_khz / 1000, > > - (clocks.data[i].clocks_in_khz == now > > * 10) > > - ? "*" : ""); > > - break; > > - > > - case SMU_MCLK: > > - ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now); > > - if (ret) { > > - pr_err("Attempt to get current mclk Failed!"); > > - return ret; > > - } > > - > > - single_dpm_table = &(dpm_table->mem_table); > > - ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get memory clk levels Failed!"); > > - return ret; > > - } > > - > > - for (i = 0; i < clocks.num_levels; i++) > > - size += sprintf(buf + size, "%d: %uMhz %s\n", > > - i, clocks.data[i].clocks_in_khz / 1000, > > - (clocks.data[i].clocks_in_khz == now * 10) > > - ? "*" : ""); > > - break; > > - > > - case SMU_SOCCLK: > > - ret = smu_get_current_clk_freq(smu, PPCLK_SOCCLK, > > &now); > > - if (ret) { > > - pr_err("Attempt to get current socclk Failed!"); > > - return ret; > > - } > > - > > - single_dpm_table = &(dpm_table->soc_table); > > - ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get socclk levels Failed!"); > > - return ret; > > - } > > - > > - for (i = 0; i < clocks.num_levels; i++) > > - size += sprintf(buf + size, "%d: %uMhz %s\n", > > - i, clocks.data[i].clocks_in_khz / 1000, > > - (clocks.data[i].clocks_in_khz == now * 10) > > - ? "*" : ""); > > - break; > > - > > - case SMU_FCLK: > > - ret = smu_get_current_clk_freq(smu, PPCLK_FCLK, &now); > > - if (ret) { > > - pr_err("Attempt to get current fclk Failed!"); > > - return ret; > > - } > > - > > - single_dpm_table = &(dpm_table->fclk_table); > > - for (i = 0; i < single_dpm_table->count; i++) > > - size += sprintf(buf + size, "%d: %uMhz %s\n", > > - i, single_dpm_table->dpm_levels[i].value, > > - (single_dpm_table->dpm_levels[i].value == > > now / 100) > > - ? "*" : ""); > > - break; > > - > > - case SMU_DCEFCLK: > > - ret = smu_get_current_clk_freq(smu, PPCLK_DCEFCLK, > > &now); > > - if (ret) { > > - pr_err("Attempt to get current dcefclk Failed!"); > > - return ret; > > - } > > - > > - single_dpm_table = &(dpm_table->dcef_table); > > - ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get dcefclk levels Failed!"); > > - return ret; > > - } > > - > > - for (i = 0; i < clocks.num_levels; i++) > > - size += sprintf(buf + size, "%d: %uMhz %s\n", > > - i, clocks.data[i].clocks_in_khz / 1000, > > - (clocks.data[i].clocks_in_khz == now * 10) ? > > "*" : ""); > > - break; > > - > > - case SMU_PCIE: > > - gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & > > - > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) > > - >> > > PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; > > - lane_width = > > (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & > > - > > PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) > > - >> > > PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; > > - for (i = 0; i < NUM_LINK_LEVELS; i++) > > - size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, > > - (pptable->PcieGenSpeed[i] == 0) ? > > "2.5GT/s," : > > - (pptable->PcieGenSpeed[i] == 1) ? > > "5.0GT/s," : > > - (pptable->PcieGenSpeed[i] == 2) ? > > "8.0GT/s," : > > - (pptable->PcieGenSpeed[i] == 3) ? > > "16.0GT/s," : "", > > - (pptable->PcieLaneCount[i] == 1) ? > > "x1" : > > - (pptable->PcieLaneCount[i] == 2) ? > > "x2" : > > - (pptable->PcieLaneCount[i] == 3) ? > > "x4" : > > - (pptable->PcieLaneCount[i] == 4) ? > > "x8" : > > - (pptable->PcieLaneCount[i] == 5) ? > > "x12" : > > - (pptable->PcieLaneCount[i] == 6) ? > > "x16" : "", > > - pptable->LclkFreq[i], > > - (gen_speed == pptable- > > >PcieGenSpeed[i]) && > > - (lane_width == pptable- > > >PcieLaneCount[i]) ? > > - "*" : ""); > > - break; > > - > > - case SMU_OD_SCLK: > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { > > - size = sprintf(buf, "%s:\n", "OD_SCLK"); > > - size += sprintf(buf + size, "0: %10uMhz\n", > > - od_table->GfxclkFmin); > > - size += sprintf(buf + size, "1: %10uMhz\n", > > - od_table->GfxclkFmax); > > - } > > - > > - break; > > - > > - case SMU_OD_MCLK: > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > - size = sprintf(buf, "%s:\n", "OD_MCLK"); > > - size += sprintf(buf + size, "1: %10uMhz\n", > > - od_table->UclkFmax); > > - } > > - > > - break; > > - > > - case SMU_OD_VDDC_CURVE: > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { > > - size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); > > - size += sprintf(buf + size, "0: %10uMhz %10dmV\n", > > - od_table->GfxclkFreq1, > > - od_table->GfxclkVolt1 / > > VOLTAGE_SCALE); > > - size += sprintf(buf + size, "1: %10uMhz %10dmV\n", > > - od_table->GfxclkFreq2, > > - od_table->GfxclkVolt2 / > > VOLTAGE_SCALE); > > - size += sprintf(buf + size, "2: %10uMhz %10dmV\n", > > - od_table->GfxclkFreq3, > > - od_table->GfxclkVolt3 / > > VOLTAGE_SCALE); > > - } > > - > > - break; > > - > > - case SMU_OD_RANGE: > > - size = sprintf(buf, "%s:\n", "OD_RANGE"); > > - > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { > > - size += sprintf(buf + size, > > "SCLK: %7uMhz %10uMhz\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); > > - } > > - > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > - single_dpm_table = &(dpm_table->mem_table); > > - ret = vega20_get_clk_table(smu, &clocks, > > single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get memory clk levels > > Failed!"); > > - return ret; > > - } > > - > > - size += sprintf(buf + size, > > "MCLK: %7uMhz %10uMhz\n", > > - clocks.data[0].clocks_in_khz / 1000, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); > > - } > > - > > - if (od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { > > - size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value); > > - size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); > > - size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value); > > - size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); > > - size += sprintf(buf + size, > > "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value); > > - size += sprintf(buf + size, > > "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); > > - } > > - > > - break; > > - > > - default: > > - break; > > - } > > - return size; > > -} > > - > > -static int vega20_upload_dpm_level(struct smu_context *smu, bool max, > > - uint32_t feature_mask) > > -{ > > - struct vega20_dpm_table *dpm_table; > > - struct vega20_single_dpm_table *single_dpm_table; > > - uint32_t freq; > > - int ret = 0; > > - > > - dpm_table = smu->smu_dpm.dpm_context; > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) > > && > > - (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { > > - single_dpm_table = &(dpm_table->gfx_table); > > - freq = max ? single_dpm_table->dpm_state.soft_max_level : > > - single_dpm_table->dpm_state.soft_min_level; > > - ret = smu_send_smc_msg_with_param(smu, > > - (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > - (PPCLK_GFXCLK << 16) | (freq & 0xffff)); > > - if (ret) { > > - pr_err("Failed to set soft %s gfxclk !\n", > > - max ? "max" : "min"); > > - return ret; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) > > && > > - (feature_mask & FEATURE_DPM_UCLK_MASK)) { > > - single_dpm_table = &(dpm_table->mem_table); > > - freq = max ? single_dpm_table->dpm_state.soft_max_level : > > - single_dpm_table->dpm_state.soft_min_level; > > - ret = smu_send_smc_msg_with_param(smu, > > - (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > - (PPCLK_UCLK << 16) | (freq & 0xffff)); > > - if (ret) { > > - pr_err("Failed to set soft %s memclk !\n", > > - max ? "max" : "min"); > > - return ret; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) > > && > > - (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { > > - single_dpm_table = &(dpm_table->soc_table); > > - freq = max ? single_dpm_table->dpm_state.soft_max_level : > > - single_dpm_table->dpm_state.soft_min_level; > > - ret = smu_send_smc_msg_with_param(smu, > > - (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > - (PPCLK_SOCCLK << 16) | (freq & 0xffff)); > > - if (ret) { > > - pr_err("Failed to set soft %s socclk !\n", > > - max ? "max" : "min"); > > - return ret; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) > > && > > - (feature_mask & FEATURE_DPM_FCLK_MASK)) { > > - single_dpm_table = &(dpm_table->fclk_table); > > - freq = max ? single_dpm_table->dpm_state.soft_max_level : > > - single_dpm_table->dpm_state.soft_min_level; > > - ret = smu_send_smc_msg_with_param(smu, > > - (max ? SMU_MSG_SetSoftMaxByFreq : > > SMU_MSG_SetSoftMinByFreq), > > - (PPCLK_FCLK << 16) | (freq & 0xffff)); > > - if (ret) { > > - pr_err("Failed to set soft %s fclk !\n", > > - max ? "max" : "min"); > > - return ret; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > - (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { > > - single_dpm_table = &(dpm_table->dcef_table); > > - freq = single_dpm_table->dpm_state.hard_min_level; > > - if (!max) { > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_SetHardMinByFreq, > > - (PPCLK_DCEFCLK << 16) | (freq & 0xffff)); > > - if (ret) { > > - pr_err("Failed to set hard min dcefclk !\n"); > > - return ret; > > - } > > - } > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_force_clk_levels(struct smu_context *smu, > > - enum smu_clk_type clk_type, uint32_t mask) > > -{ > > - struct vega20_dpm_table *dpm_table; > > - struct vega20_single_dpm_table *single_dpm_table; > > - uint32_t soft_min_level, soft_max_level, hard_min_level; > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - int ret = 0; > > - > > - if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { > > - pr_info("force clock level is for dpm manual mode only.\n"); > > - return -EINVAL; > > - } > > - > > - mutex_lock(&(smu->mutex)); > > - > > - soft_min_level = mask ? (ffs(mask) - 1) : 0; > > - soft_max_level = mask ? (fls(mask) - 1) : 0; > > - > > - dpm_table = smu->smu_dpm.dpm_context; > > - > > - switch (clk_type) { > > - case SMU_SCLK: > > - single_dpm_table = &(dpm_table->gfx_table); > > - > > - if (soft_max_level >= single_dpm_table->count) { > > - pr_err("Clock level specified %d is over max > > allowed %d\n", > > - soft_max_level, single_dpm_table- > > >count - 1); > > - ret = -EINVAL; > > - break; > > - } > > - > > - single_dpm_table->dpm_state.soft_min_level = > > - single_dpm_table- > > >dpm_levels[soft_min_level].value; > > - single_dpm_table->dpm_state.soft_max_level = > > - single_dpm_table- > > >dpm_levels[soft_max_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_GFXCLK_MASK); > > - if (ret) { > > - pr_err("Failed to upload boot level to lowest!\n"); > > - break; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_GFXCLK_MASK); > > - if (ret) > > - pr_err("Failed to upload dpm max level to > > highest!\n"); > > - > > - break; > > - > > - case SMU_MCLK: > > - single_dpm_table = &(dpm_table->mem_table); > > - > > - if (soft_max_level >= single_dpm_table->count) { > > - pr_err("Clock level specified %d is over max > > allowed %d\n", > > - soft_max_level, single_dpm_table- > > >count - 1); > > - ret = -EINVAL; > > - break; > > - } > > - > > - single_dpm_table->dpm_state.soft_min_level = > > - single_dpm_table- > > >dpm_levels[soft_min_level].value; > > - single_dpm_table->dpm_state.soft_max_level = > > - single_dpm_table- > > >dpm_levels[soft_max_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_UCLK_MASK); > > - if (ret) { > > - pr_err("Failed to upload boot level to lowest!\n"); > > - break; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_UCLK_MASK); > > - if (ret) > > - pr_err("Failed to upload dpm max level to > > highest!\n"); > > - > > - break; > > - > > - case SMU_SOCCLK: > > - single_dpm_table = &(dpm_table->soc_table); > > - > > - if (soft_max_level >= single_dpm_table->count) { > > - pr_err("Clock level specified %d is over max > > allowed %d\n", > > - soft_max_level, single_dpm_table- > > >count - 1); > > - ret = -EINVAL; > > - break; > > - } > > - > > - single_dpm_table->dpm_state.soft_min_level = > > - single_dpm_table- > > >dpm_levels[soft_min_level].value; > > - single_dpm_table->dpm_state.soft_max_level = > > - single_dpm_table- > > >dpm_levels[soft_max_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_SOCCLK_MASK); > > - if (ret) { > > - pr_err("Failed to upload boot level to lowest!\n"); > > - break; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_SOCCLK_MASK); > > - if (ret) > > - pr_err("Failed to upload dpm max level to > > highest!\n"); > > - > > - break; > > - > > - case SMU_FCLK: > > - single_dpm_table = &(dpm_table->fclk_table); > > - > > - if (soft_max_level >= single_dpm_table->count) { > > - pr_err("Clock level specified %d is over max > > allowed %d\n", > > - soft_max_level, single_dpm_table- > > >count - 1); > > - ret = -EINVAL; > > - break; > > - } > > - > > - single_dpm_table->dpm_state.soft_min_level = > > - single_dpm_table- > > >dpm_levels[soft_min_level].value; > > - single_dpm_table->dpm_state.soft_max_level = > > - single_dpm_table- > > >dpm_levels[soft_max_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_FCLK_MASK); > > - if (ret) { > > - pr_err("Failed to upload boot level to lowest!\n"); > > - break; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, > > FEATURE_DPM_FCLK_MASK); > > - if (ret) > > - pr_err("Failed to upload dpm max level to > > highest!\n"); > > - > > - break; > > - > > - case SMU_DCEFCLK: > > - hard_min_level = soft_min_level; > > - single_dpm_table = &(dpm_table->dcef_table); > > - > > - if (hard_min_level >= single_dpm_table->count) { > > - pr_err("Clock level specified %d is over max > > allowed %d\n", > > - hard_min_level, single_dpm_table- > > >count - 1); > > - ret = -EINVAL; > > - break; > > - } > > - > > - single_dpm_table->dpm_state.hard_min_level = > > - single_dpm_table- > > >dpm_levels[hard_min_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, > > FEATURE_DPM_DCEFCLK_MASK); > > - if (ret) > > - pr_err("Failed to upload boot level to lowest!\n"); > > - > > - break; > > - > > - case SMU_PCIE: > > - if (soft_min_level >= NUM_LINK_LEVELS || > > - soft_max_level >= NUM_LINK_LEVELS) { > > - ret = -EINVAL; > > - break; > > - } > > - > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_SetMinLinkDpmByIndex, > > soft_min_level); > > - if (ret) > > - pr_err("Failed to set min link dpm level!\n"); > > - > > - break; > > - > > - default: > > - break; > > - } > > - > > - mutex_unlock(&(smu->mutex)); > > - return ret; > > -} > > - > > -static int vega20_get_clock_by_type_with_latency(struct smu_context > > *smu, > > - enum smu_clk_type > > clk_type, > > - struct > > pp_clock_levels_with_latency *clocks) > > -{ > > - int ret; > > - struct vega20_single_dpm_table *single_dpm_table; > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - > > - dpm_table = smu_dpm->dpm_context; > > - > > - mutex_lock(&smu->mutex); > > - > > - switch (clk_type) { > > - case SMU_GFXCLK: > > - single_dpm_table = &(dpm_table->gfx_table); > > - ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > - break; > > - case SMU_MCLK: > > - single_dpm_table = &(dpm_table->mem_table); > > - ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > - break; > > - case SMU_DCEFCLK: > > - single_dpm_table = &(dpm_table->dcef_table); > > - ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > - break; > > - case SMU_SOCCLK: > > - single_dpm_table = &(dpm_table->soc_table); > > - ret = vega20_get_clk_table(smu, clocks, single_dpm_table); > > - break; > > - default: > > - ret = -EINVAL; > > - } > > - > > - mutex_unlock(&smu->mutex); > > - return ret; > > -} > > - > > -static int vega20_overdrive_get_gfx_clk_base_voltage(struct > smu_context > > *smu, > > - uint32_t *voltage, > > - uint32_t freq) > > -{ > > - int ret; > > - > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_GetAVFSVoltageByDpm, > > - ((AVFS_CURVE << 24) | > > (OD8_HOTCURVE_TEMPERATURE << 16) | freq)); > > - if (ret) { > > - pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage > > from SMU!"); > > - return ret; > > - } > > - > > - smu_read_smc_arg(smu, voltage); > > - *voltage = *voltage / VOLTAGE_SCALE; > > - > > - return 0; > > -} > > - > > -static int vega20_set_default_od8_setttings(struct smu_context *smu) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context- > > >overdrive_table); > > - struct vega20_od8_settings *od8_settings = NULL; > > - PPTable_t *smc_pptable = table_context->driver_pptable; > > - int i, ret; > > - > > - if (smu->od_settings) > > - return -EINVAL; > > - > > - od8_settings = kzalloc(sizeof(struct vega20_od8_settings), > > GFP_KERNEL); > > - > > - if (od8_settings) > > - return -ENOMEM; > > - > > - smu->od_settings = (void *)od8_settings; > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] > && > > - od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && > > - od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_FMIN])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = > > - OD8_GFXCLK_LIMITS; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = > > - OD8_GFXCLK_LIMITS; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = > > - od_table->GfxclkFmin; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = > > - od_table->GfxclkFmax; > > - } > > - > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] > && > > - (od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= > > - smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= > > - smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) && > > - (od8_settings- > > >od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <= > > - od8_settings- > > >od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = > > - OD8_GFXCLK_CURVE; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = > > - OD8_GFXCLK_CURVE; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = > > - OD8_GFXCLK_CURVE; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = > > - OD8_GFXCLK_CURVE; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = > > - OD8_GFXCLK_CURVE; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = > > - OD8_GFXCLK_CURVE; > > - > > - od_table->GfxclkFreq1 = od_table->GfxclkFmin; > > - od_table->GfxclkFreq2 = (od_table->GfxclkFmin + > > od_table->GfxclkFmax) / 2; > > - od_table->GfxclkFreq3 = od_table->GfxclkFmax; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = > > - od_table->GfxclkFreq1; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = > > - od_table->GfxclkFreq2; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = > > - od_table->GfxclkFreq3; > > - > > - ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > - &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value, > > - od_table->GfxclkFreq1); > > - if (ret) > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = > 0; > > - od_table->GfxclkVolt1 = > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value > > - * VOLTAGE_SCALE; > > - ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > - &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value, > > - od_table->GfxclkFreq2); > > - if (ret) > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = > 0; > > - od_table->GfxclkVolt2 = > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value > > - * VOLTAGE_SCALE; > > - ret = > > vega20_overdrive_get_gfx_clk_base_voltage(smu, > > - &od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value, > > - od_table->GfxclkFreq3); > > - if (ret) > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = > 0; > > - od_table->GfxclkVolt3 = > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value > > - * VOLTAGE_SCALE; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && > > - od8_settings- > > >od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_UCLK_FMAX] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_UCLK_FMAX])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = > > - OD8_UCLK_MAX; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = > > - od_table->UclkFmax; > > - } > > - } > > - > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] > && > > - od8_settings- > > >od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && > > - od8_settings- > > >od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = > > - OD8_POWER_LIMIT; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value > = > > - od_table->OverDrivePct; > > - } > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_FAN_CONTROL_BIT)) { > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LI > > MIT] && > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = > > - OD8_ACOUSTIC_LIMIT_SCLK; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value > = > > - od_table->FanMaximumRpm; > > - } > > - > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] > > && > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = > > - OD8_FAN_SPEED_MIN; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = > > - od_table->FanMinimumPwm * smc_pptable- > > >FanMaximumRpm / 100; > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) { > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FA > N] > > && > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = > > - OD8_TEMPERATURE_FAN; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = > > - od_table->FanTargetTemperature; > > - } > > - > > - if (od8_settings- > > >od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SY > S > > TEM] && > > - od8_settings- > > >od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && > > - od8_settings- > > >od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && > > - (od8_settings- > > >od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= > > - od8_settings- > > >od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) { > > - od8_settings- > > >od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id > = > > - OD8_TEMPERATURE_SYSTEM; > > - od8_settings- > > >od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_val > u > > e = > > - od_table->MaxOpTemp; > > - } > > - } > > - > > - for (i = 0; i < OD8_SETTING_COUNT; i++) { > > - if (od8_settings->od8_settings_array[i].feature_id) { > > - od8_settings->od8_settings_array[i].min_value = > > - od8_settings->od_settings_min[i]; > > - od8_settings->od8_settings_array[i].max_value = > > - od8_settings->od_settings_max[i]; > > - od8_settings->od8_settings_array[i].current_value = > > - od8_settings- > > >od8_settings_array[i].default_value; > > - } else { > > - od8_settings->od8_settings_array[i].min_value = 0; > > - od8_settings->od8_settings_array[i].max_value = 0; > > - od8_settings->od8_settings_array[i].current_value = > > 0; > > - } > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_get_metrics_table(struct smu_context *smu, > > - SmuMetrics_t *metrics_table) > > -{ > > - struct smu_table_context *smu_table= &smu->smu_table; > > - int ret = 0; > > - > > - if (!smu_table->metrics_time || time_after(jiffies, smu_table- > > >metrics_time + HZ / 1000)) { > > - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, > > - (void *)smu_table->metrics_table, false); > > - if (ret) { > > - pr_info("Failed to export SMU metrics table!\n"); > > - return ret; > > - } > > - smu_table->metrics_time = jiffies; > > - } > > - > > - memcpy(metrics_table, smu_table->metrics_table, > > sizeof(SmuMetrics_t)); > > - > > - return ret; > > -} > > - > > -static int vega20_set_default_od_settings(struct smu_context *smu, > > - bool initialize) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - int ret; > > - > > - if (initialize) { > > - if (table_context->overdrive_table) > > - return -EINVAL; > > - > > - table_context->overdrive_table = > > kzalloc(sizeof(OverDriveTable_t), GFP_KERNEL); > > - > > - if (!table_context->overdrive_table) > > - return -ENOMEM; > > - > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > - table_context->overdrive_table, false); > > - if (ret) { > > - pr_err("Failed to export over drive table!\n"); > > - return ret; > > - } > > - > > - ret = vega20_set_default_od8_setttings(smu); > > - if (ret) > > - return ret; > > - } > > - > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > - table_context->overdrive_table, true); > > - if (ret) { > > - pr_err("Failed to import over drive table!\n"); > > - return ret; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_get_od_percentage(struct smu_context *smu, > > - enum smu_clk_type clk_type) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_dpm_table *golden_table = NULL; > > - struct vega20_single_dpm_table *single_dpm_table; > > - struct vega20_single_dpm_table *golden_dpm_table; > > - int value, golden_value; > > - > > - dpm_table = smu_dpm->dpm_context; > > - golden_table = smu_dpm->golden_dpm_context; > > - > > - switch (clk_type) { > > - case SMU_OD_SCLK: > > - single_dpm_table = &(dpm_table->gfx_table); > > - golden_dpm_table = &(golden_table->gfx_table); > > - break; > > - case SMU_OD_MCLK: > > - single_dpm_table = &(dpm_table->mem_table); > > - golden_dpm_table = &(golden_table->mem_table); > > - break; > > - default: > > - return -EINVAL; > > - break; > > - } > > - > > - value = single_dpm_table->dpm_levels[single_dpm_table->count - > > 1].value; > > - golden_value = golden_dpm_table- > > >dpm_levels[golden_dpm_table->count - 1].value; > > - > > - value -= golden_value; > > - value = DIV_ROUND_UP(value * 100, golden_value); > > - > > - return value; > > -} > > - > > -static int vega20_get_power_profile_mode(struct smu_context *smu, > char > > *buf) > > -{ > > - DpmActivityMonitorCoeffInt_t activity_monitor; > > - uint32_t i, size = 0; > > - uint16_t workload_type = 0; > > - static const char *profile_name[] = { > > - "BOOTUP_DEFAULT", > > - "3D_FULL_SCREEN", > > - "POWER_SAVING", > > - "VIDEO", > > - "VR", > > - "COMPUTE", > > - "CUSTOM"}; > > - static const char *title[] = { > > - "PROFILE_INDEX(NAME)", > > - "CLOCK_TYPE(NAME)", > > - "FPS", > > - "UseRlcBusy", > > - "MinActiveFreqType", > > - "MinActiveFreq", > > - "BoosterFreqType", > > - "BoosterFreq", > > - "PD_Data_limit_c", > > - "PD_Data_error_coeff", > > - "PD_Data_error_rate_coeff"}; > > - int result = 0; > > - > > - if (!smu->pm_enabled || !buf) > > - return -EINVAL; > > - > > - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", > > - title[0], title[1], title[2], title[3], title[4], title[5], > > - title[6], title[7], title[8], title[9], title[10]); > > - > > - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { > > - /* conv PP_SMC_POWER_PROFILE* to > > WORKLOAD_PPLIB_*_BIT */ > > - workload_type = smu_workload_get_type(smu, i); > > - result = smu_update_table(smu, > > - > > SMU_TABLE_ACTIVITY_MONITOR_COEFF | workload_type << 16, > > - (void *)(&activity_monitor), false); > > - if (result) { > > - pr_err("[%s] Failed to get activity monitor!", > > __func__); > > - return result; > > - } > > - > > - size += sprintf(buf + size, "%2d %14s%s:\n", > > - i, profile_name[i], (i == smu->power_profile_mode) ? > > "*" : " "); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 0, > > - "GFXCLK", > > - activity_monitor.Gfx_FPS, > > - activity_monitor.Gfx_UseRlcBusy, > > - activity_monitor.Gfx_MinActiveFreqType, > > - activity_monitor.Gfx_MinActiveFreq, > > - activity_monitor.Gfx_BoosterFreqType, > > - activity_monitor.Gfx_BoosterFreq, > > - activity_monitor.Gfx_PD_Data_limit_c, > > - activity_monitor.Gfx_PD_Data_error_coeff, > > - activity_monitor.Gfx_PD_Data_error_rate_coeff); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 1, > > - "SOCCLK", > > - activity_monitor.Soc_FPS, > > - activity_monitor.Soc_UseRlcBusy, > > - activity_monitor.Soc_MinActiveFreqType, > > - activity_monitor.Soc_MinActiveFreq, > > - activity_monitor.Soc_BoosterFreqType, > > - activity_monitor.Soc_BoosterFreq, > > - activity_monitor.Soc_PD_Data_limit_c, > > - activity_monitor.Soc_PD_Data_error_coeff, > > - activity_monitor.Soc_PD_Data_error_rate_coeff); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 2, > > - "UCLK", > > - activity_monitor.Mem_FPS, > > - activity_monitor.Mem_UseRlcBusy, > > - activity_monitor.Mem_MinActiveFreqType, > > - activity_monitor.Mem_MinActiveFreq, > > - activity_monitor.Mem_BoosterFreqType, > > - activity_monitor.Mem_BoosterFreq, > > - activity_monitor.Mem_PD_Data_limit_c, > > - activity_monitor.Mem_PD_Data_error_coeff, > > - activity_monitor.Mem_PD_Data_error_rate_coeff); > > - > > - size += sprintf(buf + size, > > "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", > > - " ", > > - 3, > > - "FCLK", > > - activity_monitor.Fclk_FPS, > > - activity_monitor.Fclk_UseRlcBusy, > > - activity_monitor.Fclk_MinActiveFreqType, > > - activity_monitor.Fclk_MinActiveFreq, > > - activity_monitor.Fclk_BoosterFreqType, > > - activity_monitor.Fclk_BoosterFreq, > > - activity_monitor.Fclk_PD_Data_limit_c, > > - activity_monitor.Fclk_PD_Data_error_coeff, > > - activity_monitor.Fclk_PD_Data_error_rate_coeff); > > - } > > - > > - return size; > > -} > > - > > -static int vega20_set_power_profile_mode(struct smu_context *smu, > long > > *input, uint32_t size) > > -{ > > - DpmActivityMonitorCoeffInt_t activity_monitor; > > - int workload_type = 0, ret = 0; > > - > > - smu->power_profile_mode = input[size]; > > - > > - if (!smu->pm_enabled) > > - return ret; > > - if (smu->power_profile_mode > > > PP_SMC_POWER_PROFILE_CUSTOM) { > > - pr_err("Invalid power profile mode %d\n", smu- > > >power_profile_mode); > > - return -EINVAL; > > - } > > - > > - if (smu->power_profile_mode == > > PP_SMC_POWER_PROFILE_CUSTOM) { > > - ret = smu_update_table(smu, > > - SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > - (void *)(&activity_monitor), false); > > - if (ret) { > > - pr_err("[%s] Failed to get activity monitor!", > > __func__); > > - return ret; > > - } > > - > > - switch (input[0]) { > > - case 0: /* Gfxclk */ > > - activity_monitor.Gfx_FPS = input[1]; > > - activity_monitor.Gfx_UseRlcBusy = input[2]; > > - activity_monitor.Gfx_MinActiveFreqType = input[3]; > > - activity_monitor.Gfx_MinActiveFreq = input[4]; > > - activity_monitor.Gfx_BoosterFreqType = input[5]; > > - activity_monitor.Gfx_BoosterFreq = input[6]; > > - activity_monitor.Gfx_PD_Data_limit_c = input[7]; > > - activity_monitor.Gfx_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Gfx_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - case 1: /* Socclk */ > > - activity_monitor.Soc_FPS = input[1]; > > - activity_monitor.Soc_UseRlcBusy = input[2]; > > - activity_monitor.Soc_MinActiveFreqType = input[3]; > > - activity_monitor.Soc_MinActiveFreq = input[4]; > > - activity_monitor.Soc_BoosterFreqType = input[5]; > > - activity_monitor.Soc_BoosterFreq = input[6]; > > - activity_monitor.Soc_PD_Data_limit_c = input[7]; > > - activity_monitor.Soc_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Soc_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - case 2: /* Uclk */ > > - activity_monitor.Mem_FPS = input[1]; > > - activity_monitor.Mem_UseRlcBusy = input[2]; > > - activity_monitor.Mem_MinActiveFreqType = > > input[3]; > > - activity_monitor.Mem_MinActiveFreq = input[4]; > > - activity_monitor.Mem_BoosterFreqType = input[5]; > > - activity_monitor.Mem_BoosterFreq = input[6]; > > - activity_monitor.Mem_PD_Data_limit_c = input[7]; > > - activity_monitor.Mem_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Mem_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - case 3: /* Fclk */ > > - activity_monitor.Fclk_FPS = input[1]; > > - activity_monitor.Fclk_UseRlcBusy = input[2]; > > - activity_monitor.Fclk_MinActiveFreqType = input[3]; > > - activity_monitor.Fclk_MinActiveFreq = input[4]; > > - activity_monitor.Fclk_BoosterFreqType = input[5]; > > - activity_monitor.Fclk_BoosterFreq = input[6]; > > - activity_monitor.Fclk_PD_Data_limit_c = input[7]; > > - activity_monitor.Fclk_PD_Data_error_coeff = > > input[8]; > > - activity_monitor.Fclk_PD_Data_error_rate_coeff = > > input[9]; > > - break; > > - } > > - > > - ret = smu_update_table(smu, > > - SMU_TABLE_ACTIVITY_MONITOR_COEFF > > | WORKLOAD_PPLIB_CUSTOM_BIT << 16, > > - (void *)(&activity_monitor), true); > > - if (ret) { > > - pr_err("[%s] Failed to set activity monitor!", > > __func__); > > - return ret; > > - } > > - } > > - > > - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ > > - workload_type = smu_workload_get_type(smu, smu- > > >power_profile_mode); > > - smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetWorkloadMask, > > - 1 << workload_type); > > - > > - return ret; > > -} > > - > > -static int > > -vega20_get_profiling_clk_mask(struct smu_context *smu, > > - enum amd_dpm_forced_level level, > > - uint32_t *sclk_mask, > > - uint32_t *mclk_mask, > > - uint32_t *soc_mask) > > -{ > > - struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table > > *)smu->smu_dpm.dpm_context; > > - struct vega20_single_dpm_table *gfx_dpm_table; > > - struct vega20_single_dpm_table *mem_dpm_table; > > - struct vega20_single_dpm_table *soc_dpm_table; > > - > > - if (!smu->smu_dpm.dpm_context) > > - return -EINVAL; > > - > > - gfx_dpm_table = &dpm_table->gfx_table; > > - mem_dpm_table = &dpm_table->mem_table; > > - soc_dpm_table = &dpm_table->soc_table; > > - > > - *sclk_mask = 0; > > - *mclk_mask = 0; > > - *soc_mask = 0; > > - > > - if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL > > && > > - mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL > > && > > - soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { > > - *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; > > - *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; > > - *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; > > - } > > - > > - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > - *sclk_mask = 0; > > - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > - *mclk_mask = 0; > > - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - *sclk_mask = gfx_dpm_table->count - 1; > > - *mclk_mask = mem_dpm_table->count - 1; > > - *soc_mask = soc_dpm_table->count - 1; > > - } > > - > > - return 0; > > -} > > - > > -static int > > -vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu, > > - struct vega20_single_dpm_table > > *dpm_table) > > -{ > > - int ret = 0; > > - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > - if (!smu_dpm_ctx->dpm_context) > > - return -EINVAL; > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - if (dpm_table->count <= 0) { > > - pr_err("[%s] Dpm table has no entry!", __func__); > > - return -EINVAL; > > - } > > - > > - if (dpm_table->count > NUM_UCLK_DPM_LEVELS) { > > - pr_err("[%s] Dpm table has too many entries!", > > __func__); > > - return -EINVAL; > > - } > > - > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - ret = smu_send_smc_msg_with_param(smu, > > - SMU_MSG_SetHardMinByFreq, > > - (PPCLK_UCLK << 16) | dpm_table- > > >dpm_state.hard_min_level); > > - if (ret) { > > - pr_err("[%s] Set hard min uclk failed!", __func__); > > - return ret; > > - } > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_pre_display_config_changed(struct smu_context *smu) > > -{ > > - int ret = 0; > > - struct vega20_dpm_table *dpm_table = smu- > > >smu_dpm.dpm_context; > > - > > - if (!smu->smu_dpm.dpm_context) > > - return -EINVAL; > > - > > - smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, > > 0); > > - ret = vega20_set_uclk_to_highest_dpm_level(smu, > > - &dpm_table->mem_table); > > - if (ret) > > - pr_err("Failed to set uclk to highest dpm level"); > > - return ret; > > -} > > - > > -static int vega20_display_config_changed(struct smu_context *smu) > > -{ > > - int ret = 0; > > - > > - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { > > - ret = smu_write_watermarks_table(smu); > > - if (ret) { > > - pr_err("Failed to update WMTABLE!"); > > - return ret; > > - } > > - smu->watermarks_bitmap |= WATERMARKS_LOADED; > > - } > > - > > - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && > > - smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT) && > > - smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_SOCCLK_BIT)) { > > - smu_send_smc_msg_with_param(smu, > > - SMU_MSG_NumOfDisplays, > > - smu->display_config- > > >num_display); > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_apply_clocks_adjust_rules(struct smu_context *smu) > > -{ > > - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); > > - struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table > > *)(smu_dpm_ctx->dpm_context); > > - struct vega20_single_dpm_table *dpm_table; > > - bool vblank_too_short = false; > > - bool disable_mclk_switching; > > - uint32_t i, latency; > > - > > - disable_mclk_switching = ((1 < smu->display_config->num_display) > > && > > - !smu->display_config- > > >multi_monitor_in_sync) || vblank_too_short; > > - latency = smu->display_config- > > >dce_tolerable_mclk_in_active_latency; > > - > > - /* gfxclk */ > > - dpm_table = &(dpm_ctx->gfx_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table- > > >count) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[0].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - > > - /* memclk */ > > - dpm_table = &(dpm_ctx->mem_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) > > { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[0].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - > > - /* honour DAL's UCLK Hardmin */ > > - if (dpm_table->dpm_state.hard_min_level < (smu->display_config- > > >min_mem_set_clock / 100)) > > - dpm_table->dpm_state.hard_min_level = smu- > > >display_config->min_mem_set_clock / 100; > > - > > - /* Hardmin is dependent on displayconfig */ > > - if (disable_mclk_switching) { > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; > > i++) { > > - if (smu_dpm_ctx->mclk_latency_table- > > >entries[i].latency <= latency) { > > - if (dpm_table->dpm_levels[i].value >= (smu- > > >display_config->min_mem_set_clock / 100)) { > > - dpm_table- > > >dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; > > - break; > > - } > > - } > > - } > > - } > > - > > - if (smu->display_config->nb_pstate_switch_disable) > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - /* vclk */ > > - dpm_table = &(dpm_ctx->vclk_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table- > > >count) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - > > - /* dclk */ > > - dpm_table = &(dpm_ctx->dclk_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table- > > >count) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - > > - /* socclk */ > > - dpm_table = &(dpm_ctx->soc_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table- > > >count) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - > > - /* eclk */ > > - dpm_table = &(dpm_ctx->eclk_table); > > - dpm_table->dpm_state.soft_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.soft_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.hard_min_level = dpm_table- > > >dpm_levels[0].value; > > - dpm_table->dpm_state.hard_max_level = dpm_table- > > >dpm_levels[dpm_table->count - 1].value; > > - > > - if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table- > > >count) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; > > - } > > - > > - if (smu_dpm_ctx->dpm_level == > > AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { > > - dpm_table->dpm_state.soft_min_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - dpm_table->dpm_state.soft_max_level = > > dpm_table->dpm_levels[dpm_table->count - 1].value; > > - } > > - return 0; > > -} > > - > > -static int > > -vega20_notify_smc_dispaly_config(struct smu_context *smu) > > -{ > > - struct vega20_dpm_table *dpm_table = smu- > > >smu_dpm.dpm_context; > > - struct vega20_single_dpm_table *memtable = &dpm_table- > > >mem_table; > > - struct smu_clocks min_clocks = {0}; > > - struct pp_display_clock_request clock_req; > > - int ret = 0; > > - > > - min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; > > - min_clocks.dcef_clock_in_sr = smu->display_config- > > >min_dcef_deep_sleep_set_clk; > > - min_clocks.memory_clock = smu->display_config- > > >min_mem_set_clock; > > - > > - if (smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_DCEFCLK_BIT)) { > > - clock_req.clock_type = amd_pp_dcef_clock; > > - clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; > > - if (!smu->funcs->display_clock_voltage_request(smu, > > &clock_req)) { > > - if (smu_feature_is_supported(smu, > > SMU_FEATURE_DS_DCEFCLK_BIT)) { > > - ret = smu_send_smc_msg_with_param(smu, > > - > > SMU_MSG_SetMinDeepSleepDcefclk, > > - > > min_clocks.dcef_clock_in_sr/100); > > - if (ret) { > > - pr_err("Attempt to set divider for > > DCEFCLK Failed!"); > > - return ret; > > - } > > - } > > - } else { > > - pr_info("Attempt to set Hard Min for DCEFCLK > > Failed!"); > > - } > > - } > > - > > - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) > > { > > - memtable->dpm_state.hard_min_level = > > min_clocks.memory_clock/100; > > - ret = smu_send_smc_msg_with_param(smu, > > - > > SMU_MSG_SetHardMinByFreq, > > - (PPCLK_UCLK << 16) | > > memtable->dpm_state.hard_min_level); > > - if (ret) { > > - pr_err("[%s] Set hard min uclk failed!", __func__); > > - return ret; > > - } > > - } > > - > > - return 0; > > -} > > - > > -static uint32_t vega20_find_lowest_dpm_level(struct > > vega20_single_dpm_table *table) > > -{ > > - uint32_t i; > > - > > - for (i = 0; i < table->count; i++) { > > - if (table->dpm_levels[i].enabled) > > - break; > > - } > > - if (i >= table->count) { > > - i = 0; > > - table->dpm_levels[i].enabled = true; > > - } > > - > > - return i; > > -} > > - > > -static uint32_t vega20_find_highest_dpm_level(struct > > vega20_single_dpm_table *table) > > -{ > > - int i = 0; > > - > > - if (!table) { > > - pr_err("[%s] DPM Table does not exist!", __func__); > > - return 0; > > - } > > - if (table->count <= 0) { > > - pr_err("[%s] DPM Table has no entry!", __func__); > > - return 0; > > - } > > - if (table->count > MAX_REGULAR_DPM_NUMBER) { > > - pr_err("[%s] DPM Table has too many entries!", __func__); > > - return MAX_REGULAR_DPM_NUMBER - 1; > > - } > > - > > - for (i = table->count - 1; i >= 0; i--) { > > - if (table->dpm_levels[i].enabled) > > - break; > > - } > > - if (i < 0) { > > - i = 0; > > - table->dpm_levels[i].enabled = true; > > - } > > - > > - return i; > > -} > > - > > -static int vega20_force_dpm_limit_value(struct smu_context *smu, bool > > highest) > > -{ > > - uint32_t soft_level; > > - int ret = 0; > > - struct vega20_dpm_table *dpm_table = > > - (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; > > - > > - if (highest) > > - soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >gfx_table)); > > - else > > - soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >gfx_table)); > > - > > - dpm_table->gfx_table.dpm_state.soft_min_level = > > - dpm_table->gfx_table.dpm_state.soft_max_level = > > - dpm_table->gfx_table.dpm_levels[soft_level].value; > > - > > - if (highest) > > - soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >mem_table)); > > - else > > - soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >mem_table)); > > - > > - dpm_table->mem_table.dpm_state.soft_min_level = > > - dpm_table->mem_table.dpm_state.soft_max_level = > > - dpm_table->mem_table.dpm_levels[soft_level].value; > > - > > - if (highest) > > - soft_level = vega20_find_highest_dpm_level(&(dpm_table- > > >soc_table)); > > - else > > - soft_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >soc_table)); > > - > > - dpm_table->soc_table.dpm_state.soft_min_level = > > - dpm_table->soc_table.dpm_state.soft_max_level = > > - dpm_table->soc_table.dpm_levels[soft_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); > > - if (ret) { > > - pr_err("Failed to upload boot level to %s!\n", > > - highest ? "highest" : "lowest"); > > - return ret; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); > > - if (ret) { > > - pr_err("Failed to upload dpm max level to %s!\n!", > > - highest ? "highest" : "lowest"); > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_unforce_dpm_levels(struct smu_context *smu) > > -{ > > - uint32_t soft_min_level, soft_max_level; > > - int ret = 0; > > - struct vega20_dpm_table *dpm_table = > > - (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; > > - > > - soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >gfx_table)); > > - soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >gfx_table)); > > - dpm_table->gfx_table.dpm_state.soft_min_level = > > - dpm_table->gfx_table.dpm_levels[soft_min_level].value; > > - dpm_table->gfx_table.dpm_state.soft_max_level = > > - dpm_table->gfx_table.dpm_levels[soft_max_level].value; > > - > > - soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >mem_table)); > > - soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >mem_table)); > > - dpm_table->mem_table.dpm_state.soft_min_level = > > - dpm_table->gfx_table.dpm_levels[soft_min_level].value; > > - dpm_table->mem_table.dpm_state.soft_max_level = > > - dpm_table->gfx_table.dpm_levels[soft_max_level].value; > > - > > - soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table- > > >soc_table)); > > - soft_max_level = vega20_find_highest_dpm_level(&(dpm_table- > > >soc_table)); > > - dpm_table->soc_table.dpm_state.soft_min_level = > > - dpm_table->soc_table.dpm_levels[soft_min_level].value; > > - dpm_table->soc_table.dpm_state.soft_max_level = > > - dpm_table->soc_table.dpm_levels[soft_max_level].value; > > - > > - ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); > > - if (ret) { > > - pr_err("Failed to upload DPM Bootup Levels!"); > > - return ret; > > - } > > - > > - ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); > > - if (ret) { > > - pr_err("Failed to upload DPM Max Levels!"); > > - return ret; > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_update_specified_od8_value(struct smu_context *smu, > > - uint32_t index, > > - uint32_t value) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - OverDriveTable_t *od_table = > > - (OverDriveTable_t *)(table_context->overdrive_table); > > - struct vega20_od8_settings *od8_settings = > > - (struct vega20_od8_settings *)smu->od_settings; > > - > > - switch (index) { > > - case OD8_SETTING_GFXCLK_FMIN: > > - od_table->GfxclkFmin = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_FMAX: > > - if (value < od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value || > > - value > od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) > > - return -EINVAL; > > - od_table->GfxclkFmax = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_FREQ1: > > - od_table->GfxclkFreq1 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_VOLTAGE1: > > - od_table->GfxclkVolt1 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_FREQ2: > > - od_table->GfxclkFreq2 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_VOLTAGE2: > > - od_table->GfxclkVolt2 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_FREQ3: > > - od_table->GfxclkFreq3 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_GFXCLK_VOLTAGE3: > > - od_table->GfxclkVolt3 = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_UCLK_FMAX: > > - if (value < od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value || > > - value > od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) > > - return -EINVAL; > > - od_table->UclkFmax = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_POWER_PERCENTAGE: > > - od_table->OverDrivePct = (int16_t)value; > > - break; > > - > > - case OD8_SETTING_FAN_ACOUSTIC_LIMIT: > > - od_table->FanMaximumRpm = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_FAN_MIN_SPEED: > > - od_table->FanMinimumPwm = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_FAN_TARGET_TEMP: > > - od_table->FanTargetTemperature = (uint16_t)value; > > - break; > > - > > - case OD8_SETTING_OPERATING_TEMP_MAX: > > - od_table->MaxOpTemp = (uint16_t)value; > > - break; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_update_od8_settings(struct smu_context *smu, > > - uint32_t index, > > - uint32_t value) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - int ret; > > - > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > - table_context->overdrive_table, false); > > - if (ret) { > > - pr_err("Failed to export over drive table!\n"); > > - return ret; > > - } > > - > > - ret = vega20_update_specified_od8_value(smu, index, value); > > - if (ret) > > - return ret; > > - > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > - table_context->overdrive_table, true); > > - if (ret) { > > - pr_err("Failed to import over drive table!\n"); > > - return ret; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_set_od_percentage(struct smu_context *smu, > > - enum smu_clk_type clk_type, > > - uint32_t value) > > -{ > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_dpm_table *golden_table = NULL; > > - struct vega20_single_dpm_table *single_dpm_table; > > - struct vega20_single_dpm_table *golden_dpm_table; > > - uint32_t od_clk, index; > > - int ret = 0; > > - int feature_enabled; > > - PPCLK_e clk_id; > > - > > - mutex_lock(&(smu->mutex)); > > - > > - dpm_table = smu_dpm->dpm_context; > > - golden_table = smu_dpm->golden_dpm_context; > > - > > - switch (clk_type) { > > - case SMU_OD_SCLK: > > - single_dpm_table = &(dpm_table->gfx_table); > > - golden_dpm_table = &(golden_table->gfx_table); > > - feature_enabled = smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT); > > - clk_id = PPCLK_GFXCLK; > > - index = OD8_SETTING_GFXCLK_FMAX; > > - break; > > - case SMU_OD_MCLK: > > - single_dpm_table = &(dpm_table->mem_table); > > - golden_dpm_table = &(golden_table->mem_table); > > - feature_enabled = smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UCLK_BIT); > > - clk_id = PPCLK_UCLK; > > - index = OD8_SETTING_UCLK_FMAX; > > - break; > > - default: > > - ret = -EINVAL; > > - break; > > - } > > - > > - if (ret) > > - goto set_od_failed; > > - > > - od_clk = golden_dpm_table->dpm_levels[golden_dpm_table- > > >count - 1].value * value; > > - od_clk /= 100; > > - od_clk += golden_dpm_table->dpm_levels[golden_dpm_table- > > >count - 1].value; > > - > > - ret = vega20_update_od8_settings(smu, index, od_clk); > > - if (ret) { > > - pr_err("[Setoverdrive] failed to set od clk!\n"); > > - goto set_od_failed; > > - } > > - > > - if (feature_enabled) { > > - ret = vega20_set_single_dpm_table(smu, single_dpm_table, > > - clk_id); > > - if (ret) { > > - pr_err("[Setoverdrive] failed to refresh dpm > > table!\n"); > > - goto set_od_failed; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = smu- > > >smu_table.boot_values.gfxclk / 100; > > - } > > - > > - ret = smu_handle_task(smu, smu_dpm->dpm_level, > > - AMD_PP_TASK_READJUST_POWER_STATE); > > - > > -set_od_failed: > > - mutex_unlock(&(smu->mutex)); > > - > > - return ret; > > -} > > - > > -static int vega20_odn_edit_dpm_table(struct smu_context *smu, > > - enum PP_OD_DPM_TABLE_COMMAND > > type, > > - long *input, uint32_t size) > > -{ > > - struct smu_table_context *table_context = &smu->smu_table; > > - OverDriveTable_t *od_table = > > - (OverDriveTable_t *)(table_context->overdrive_table); > > - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; > > - struct vega20_dpm_table *dpm_table = NULL; > > - struct vega20_single_dpm_table *single_dpm_table; > > - struct vega20_od8_settings *od8_settings = > > - (struct vega20_od8_settings *)smu->od_settings; > > - struct pp_clock_levels_with_latency clocks; > > - int32_t input_index, input_clk, input_vol, i; > > - int od8_id; > > - int ret = 0; > > - > > - dpm_table = smu_dpm->dpm_context; > > - > > - if (!input) { > > - pr_warn("NULL user input for clock and voltage\n"); > > - return -EINVAL; > > - } > > - > > - switch (type) { > > - case PP_OD_EDIT_SCLK_VDDC_TABLE: > > - if (!(od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) { > > - pr_info("Sclk min/max frequency overdrive not > > supported\n"); > > - return -EOPNOTSUPP; > > - } > > - > > - for (i = 0; i < size; i += 2) { > > - if (i + 2 > size) { > > - pr_info("invalid number of input > > parameters %d\n", size); > > - return -EINVAL; > > - } > > - > > - input_index = input[i]; > > - input_clk = input[i + 1]; > > - > > - if (input_index != 0 && input_index != 1) { > > - pr_info("Invalid index %d\n", input_index); > > - pr_info("Support min/max sclk frequency > > settingonly which index by 0/1\n"); > > - return -EINVAL; > > - } > > - > > - if (input_clk < od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value || > > - input_clk > od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) { > > - pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > - input_clk, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); > > - return -EINVAL; > > - } > > - > > - if (input_index == 0 && od_table->GfxclkFmin != > > input_clk) { > > - od_table->GfxclkFmin = input_clk; > > - od8_settings->od_gfxclk_update = true; > > - } else if (input_index == 1 && od_table- > > >GfxclkFmax != input_clk) { > > - od_table->GfxclkFmax = input_clk; > > - od8_settings->od_gfxclk_update = true; > > - } > > - } > > - > > - break; > > - > > - case PP_OD_EDIT_MCLK_VDDC_TABLE: > > - if (!od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { > > - pr_info("Mclk max frequency overdrive not > > supported\n"); > > - return -EOPNOTSUPP; > > - } > > - > > - single_dpm_table = &(dpm_table->mem_table); > > - ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); > > - if (ret) { > > - pr_err("Attempt to get memory clk levels Failed!"); > > - return ret; > > - } > > - > > - for (i = 0; i < size; i += 2) { > > - if (i + 2 > size) { > > - pr_info("invalid number of input > > parameters %d\n", > > - size); > > - return -EINVAL; > > - } > > - > > - input_index = input[i]; > > - input_clk = input[i + 1]; > > - > > - if (input_index != 1) { > > - pr_info("Invalid index %d\n", input_index); > > - pr_info("Support max Mclk frequency setting > > only which index by 1\n"); > > - return -EINVAL; > > - } > > - > > - if (input_clk < clocks.data[0].clocks_in_khz / 1000 || > > - input_clk > od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) { > > - pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > - input_clk, > > - clocks.data[0].clocks_in_khz / 1000, > > - od8_settings- > > >od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); > > - return -EINVAL; > > - } > > - > > - if (input_index == 1 && od_table->UclkFmax != > > input_clk) { > > - od8_settings->od_gfxclk_update = true; > > - od_table->UclkFmax = input_clk; > > - } > > - } > > - > > - break; > > - > > - case PP_OD_EDIT_VDDC_CURVE: > > - if (!(od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && > > - od8_settings- > > >od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { > > - pr_info("Voltage curve calibrate not supported\n"); > > - return -EOPNOTSUPP; > > - } > > - > > - for (i = 0; i < size; i += 3) { > > - if (i + 3 > size) { > > - pr_info("invalid number of input > > parameters %d\n", > > - size); > > - return -EINVAL; > > - } > > - > > - input_index = input[i]; > > - input_clk = input[i + 1]; > > - input_vol = input[i + 2]; > > - > > - if (input_index > 2) { > > - pr_info("Setting for point %d is not > > supported\n", > > - input_index + 1); > > - pr_info("Three supported points index by 0, > > 1, 2\n"); > > - return -EINVAL; > > - } > > - > > - od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * > > input_index; > > - if (input_clk < od8_settings- > > >od8_settings_array[od8_id].min_value || > > - input_clk > od8_settings- > > >od8_settings_array[od8_id].max_value) { > > - pr_info("clock freq %d is not within allowed > > range [%d - %d]\n", > > - input_clk, > > - od8_settings- > > >od8_settings_array[od8_id].min_value, > > - od8_settings- > > >od8_settings_array[od8_id].max_value); > > - return -EINVAL; > > - } > > - > > - od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * > > input_index; > > - if (input_vol < od8_settings- > > >od8_settings_array[od8_id].min_value || > > - input_vol > od8_settings- > > >od8_settings_array[od8_id].max_value) { > > - pr_info("clock voltage %d is not within > > allowed range [%d- %d]\n", > > - input_vol, > > - od8_settings- > > >od8_settings_array[od8_id].min_value, > > - od8_settings- > > >od8_settings_array[od8_id].max_value); > > - return -EINVAL; > > - } > > - > > - switch (input_index) { > > - case 0: > > - od_table->GfxclkFreq1 = input_clk; > > - od_table->GfxclkVolt1 = input_vol * > > VOLTAGE_SCALE; > > - break; > > - case 1: > > - od_table->GfxclkFreq2 = input_clk; > > - od_table->GfxclkVolt2 = input_vol * > > VOLTAGE_SCALE; > > - break; > > - case 2: > > - od_table->GfxclkFreq3 = input_clk; > > - od_table->GfxclkVolt3 = input_vol * > > VOLTAGE_SCALE; > > - break; > > - } > > - } > > - > > - break; > > - > > - case PP_OD_RESTORE_DEFAULT_TABLE: > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > table_context->overdrive_table, false); > > - if (ret) { > > - pr_err("Failed to export over drive table!\n"); > > - return ret; > > - } > > - > > - break; > > - > > - case PP_OD_COMMIT_DPM_TABLE: > > - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, > > table_context->overdrive_table, true); > > - if (ret) { > > - pr_err("Failed to import over drive table!\n"); > > - return ret; > > - } > > - > > - /* retrieve updated gfxclk table */ > > - if (od8_settings->od_gfxclk_update) { > > - od8_settings->od_gfxclk_update = false; > > - single_dpm_table = &(dpm_table->gfx_table); > > - > > - if (smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_GFXCLK_BIT)) { > > - ret = vega20_set_single_dpm_table(smu, > > single_dpm_table, > > - > > PPCLK_GFXCLK); > > - if (ret) { > > - pr_err("[Setoverdrive] failed to > > refresh dpm table!\n"); > > - return ret; > > - } > > - } else { > > - single_dpm_table->count = 1; > > - single_dpm_table->dpm_levels[0].value = > > smu->smu_table.boot_values.gfxclk / 100; > > - } > > - } > > - > > - break; > > - > > - default: > > - return -EINVAL; > > - } > > - > > - if (type == PP_OD_COMMIT_DPM_TABLE) { > > - mutex_lock(&(smu->mutex)); > > - ret = smu_handle_task(smu, smu_dpm->dpm_level, > > - > > AMD_PP_TASK_READJUST_POWER_STATE); > > - mutex_unlock(&(smu->mutex)); > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool > > enable) > > -{ > > - if (!smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_UVD_BIT)) > > - return 0; > > - > > - if (enable == smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT)) > > - return 0; > > - > > - return smu_feature_set_enabled(smu, > > SMU_FEATURE_DPM_UVD_BIT, enable); > > -} > > - > > -static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool > > enable) > > -{ > > - if (!smu_feature_is_supported(smu, > > SMU_FEATURE_DPM_VCE_BIT)) > > - return 0; > > - > > - if (enable == smu_feature_is_enabled(smu, > > SMU_FEATURE_DPM_VCE_BIT)) > > - return 0; > > - > > - return smu_feature_set_enabled(smu, > > SMU_FEATURE_DPM_VCE_BIT, enable); > > -} > > - > > -static int vega20_get_enabled_smc_features(struct smu_context *smu, > > - uint64_t *features_enabled) > > -{ > > - uint32_t feature_mask[2] = {0, 0}; > > - int ret = 0; > > - > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - if (ret) > > - return ret; > > - > > - *features_enabled = ((((uint64_t)feature_mask[0] << > > SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | > > - (((uint64_t)feature_mask[1] << > > SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); > > - > > - return ret; > > -} > > - > > -static int vega20_enable_smc_features(struct smu_context *smu, > > - bool enable, uint64_t feature_mask) > > -{ > > - uint32_t smu_features_low, smu_features_high; > > - int ret = 0; > > - > > - smu_features_low = (uint32_t)((feature_mask & > > SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); > > - smu_features_high = (uint32_t)((feature_mask & > > SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); > > - > > - if (enable) { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesLow, > > - smu_features_low); > > - if (ret) > > - return ret; > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_EnableSmuFeaturesHigh, > > - smu_features_high); > > - if (ret) > > - return ret; > > - } else { > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesLow, > > - smu_features_low); > > - if (ret) > > - return ret; > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_DisableSmuFeaturesHigh, > > - smu_features_high); > > - if (ret) > > - return ret; > > - } > > - > > - return 0; > > - > > -} > > - > > -static int vega20_get_ppfeature_status(struct smu_context *smu, char > > *buf) > > -{ > > - static const char *ppfeature_name[] = { > > - "DPM_PREFETCHER", > > - "GFXCLK_DPM", > > - "UCLK_DPM", > > - "SOCCLK_DPM", > > - "UVD_DPM", > > - "VCE_DPM", > > - "ULV", > > - "MP0CLK_DPM", > > - "LINK_DPM", > > - "DCEFCLK_DPM", > > - "GFXCLK_DS", > > - "SOCCLK_DS", > > - "LCLK_DS", > > - "PPT", > > - "TDC", > > - "THERMAL", > > - "GFX_PER_CU_CG", > > - "RM", > > - "DCEFCLK_DS", > > - "ACDC", > > - "VR0HOT", > > - "VR1HOT", > > - "FW_CTF", > > - "LED_DISPLAY", > > - "FAN_CONTROL", > > - "GFX_EDC", > > - "GFXOFF", > > - "CG", > > - "FCLK_DPM", > > - "FCLK_DS", > > - "MP1CLK_DS", > > - "MP0CLK_DS", > > - "XGMI", > > - "ECC"}; > > - static const char *output_title[] = { > > - "FEATURES", > > - "BITMASK", > > - "ENABLEMENT"}; > > - uint64_t features_enabled; > > - int i; > > - int ret = 0; > > - int size = 0; > > - > > - ret = vega20_get_enabled_smc_features(smu, &features_enabled); > > - if (ret) > > - return ret; > > - > > - size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", > > features_enabled); > > - size += sprintf(buf + size, "%-19s %-22s %s\n", > > - output_title[0], > > - output_title[1], > > - output_title[2]); > > - for (i = 0; i < GNLD_FEATURES_MAX; i++) { > > - size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", > > - ppfeature_name[i], > > - 1ULL << i, > > - (features_enabled & (1ULL << i)) ? > > "Y" : "N"); > > - } > > - > > - return size; > > -} > > - > > -static int vega20_set_ppfeature_status(struct smu_context *smu, > uint64_t > > new_ppfeature_masks) > > -{ > > - uint64_t features_enabled; > > - uint64_t features_to_enable; > > - uint64_t features_to_disable; > > - int ret = 0; > > - > > - if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) > > - return -EINVAL; > > - > > - ret = vega20_get_enabled_smc_features(smu, &features_enabled); > > - if (ret) > > - return ret; > > - > > - features_to_disable = > > - features_enabled & ~new_ppfeature_masks; > > - features_to_enable = > > - ~features_enabled & new_ppfeature_masks; > > - > > - pr_debug("features_to_disable 0x%llx\n", features_to_disable); > > - pr_debug("features_to_enable 0x%llx\n", features_to_enable); > > - > > - if (features_to_disable) { > > - ret = vega20_enable_smc_features(smu, false, > > features_to_disable); > > - if (ret) > > - return ret; > > - } > > - > > - if (features_to_enable) { > > - ret = vega20_enable_smc_features(smu, true, > > features_to_enable); > > - if (ret) > > - return ret; > > - } > > - > > - return 0; > > -} > > - > > -static bool vega20_is_dpm_running(struct smu_context *smu) > > -{ > > - int ret = 0; > > - uint32_t feature_mask[2]; > > - unsigned long feature_enabled; > > - ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); > > - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | > > - ((uint64_t)feature_mask[1] << 32)); > > - return !!(feature_enabled & SMC_DPM_FEATURE); > > -} > > - > > -static int vega20_set_thermal_fan_table(struct smu_context *smu) > > -{ > > - int ret; > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *pptable = table_context->driver_pptable; > > - > > - ret = smu_send_smc_msg_with_param(smu, > > SMU_MSG_SetFanTemperatureTarget, > > - (uint32_t)pptable->FanTargetTemperature); > > - > > - return ret; > > -} > > - > > -static int vega20_get_fan_speed_percent(struct smu_context *smu, > > - uint32_t *speed) > > -{ > > - int ret = 0; > > - uint32_t percent = 0; > > - uint32_t current_rpm; > > - PPTable_t *pptable = smu->smu_table.driver_pptable; > > - > > - ret = smu_get_current_rpm(smu, ¤t_rpm); > > - percent = current_rpm * 100 / pptable->FanMaximumRpm; > > - *speed = percent > 100 ? 100 : percent; > > - > > - return ret; > > -} > > - > > -static int vega20_get_gpu_power(struct smu_context *smu, uint32_t > > *value) > > -{ > > - int ret = 0; > > - SmuMetrics_t metrics; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = vega20_get_metrics_table(smu, &metrics); > > - if (ret) > > - return ret; > > - > > - *value = metrics.CurrSocketPower << 8; > > - > > - return 0; > > -} > > - > > -static int vega20_get_current_activity_percent(struct smu_context *smu, > > - enum amd_pp_sensors sensor, > > - uint32_t *value) > > -{ > > - int ret = 0; > > - SmuMetrics_t metrics; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = vega20_get_metrics_table(smu, &metrics); > > - if (ret) > > - return ret; > > - > > - switch (sensor) { > > - case AMDGPU_PP_SENSOR_GPU_LOAD: > > - *value = metrics.AverageGfxActivity; > > - break; > > - case AMDGPU_PP_SENSOR_MEM_LOAD: > > - *value = metrics.AverageUclkActivity; > > - break; > > - default: > > - pr_err("Invalid sensor for retrieving clock activity\n"); > > - return -EINVAL; > > - } > > - > > - return 0; > > -} > > - > > -static int vega20_thermal_get_temperature(struct smu_context *smu, > > - enum amd_pp_sensors sensor, > > - uint32_t *value) > > -{ > > - struct amdgpu_device *adev = smu->adev; > > - SmuMetrics_t metrics; > > - uint32_t temp = 0; > > - int ret = 0; > > - > > - if (!value) > > - return -EINVAL; > > - > > - ret = vega20_get_metrics_table(smu, &metrics); > > - if (ret) > > - return ret; > > - > > - switch (sensor) { > > - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: > > - temp = RREG32_SOC15(THM, 0, > > mmCG_MULT_THERMAL_STATUS); > > - temp = (temp & > > CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> > > - > > CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; > > - > > - temp = temp & 0x1ff; > > - temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - > > - *value = temp; > > - break; > > - case AMDGPU_PP_SENSOR_EDGE_TEMP: > > - *value = metrics.TemperatureEdge * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - break; > > - case AMDGPU_PP_SENSOR_MEM_TEMP: > > - *value = metrics.TemperatureHBM * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - break; > > - default: > > - pr_err("Invalid sensor for retrieving temp\n"); > > - return -EINVAL; > > - } > > - > > - return 0; > > -} > > -static int vega20_read_sensor(struct smu_context *smu, > > - enum amd_pp_sensors sensor, > > - void *data, uint32_t *size) > > -{ > > - int ret = 0; > > - struct smu_table_context *table_context = &smu->smu_table; > > - PPTable_t *pptable = table_context->driver_pptable; > > - > > - switch (sensor) { > > - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: > > - *(uint32_t *)data = pptable->FanMaximumRpm; > > - *size = 4; > > - break; > > - case AMDGPU_PP_SENSOR_MEM_LOAD: > > - case AMDGPU_PP_SENSOR_GPU_LOAD: > > - ret = vega20_get_current_activity_percent(smu, > > - sensor, > > - (uint32_t *)data); > > - *size = 4; > > - break; > > - case AMDGPU_PP_SENSOR_GPU_POWER: > > - ret = vega20_get_gpu_power(smu, (uint32_t *)data); > > - *size = 4; > > - break; > > - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: > > - case AMDGPU_PP_SENSOR_EDGE_TEMP: > > - case AMDGPU_PP_SENSOR_MEM_TEMP: > > - ret = vega20_thermal_get_temperature(smu, sensor, > > (uint32_t *)data); > > - *size = 4; > > - break; > > - default: > > - return -EINVAL; > > - } > > - > > - return ret; > > -} > > - > > -static int vega20_set_watermarks_table(struct smu_context *smu, > > - void *watermarks, struct > > - > > dm_pp_wm_sets_with_clock_ranges_soc15 > > - *clock_ranges) > > -{ > > - int i; > > - Watermarks_t *table = watermarks; > > - > > - if (!table || !clock_ranges) > > - return -EINVAL; > > - > > - if (clock_ranges->num_wm_dmif_sets > 4 || > > - clock_ranges->num_wm_mcif_sets > 4) > > - return -EINVAL; > > - > > - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { > > - table->WatermarkRow[1][i].MinClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MaxClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MinUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].MaxUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[1][i].WmSetting = (uint8_t) > > - clock_ranges- > > >wm_dmif_clocks_ranges[i].wm_set_id; > > - } > > - > > - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { > > - table->WatermarkRow[0][i].MinClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MaxClock = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MinUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].MaxUclk = > > - cpu_to_le16((uint16_t) > > - (clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / > > - 1000)); > > - table->WatermarkRow[0][i].WmSetting = (uint8_t) > > - clock_ranges- > > >wm_mcif_clocks_ranges[i].wm_set_id; > > - } > > - > > - return 0; > > -} > > - > > -static const struct smu_temperature_range vega20_thermal_policy[] = > > -{ > > - {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, > > - { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, > > 120000}, > > -}; > > - > > -static int vega20_get_thermal_temperature_range(struct smu_context > > *smu, > > - struct > > smu_temperature_range*range) > > -{ > > - > > - PPTable_t *pptable = smu->smu_table.driver_pptable; > > - > > - if (!range) > > - return -EINVAL; > > - > > - memcpy(range, &vega20_thermal_policy[0], sizeof(struct > > smu_temperature_range)); > > - > > - range->max = pptable->TedgeLimit * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - range->edge_emergency_max = (pptable->TedgeLimit + > > CTF_OFFSET_EDGE) * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - range->hotspot_crit_max = pptable->ThotspotLimit * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - range->hotspot_emergency_max = (pptable->ThotspotLimit + > > CTF_OFFSET_HOTSPOT) * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - range->mem_crit_max = pptable->ThbmLimit * > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - range->mem_emergency_max = (pptable->ThbmLimit + > > CTF_OFFSET_HBM)* > > - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; > > - > > - > > - return 0; > > -} > > - > > -static const struct pptable_funcs vega20_ppt_funcs = { > > - .tables_init = vega20_tables_init, > > - .alloc_dpm_context = vega20_allocate_dpm_context, > > - .store_powerplay_table = vega20_store_powerplay_table, > > - .check_powerplay_table = vega20_check_powerplay_table, > > - .append_powerplay_table = vega20_append_powerplay_table, > > - .get_smu_msg_index = vega20_get_smu_msg_index, > > - .get_smu_clk_index = vega20_get_smu_clk_index, > > - .get_smu_feature_index = vega20_get_smu_feature_index, > > - .get_smu_table_index = vega20_get_smu_table_index, > > - .get_smu_power_index = vega20_get_pwr_src_index, > > - .get_workload_type = vega20_get_workload_type, > > - .run_afll_btc = vega20_run_btc_afll, > > - .get_allowed_feature_mask = vega20_get_allowed_feature_mask, > > - .get_current_power_state = vega20_get_current_power_state, > > - .set_default_dpm_table = vega20_set_default_dpm_table, > > - .set_power_state = NULL, > > - .populate_umd_state_clk = vega20_populate_umd_state_clk, > > - .print_clk_levels = vega20_print_clk_levels, > > - .force_clk_levels = vega20_force_clk_levels, > > - .get_clock_by_type_with_latency = > > vega20_get_clock_by_type_with_latency, > > - .get_od_percentage = vega20_get_od_percentage, > > - .get_power_profile_mode = vega20_get_power_profile_mode, > > - .set_power_profile_mode = vega20_set_power_profile_mode, > > - .set_od_percentage = vega20_set_od_percentage, > > - .set_default_od_settings = vega20_set_default_od_settings, > > - .od_edit_dpm_table = vega20_odn_edit_dpm_table, > > - .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable, > > - .dpm_set_vce_enable = vega20_dpm_set_vce_enable, > > - .read_sensor = vega20_read_sensor, > > - .pre_display_config_changed = vega20_pre_display_config_changed, > > - .display_config_changed = vega20_display_config_changed, > > - .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, > > - .notify_smc_dispaly_config = vega20_notify_smc_dispaly_config, > > - .force_dpm_limit_value = vega20_force_dpm_limit_value, > > - .unforce_dpm_levels = vega20_unforce_dpm_levels, > > - .get_profiling_clk_mask = vega20_get_profiling_clk_mask, > > - .set_ppfeature_status = vega20_set_ppfeature_status, > > - .get_ppfeature_status = vega20_get_ppfeature_status, > > - .is_dpm_running = vega20_is_dpm_running, > > - .set_thermal_fan_table = vega20_set_thermal_fan_table, > > - .get_fan_speed_percent = vega20_get_fan_speed_percent, > > - .set_watermarks_table = vega20_set_watermarks_table, > > - .get_thermal_temperature_range = > > vega20_get_thermal_temperature_range > > -}; > > - > > -void vega20_set_ppt_funcs(struct smu_context *smu) > > -{ > > - struct smu_table_context *smu_table = &smu->smu_table; > > - > > - smu->ppt_funcs = &vega20_ppt_funcs; > > - smu->smc_if_version = SMU11_DRIVER_IF_VERSION; > > - smu_table->table_count = TABLE_COUNT; > > -} > > diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.h > > b/drivers/gpu/drm/amd/powerplay/vega20_ppt.h > > deleted file mode 100644 > > index 2dc10e4..0000000 > > --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.h > > +++ /dev/null > > @@ -1,179 +0,0 @@ > > -/* > > - * Copyright 2019 Advanced Micro Devices, Inc. > > - * > > - * Permission is hereby granted, free of charge, to any person obtaining a > > - * copy of this software and associated documentation files (the > "Software"), > > - * to deal in the Software without restriction, including without limitation > > - * the rights to use, copy, modify, merge, publish, distribute, sublicense, > > - * and/or sell copies of the Software, and to permit persons to whom the > > - * Software is furnished to do so, subject to the following conditions: > > - * > > - * The above copyright notice and this permission notice shall be included > in > > - * all copies or substantial portions of the Software. > > - * > > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, > > EXPRESS OR > > - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > > MERCHANTABILITY, > > - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO > > EVENT SHALL > > - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > > DAMAGES OR > > - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > > OTHERWISE, > > - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR > > THE USE OR > > - * OTHER DEALINGS IN THE SOFTWARE. > > - * > > - */ > > -#ifndef __VEGA20_PPT_H__ > > -#define __VEGA20_PPT_H__ > > - > > -#define VEGA20_UMD_PSTATE_GFXCLK_LEVEL 0x3 > > -#define VEGA20_UMD_PSTATE_SOCCLK_LEVEL 0x3 > > -#define VEGA20_UMD_PSTATE_MCLK_LEVEL 0x2 > > -#define VEGA20_UMD_PSTATE_UVDCLK_LEVEL 0x3 > > -#define VEGA20_UMD_PSTATE_VCEMCLK_LEVEL 0x3 > > - > > -#define MAX_REGULAR_DPM_NUMBER 16 > > -#define MAX_PCIE_CONF 2 > > - > > -#define VOLTAGE_SCALE 4 > > -#define AVFS_CURVE 0 > > -#define OD8_HOTCURVE_TEMPERATURE 85 > > - > > -#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF > > -#define SMU_FEATURES_LOW_SHIFT 0 > > -#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 > > -#define SMU_FEATURES_HIGH_SHIFT 32 > > - > > -enum { > > - GNLD_DPM_PREFETCHER = 0, > > - GNLD_DPM_GFXCLK, > > - GNLD_DPM_UCLK, > > - GNLD_DPM_SOCCLK, > > - GNLD_DPM_UVD, > > - GNLD_DPM_VCE, > > - GNLD_ULV, > > - GNLD_DPM_MP0CLK, > > - GNLD_DPM_LINK, > > - GNLD_DPM_DCEFCLK, > > - GNLD_DS_GFXCLK, > > - GNLD_DS_SOCCLK, > > - GNLD_DS_LCLK, > > - GNLD_PPT, > > - GNLD_TDC, > > - GNLD_THERMAL, > > - GNLD_GFX_PER_CU_CG, > > - GNLD_RM, > > - GNLD_DS_DCEFCLK, > > - GNLD_ACDC, > > - GNLD_VR0HOT, > > - GNLD_VR1HOT, > > - GNLD_FW_CTF, > > - GNLD_LED_DISPLAY, > > - GNLD_FAN_CONTROL, > > - GNLD_DIDT, > > - GNLD_GFXOFF, > > - GNLD_CG, > > - GNLD_DPM_FCLK, > > - GNLD_DS_FCLK, > > - GNLD_DS_MP1CLK, > > - GNLD_DS_MP0CLK, > > - GNLD_XGMI, > > - GNLD_ECC, > > - > > - GNLD_FEATURES_MAX > > -}; > > - > > -struct vega20_dpm_level { > > - bool enabled; > > - uint32_t value; > > - uint32_t param1; > > -}; > > - > > -struct vega20_dpm_state { > > - uint32_t soft_min_level; > > - uint32_t soft_max_level; > > - uint32_t hard_min_level; > > - uint32_t hard_max_level; > > -}; > > - > > -struct vega20_single_dpm_table { > > - uint32_t count; > > - struct vega20_dpm_state dpm_state; > > - struct vega20_dpm_level > dpm_levels[MAX_REGULAR_DPM_NUMBER]; > > -}; > > - > > -struct vega20_pcie_table { > > - uint16_t count; > > - uint8_t pcie_gen[MAX_PCIE_CONF]; > > - uint8_t pcie_lane[MAX_PCIE_CONF]; > > - uint32_t lclk[MAX_PCIE_CONF]; > > -}; > > - > > -struct vega20_dpm_table { > > - struct vega20_single_dpm_table soc_table; > > - struct vega20_single_dpm_table gfx_table; > > - struct vega20_single_dpm_table mem_table; > > - struct vega20_single_dpm_table eclk_table; > > - struct vega20_single_dpm_table vclk_table; > > - struct vega20_single_dpm_table dclk_table; > > - struct vega20_single_dpm_table dcef_table; > > - struct vega20_single_dpm_table pixel_table; > > - struct vega20_single_dpm_table display_table; > > - struct vega20_single_dpm_table phy_table; > > - struct vega20_single_dpm_table fclk_table; > > - struct vega20_pcie_table pcie_table; > > -}; > > - > > -enum OD8_FEATURE_ID > > -{ > > - OD8_GFXCLK_LIMITS = 1 << 0, > > - OD8_GFXCLK_CURVE = 1 << 1, > > - OD8_UCLK_MAX = 1 << 2, > > - OD8_POWER_LIMIT = 1 << 3, > > - OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm > > - OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm > > - OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature > > - OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp > > - OD8_MEMORY_TIMING_TUNE = 1 << 8, > > - OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 > > -}; > > - > > -enum OD8_SETTING_ID > > -{ > > - OD8_SETTING_GFXCLK_FMIN = 0, > > - OD8_SETTING_GFXCLK_FMAX, > > - OD8_SETTING_GFXCLK_FREQ1, > > - OD8_SETTING_GFXCLK_VOLTAGE1, > > - OD8_SETTING_GFXCLK_FREQ2, > > - OD8_SETTING_GFXCLK_VOLTAGE2, > > - OD8_SETTING_GFXCLK_FREQ3, > > - OD8_SETTING_GFXCLK_VOLTAGE3, > > - OD8_SETTING_UCLK_FMAX, > > - OD8_SETTING_POWER_PERCENTAGE, > > - OD8_SETTING_FAN_ACOUSTIC_LIMIT, > > - OD8_SETTING_FAN_MIN_SPEED, > > - OD8_SETTING_FAN_TARGET_TEMP, > > - OD8_SETTING_OPERATING_TEMP_MAX, > > - OD8_SETTING_AC_TIMING, > > - OD8_SETTING_FAN_ZERO_RPM_CONTROL, > > - OD8_SETTING_COUNT > > -}; > > - > > -struct vega20_od8_single_setting { > > - uint32_t feature_id; > > - int32_t min_value; > > - int32_t max_value; > > - int32_t current_value; > > - int32_t default_value; > > -}; > > - > > -struct vega20_od8_settings { > > - struct vega20_od8_single_setting > > od8_settings_array[OD8_SETTING_COUNT]; > > - uint8_t *od_feature_capabilities; > > - uint32_t *od_settings_max; > > - uint32_t *od_settings_min; > > - void *od8_settings; > > - bool od_gfxclk_update; > > - bool od_memclk_update; > > -}; > > - > > -extern void vega20_set_ppt_funcs(struct smu_context *smu); > > - > > -#endif > > -- > > 2.7.4 > > > > _______________________________________________ > > amd-gfx mailing list > > amd-gfx@xxxxxxxxxxxxxxxxxxxxx > > https://lists.freedesktop.org/mailman/listinfo/amd-gfx _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx