diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2020-08-06 14:15:47 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2020-08-06 14:15:47 +0300 |
commit | 94fb1afb14c4f0ceb8c5508ddddac6819f662e95 (patch) | |
tree | 4988e5769dc7482caa7f441475ae31f50bbd37ef /drivers/gpu/drm/amd/powerplay/navi10_ppt.c | |
parent | c4735d990268399da9133b0ad445e488ece009ad (diff) | |
parent | 47ec5303d73ea344e84f46660fff693c57641386 (diff) | |
download | linux-94fb1afb14c4f0ceb8c5508ddddac6819f662e95.tar.xz |
Mgerge remote-tracking branch 'torvalds/master' into perf/core
To sync headers, for instance, in this case tools/perf was ahead of
upstream till Linus merged tip/perf/core to get the
PERF_RECORD_TEXT_POKE changes:
Warning: Kernel ABI header at 'tools/include/uapi/linux/perf_event.h' differs from latest version at 'include/uapi/linux/perf_event.h'
diff -u tools/include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/navi10_ppt.c')
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 1911 |
1 files changed, 1072 insertions, 839 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 0c9be864d072..6aaf483858a0 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -21,13 +21,16 @@ * */ +#define SWSMU_CODE_LAYER_L2 + #include <linux/firmware.h> #include <linux/pci.h> +#include <linux/i2c.h> #include "amdgpu.h" #include "amdgpu_smu.h" -#include "smu_internal.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" #include "soc15_common.h" #include "smu_v11_0.h" #include "smu11_driver_if_navi10.h" @@ -37,8 +40,23 @@ #include "smu_v11_0_ppsmc.h" #include "nbio/nbio_2_3_offset.h" #include "nbio/nbio_2_3_sh_mask.h" +#include "thm/thm_11_0_2_offset.h" +#include "thm/thm_11_0_2_sh_mask.h" #include "asic_reg/mp/mp_11_0_sh_mask.h" +#include "smu_cmn.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ @@ -51,81 +69,78 @@ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) -#define MSG_MAP(msg, index) \ - [SMU_MSG_##msg] = {1, (index)} - -static struct smu_11_0_cmn2aisc_mapping 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), - MSG_MAP(ArmD3, PPSMC_MSG_ArmD3), - MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange), - MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange), - MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm), - MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive), +static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), + MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0), + MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0), + MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), + MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), + MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1), + MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1), + MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), + MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 0), + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), + MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), + MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0), + MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 0), + MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 0), + MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 0), + MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0), + MSG_MAP(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 0), + MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0), + MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), + MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 0), + MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 0), + MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), + MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0), + MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0), + MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0), + MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0), + MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), + MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), + MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), + MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0), + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), + MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0), + MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0), + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), + MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), + MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), + MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0), + MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), + MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange, 0), + MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0), + MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), + MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), }; -static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = { +static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { CLK_MAP(GFXCLK, PPCLK_GFXCLK), CLK_MAP(SCLK, PPCLK_GFXCLK), CLK_MAP(SOCCLK, PPCLK_SOCCLK), @@ -140,7 +155,7 @@ static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = { CLK_MAP(PHYCLK, PPCLK_PHYCLK), }; -static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = { +static struct cmn2asic_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = { FEA_MAP(DPM_PREFETCHER), FEA_MAP(DPM_GFXCLK), FEA_MAP(DPM_GFX_PACE), @@ -186,7 +201,7 @@ static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUN FEA_MAP(APCC_DFLL), }; -static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = { +static struct cmn2asic_mapping navi10_table_map[SMU_TABLE_COUNT] = { TAB_MAP(PPTABLE), TAB_MAP(WATERMARKS), TAB_MAP(AVFS), @@ -201,12 +216,12 @@ static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = { TAB_MAP(PACE), }; -static struct smu_11_0_cmn2aisc_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { +static struct cmn2asic_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { PWR_MAP(AC), PWR_MAP(DC), }; -static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { +static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { 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), @@ -216,97 +231,6 @@ static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE 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) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (index >= SMU_MSG_MAX_COUNT) - return -EINVAL; - - mapping = navi10_message_map[index]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - -static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (index >= SMU_CLK_COUNT) - return -EINVAL; - - mapping = navi10_clk_map[index]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - -static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (index >= SMU_FEATURE_COUNT) - return -EINVAL; - - mapping = navi10_feature_mask_map[index]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - -static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (index >= SMU_TABLE_COUNT) - return -EINVAL; - - mapping = navi10_table_map[index]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - -static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (index >= SMU_POWER_SOURCE_COUNT) - return -EINVAL; - - mapping = navi10_pwr_src_map[index]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - - -static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile) -{ - struct smu_11_0_cmn2aisc_mapping mapping; - - if (profile > PP_SMC_POWER_PROFILE_CUSTOM) - return -EINVAL; - - mapping = navi10_workload_map[profile]; - if (!(mapping.valid_mapping)) { - return -EINVAL; - } - - return mapping.map_to; -} - static bool is_asic_secure(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -414,6 +338,29 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, static int navi10_check_powerplay_table(struct smu_context *smu) { + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) + smu->dc_controlled_by_gpio = true; + + mutex_lock(&smu_baco->mutex); + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || + powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) + smu_baco->platform_support = true; + mutex_unlock(&smu_baco->mutex); + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + /* + * Instead of having its own buffer space and get overdrive_table copied, + * smu->od_settings just points to the actual overdrive_table + */ + smu->od_settings = &powerplay_table->overdrive_table; + return 0; } @@ -429,17 +376,17 @@ static int navi10_append_powerplay_table(struct smu_context *smu) 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, + ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, (uint8_t **)&smc_dpm_table); if (ret) return ret; - pr_info("smc_dpm_info table revision(format.content): %d.%d\n", + dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n", smc_dpm_table->table_header.format_revision, smc_dpm_table->table_header.content_revision); if (smc_dpm_table->table_header.format_revision != 4) { - pr_err("smc_dpm_info table format revision is not 4!\n"); + dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n"); return -EINVAL; } @@ -449,7 +396,7 @@ static int navi10_append_powerplay_table(struct smu_context *smu) sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); break; case 7: /* nv12 */ - ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, + ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, (uint8_t **)&smc_dpm_table_v4_7); if (ret) return ret; @@ -457,7 +404,7 @@ static int navi10_append_powerplay_table(struct smu_context *smu) sizeof(*smc_dpm_table_v4_7) - sizeof(smc_dpm_table_v4_7->table_header)); break; default: - pr_err("smc_dpm_info with unsupported content revision %d!\n", + dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n", smc_dpm_table->table_header.content_revision); return -EINVAL; } @@ -472,35 +419,43 @@ static int navi10_append_powerplay_table(struct smu_context *smu) 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; - struct smu_baco_context *smu_baco = &smu->smu_baco; - - if (!table_context->power_play_table) - return -EINVAL; - - powerplay_table = table_context->power_play_table; + struct smu_11_0_powerplay_table *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; +} - if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) - smu->dc_controlled_by_gpio = true; +static int navi10_setup_pptable(struct smu_context *smu) +{ + int ret = 0; - mutex_lock(&smu_baco->mutex); - if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || - powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) - smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); + ret = smu_v11_0_setup_pptable(smu); + if (ret) + return ret; - return 0; + ret = navi10_store_powerplay_table(smu); + if (ret) + return ret; + + ret = navi10_append_powerplay_table(smu); + if (ret) + return ret; + + ret = navi10_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; } -static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables) +static int navi10_tables_init(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); @@ -508,6 +463,8 @@ static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables) 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_I2C_COMMANDS, sizeof(SwI2cRequest_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, @@ -528,25 +485,98 @@ static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables) return 0; } -static int navi10_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table) +static int navi10_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) { struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { - ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, - (void *)smu_table->metrics_table, false); + if (!smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); if (ret) { - pr_info("Failed to export SMU metrics table!\n"); + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK]; + break; + case METRICS_CURR_DCEFCLK: + *value = metrics->CurrClock[PPCLK_DCEFCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + *value = metrics->AverageGfxclkFrequency; + break; + case METRICS_AVERAGE_SOCCLK: + *value = metrics->AverageSocclkFrequency; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->AverageUclkFrequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->TemperatureEdge * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->TemperatureHotspot * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->TemperatureMem * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->TemperatureVrGfx * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->TemperatureVrSoc * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_CURR_FANSPEED: + *value = metrics->CurrFanSpeed; + break; + default: + *value = UINT_MAX; + break; + } + mutex_unlock(&smu->metrics_lock); return ret; @@ -556,9 +586,6 @@ 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) @@ -569,52 +596,194 @@ static int navi10_allocate_dpm_context(struct smu_context *smu) return 0; } -static int navi10_set_default_dpm_table(struct smu_context *smu) +static int navi10_init_smc_tables(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; - int i; + int ret = 0; - driver_ppt = table_context->driver_pptable; + ret = navi10_tables_init(smu); + if (ret) + return ret; + + ret = navi10_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v11_0_init_smc_tables(smu); +} - 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]; +static int navi10_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table; + int ret = 0; - 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]; + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* vclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* dclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* dcefclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dcef_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCEFCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* pixelclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.pixel_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PIXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - 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]; + /* displayclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.display_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DISPCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - for (i = 0; i < MAX_PCIE_CONF; i++) { - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = driver_ppt->PcieGenSpeed[i]; - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = driver_ppt->PcieLaneCount[i]; + /* phyclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.phy_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PHYCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } return 0; } -static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable) +static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -622,15 +791,15 @@ static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable) if (enable) { /* vcn dpm on is a prerequisite for vcn power gate messages */ - if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL); + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL); if (ret) return ret; } power_gate->vcn_gated = false; } else { - if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } @@ -647,15 +816,15 @@ static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) int ret = 0; if (enable) { - if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL); + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL); if (ret) return ret; } power_gate->jpeg_gated = false; } else { - if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); if (ret) return ret; } @@ -669,20 +838,41 @@ static int navi10_get_current_clk_freq_by_table(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *value) { - int ret = 0, clk_id = 0; - SmuMetrics_t metrics; + MetricsMember_t member_type; + int clk_id = 0; - ret = navi10_get_metrics_table(smu, &metrics); - if (ret) - return ret; - - clk_id = smu_clk_get_index(smu, clk_type); + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); if (clk_id < 0) return clk_id; - *value = metrics.CurrClock[clk_id]; + switch (clk_id) { + case PPCLK_GFXCLK: + member_type = METRICS_CURR_GFXCLK; + break; + case PPCLK_UCLK: + member_type = METRICS_CURR_UCLK; + break; + case PPCLK_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case PPCLK_VCLK: + member_type = METRICS_CURR_VCLK; + break; + case PPCLK_DCLK: + member_type = METRICS_CURR_DCLK; + break; + case PPCLK_DCEFCLK: + member_type = METRICS_CURR_DCEFCLK; + break; + default: + return -EINVAL; + } - return ret; + return navi10_get_smu_metrics_data(smu, + member_type, + value); } static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type) @@ -691,7 +881,9 @@ static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu DpmDescriptor_t *dpm_desc = NULL; uint32_t clk_index = 0; - clk_index = smu_clk_get_index(smu, clk_type); + clk_index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); dpm_desc = &pptable->DpmDescriptor[clk_index]; /* 0 - Fine grained DPM, 1 - Discrete DPM */ @@ -740,20 +932,17 @@ static int navi10_print_clk_levels(struct smu_context *smu, case SMU_UCLK: case SMU_FCLK: case SMU_DCEFCLK: - ret = smu_get_current_clk_freq(smu, clk_type, &cur_value); + ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value); if (ret) return size; - /* 10KHz -> MHz */ - cur_value = cur_value / 100; - - ret = smu_get_dpm_level_count(smu, clk_type, &count); + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); if (ret) return size; if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) { for (i = 0; i < count; i++) { - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); if (ret) return size; @@ -761,10 +950,10 @@ static int navi10_print_clk_levels(struct smu_context *smu, cur_value == value ? "*" : ""); } } else { - ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); if (ret) return size; - ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); if (ret) return size; @@ -841,7 +1030,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, default: break; } - size += sprintf(buf + size, "%d: %uMHz @ %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); + size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); } break; case SMU_OD_RANGE: @@ -924,15 +1113,15 @@ static int navi10_force_clk_levels(struct smu_context *smu, soft_min_level = (soft_min_level >= 1 ? 1 : 0); } - ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + ret = smu_v11_0_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); + ret = smu_v11_0_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, false); + ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); if (ret) return size; break; @@ -945,22 +1134,93 @@ static int navi10_force_clk_levels(struct smu_context *smu, static int navi10_populate_umd_state_clk(struct smu_context *smu) { - int ret = 0; - uint32_t min_sclk_freq = 0, min_mclk_freq = 0; - - ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL, false); - if (ret) - return ret; - - smu->pstate_sclk = min_sclk_freq * 100; - - ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL, false); - if (ret) - return ret; + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; + uint32_t sclk_freq; - smu->pstate_mclk = min_mclk_freq * 100; + pstate_table->gfxclk_pstate.min = gfx_table->min; + switch (adev->asic_type) { + case CHIP_NAVI10: + switch (adev->pdev->revision) { + case 0xf0: /* XTX */ + case 0xc0: + sclk_freq = NAVI10_PEAK_SCLK_XTX; + break; + case 0xf1: /* XT */ + case 0xc1: + sclk_freq = NAVI10_PEAK_SCLK_XT; + break; + default: /* XL */ + sclk_freq = NAVI10_PEAK_SCLK_XL; + break; + } + break; + case CHIP_NAVI14: + switch (adev->pdev->revision) { + case 0xc7: /* XT */ + case 0xf4: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; + break; + case 0xc1: /* XTM */ + case 0xf2: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; + break; + case 0xc3: /* XLM */ + case 0xf3: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + case 0xc5: /* XTX */ + case 0xf6: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + default: /* XL */ + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; + break; + } + break; + case CHIP_NAVI12: + sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; + break; + default: + sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value; + break; + } + pstate_table->gfxclk_pstate.peak = sclk_freq; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK && + mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK && + soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) { + pstate_table->gfxclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_SOCCLK; + } else { + pstate_table->gfxclk_pstate.standard = + pstate_table->gfxclk_pstate.min; + pstate_table->uclk_pstate.standard = + pstate_table->uclk_pstate.min; + pstate_table->socclk_pstate.standard = + pstate_table->socclk_pstate.min; + } - return ret; + return 0; } static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, @@ -976,7 +1236,7 @@ static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, case SMU_SOCCLK: case SMU_MCLK: case SMU_UCLK: - ret = smu_get_dpm_level_count(smu, clk_type, &level_count); + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count); if (ret) return ret; @@ -984,7 +1244,7 @@ static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, clocks->num_levels = level_count; for (i = 0; i < level_count; i++) { - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq); if (ret) return ret; @@ -1004,15 +1264,15 @@ 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, NULL); + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); 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, false); + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); if (ret) return ret; - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); if (ret) return ret; } @@ -1025,9 +1285,9 @@ static int navi10_display_config_changed(struct smu_context *smu) int ret = 0; 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_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, smu->display_config->num_display, NULL); if (ret) @@ -1037,74 +1297,14 @@ static int navi10_display_config_changed(struct smu_context *smu) 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, false); - if (ret) - return ret; - - force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); - 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; - - 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, false); - if (ret) - return ret; - - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); - 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 = navi10_get_metrics_table(smu, &metrics); - if (ret) - return ret; - - *value = metrics.AverageSocketPower << 8; - - return 0; + return navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + value); } static int navi10_get_current_activity_percent(struct smu_context *smu, @@ -1112,28 +1312,27 @@ static int navi10_get_current_activity_percent(struct smu_context *smu, uint32_t *value) { int ret = 0; - SmuMetrics_t metrics; if (!value) return -EINVAL; - ret = navi10_get_metrics_table(smu, &metrics); - if (ret) - return ret; - switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: - *value = metrics.AverageGfxActivity; + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + value); break; case AMDGPU_PP_SENSOR_MEM_LOAD: - *value = metrics.AverageUclkActivity; + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + value); break; default: - pr_err("Invalid sensor for retrieving clock activity\n"); + dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); return -EINVAL; } - return 0; + return ret; } static bool navi10_is_dpm_running(struct smu_context *smu) @@ -1141,7 +1340,7 @@ 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); + ret = smu_cmn_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); @@ -1150,19 +1349,12 @@ static bool navi10_is_dpm_running(struct smu_context *smu) static int navi10_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed) { - SmuMetrics_t metrics; - int ret = 0; - if (!speed) return -EINVAL; - ret = navi10_get_metrics_table(smu, &metrics); - if (ret) - return ret; - - *speed = metrics.CurrFanSpeed; - - return ret; + return navi10_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); } static int navi10_get_fan_speed_percent(struct smu_context *smu, @@ -1219,15 +1411,17 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) 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); + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); if (workload_type < 0) return -EINVAL; - result = smu_update_table(smu, + result = smu_cmn_update_table(smu, SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, (void *)(&activity_monitor), false); if (result) { - pr_err("[%s] Failed to get activity monitor!", __func__); + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); return result; } @@ -1288,17 +1482,17 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u 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); + dev_err(smu->adev->dev, "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, + ret = smu_cmn_update_table(smu, SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, (void *)(&activity_monitor), false); if (ret) { - pr_err("[%s] Failed to get activity monitor!", __func__); + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); return ret; } @@ -1338,66 +1532,27 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u break; } - ret = smu_update_table(smu, + ret = smu_cmn_update_table(smu, SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, (void *)(&activity_monitor), true); if (ret) { - pr_err("[%s] Failed to set activity monitor!", __func__); + dev_err(smu->adev->dev, "[%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); + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + smu->power_profile_mode); if (workload_type < 0) return -EINVAL; - smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, + smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, 1 << workload_type, NULL); 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; - *mclk_mask = level_count - 1; - } - - if(soc_mask) { - ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count); - if (ret) - return ret; - *soc_mask = level_count - 1; - } - } - - return ret; -} - static int navi10_notify_smc_display_config(struct smu_context *smu) { struct smu_clocks min_clocks = {0}; @@ -1408,31 +1563,31 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) 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)) { + if (smu_cmn_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; ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); if (!ret) { - if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { - ret = smu_send_smc_msg_with_param(smu, + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetMinDeepSleepDcefclk, min_clocks.dcef_clock_in_sr/100, NULL); if (ret) { - pr_err("Attempt to set divider for DCEFCLK Failed!"); + dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!"); return ret; } } } else { - pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); + dev_info(smu->adev->dev, "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 (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); if (ret) { - pr_err("[%s] Set hard min uclk failed!", __func__); + dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); return ret; } } @@ -1441,70 +1596,68 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) } static int navi10_set_watermarks_table(struct smu_context *smu, - void *watermarks, struct - dm_pp_wm_sets_with_clock_ranges_soc15 - *clock_ranges) + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) { - int i; + Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; - Watermarks_t *table = watermarks; + int i; - if (!table || !clock_ranges) - return -EINVAL; + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + 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_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; + } - 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; + smu->watermarks_bitmap |= WATERMARKS_EXIST; } - smu->watermarks_bitmap |= WATERMARKS_EXIST; - /* pass data to smu controller */ - if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) { - ret = smu_write_watermarks_table(smu); + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + ret = smu_cmn_write_watermarks_table(smu); if (ret) { - pr_err("Failed to update WMTABLE!"); + dev_err(smu->adev->dev, "Failed to update WMTABLE!"); return ret; } smu->watermarks_bitmap |= WATERMARKS_LOADED; @@ -1517,35 +1670,33 @@ static int navi10_thermal_get_temperature(struct smu_context *smu, enum amd_pp_sensors sensor, uint32_t *value) { - SmuMetrics_t metrics; int ret = 0; if (!value) return -EINVAL; - ret = navi10_get_metrics_table(smu, &metrics); - if (ret) - return ret; - switch (sensor) { case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - *value = metrics.TemperatureHotspot * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + value); break; case AMDGPU_PP_SENSOR_EDGE_TEMP: - *value = metrics.TemperatureEdge * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + value); break; case AMDGPU_PP_SENSOR_MEM_TEMP: - *value = metrics.TemperatureMem * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + value); break; default: - pr_err("Invalid sensor for retrieving temp\n"); + dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); return -EINVAL; } - return 0; + return ret; } static int navi10_read_sensor(struct smu_context *smu, @@ -1580,8 +1731,23 @@ static int navi10_read_sensor(struct smu_context *smu, ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; default: - ret = smu_v11_0_read_sensor(smu, sensor, data, size); + ret = -EOPNOTSUPP; + break; } mutex_unlock(&smu->sensor_lock); @@ -1617,160 +1783,32 @@ static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_ return 0; } -static int navi10_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level); - -static int navi10_set_standard_performance_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - switch (adev->asic_type) { - case CHIP_NAVI10: - sclk_freq = NAVI10_UMD_PSTATE_PROFILING_GFXCLK; - uclk_freq = NAVI10_UMD_PSTATE_PROFILING_MEMCLK; - break; - case CHIP_NAVI14: - sclk_freq = NAVI14_UMD_PSTATE_PROFILING_GFXCLK; - uclk_freq = NAVI14_UMD_PSTATE_PROFILING_MEMCLK; - break; - default: - /* by default, this is same as auto performance level */ - return navi10_set_performance_level(smu, AMD_DPM_FORCED_LEVEL_AUTO); - } - - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); - if (ret) - return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); - if (ret) - return ret; - - return ret; -} - -static int navi10_set_peak_performance_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - switch (adev->asic_type) { - case CHIP_NAVI10: - switch (adev->pdev->revision) { - case 0xf0: /* XTX */ - case 0xc0: - sclk_freq = NAVI10_PEAK_SCLK_XTX; - break; - case 0xf1: /* XT */ - case 0xc1: - sclk_freq = NAVI10_PEAK_SCLK_XT; - break; - default: /* XL */ - sclk_freq = NAVI10_PEAK_SCLK_XL; - break; - } - break; - case CHIP_NAVI14: - switch (adev->pdev->revision) { - case 0xc7: /* XT */ - case 0xf4: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; - break; - case 0xc1: /* XTM */ - case 0xf2: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; - break; - case 0xc3: /* XLM */ - case 0xf3: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - case 0xc5: /* XTX */ - case 0xf6: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - default: /* XL */ - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; - break; - } - break; - case CHIP_NAVI12: - sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; - break; - default: - ret = smu_get_dpm_level_range(smu, SMU_SCLK, NULL, &sclk_freq); - if (ret) - return ret; - } - - ret = smu_get_dpm_level_range(smu, SMU_UCLK, NULL, &uclk_freq); - if (ret) - return ret; - - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); - if (ret) - return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); - if (ret) - return ret; - - return ret; -} - -static int navi10_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu_force_dpm_limit_value(smu, true); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu_force_dpm_limit_value(smu, false); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = smu_unforce_dpm_levels(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = navi10_set_standard_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - ret = smu_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); - if (ret) - return ret; - smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false); - smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false); - smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = navi10_set_peak_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - return ret; -} - static int navi10_get_thermal_temperature_range(struct smu_context *smu, struct smu_temperature_range *range) { struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; - if (!range || !powerplay_table) + if (!range) return -EINVAL; - range->max = powerplay_table->software_shutdown_temp * + memcpy(range, &smu11_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->TmemLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; return 0; } @@ -1789,9 +1827,9 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, return 0; if(disable_memory_clock_switch) - ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); else - ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); if(!ret) smu->disable_uclk_switch = disable_memory_clock_switch; @@ -1799,51 +1837,35 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, return ret; } -static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu) +static int navi10_get_power_limit(struct smu_context *smu) { + struct smu_11_0_powerplay_table *powerplay_table = + (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; + struct smu_11_0_overdrive_table *od_settings = smu->od_settings; PPTable_t *pptable = smu->smu_table.driver_pptable; - return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; -} + uint32_t power_limit, od_percent; -static int navi10_get_power_limit(struct smu_context *smu, - uint32_t *limit, - bool cap) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t asic_default_power_limit = 0; - int ret = 0; - int power_src; + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; + } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; - if (!smu->power_limit) { - if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT) && - !amdgpu_sriov_vf(smu->adev)) { - power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); - if (power_src < 0) - return -EINVAL; + if (smu->od_enabled && + navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16, &asic_default_power_limit); - if (ret) { - pr_err("[%s] get PPT limit failed!", __func__); - return ret; - } - } else { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - pr_err("Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - asic_default_power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; - } + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - smu->power_limit = asic_default_power_limit; + power_limit *= (100 + od_percent); + power_limit /= 100; } - - if (cap) - *limit = smu_v11_0_get_max_power_limit(smu); - else - *limit = smu->power_limit; + smu->max_power_limit = power_limit; return 0; } @@ -1852,19 +1874,23 @@ static int navi10_update_pcie_parameters(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap) { + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; PPTable_t *pptable = smu->smu_table.driver_pptable; - int ret, i; uint32_t smu_pcie_arg; + int ret, i; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + /* lclk dpm table setup */ + for (i = 0; i < MAX_PCIE_CONF; i++) { + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; + } for (i = 0; i < NUM_LINK_LEVELS; i++) { smu_pcie_arg = (i << 16) | ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? pptable->PcieLaneCount[i] : pcie_width_cap); - ret = smu_send_smc_msg_with_param(smu, + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_OverridePcieParameters, smu_pcie_arg, NULL); @@ -1881,23 +1907,28 @@ static int navi10_update_pcie_parameters(struct smu_context *smu, return 0; } -static inline void navi10_dump_od_table(OverDriveTable_t *od_table) { - pr_debug("OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax); - pr_debug("OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1); - pr_debug("OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2); - pr_debug("OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3); - pr_debug("OD: UclkFmax: %d\n", od_table->UclkFmax); - pr_debug("OD: OverDrivePct: %d\n", od_table->OverDrivePct); +static inline void navi10_dump_od_table(struct smu_context *smu, + OverDriveTable_t *od_table) +{ + dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax); + dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1); + dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2); + dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3); + dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax); + dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct); } -static int navi10_od_setting_check_range(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODSETTING_ID setting, uint32_t value) +static int navi10_od_setting_check_range(struct smu_context *smu, + struct smu_11_0_overdrive_table *od_table, + enum SMU_11_0_ODSETTING_ID setting, + uint32_t value) { if (value < od_table->min[setting]) { - pr_warn("OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]); + dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]); return -EINVAL; } if (value > od_table->max[setting]) { - pr_warn("OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]); + dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]); return -EINVAL; } return 0; @@ -1911,12 +1942,12 @@ static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, uint32_t value = 0; int ret; - ret = smu_send_smc_msg_with_param(smu, + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetVoltageByDpm, param, &value); if (ret) { - pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); + dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); return ret; } @@ -1925,93 +1956,61 @@ static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, return 0; } -static int navi10_setup_od_limits(struct smu_context *smu) { - struct smu_11_0_overdrive_table *overdrive_table = NULL; - struct smu_11_0_powerplay_table *powerplay_table = NULL; - - if (!smu->smu_table.power_play_table) { - pr_err("powerplay table uninitialized!\n"); - return -ENOENT; - } - powerplay_table = (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; - overdrive_table = &powerplay_table->overdrive_table; - if (!smu->od_settings) { - smu->od_settings = kmemdup(overdrive_table, sizeof(struct smu_11_0_overdrive_table), GFP_KERNEL); - } else { - memcpy(smu->od_settings, overdrive_table, sizeof(struct smu_11_0_overdrive_table)); - } - return 0; -} - static bool navi10_is_baco_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t val; - if (!smu_v11_0_baco_is_support(smu)) + if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) return false; val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; } -static int navi10_set_default_od_settings(struct smu_context *smu, bool initialize) { - OverDriveTable_t *od_table, *boot_od_table; +static int navi10_set_default_od_settings(struct smu_context *smu) +{ + OverDriveTable_t *od_table = + (OverDriveTable_t *)smu->smu_table.overdrive_table; + OverDriveTable_t *boot_od_table = + (OverDriveTable_t *)smu->smu_table.boot_overdrive_table; int ret = 0; - if (amdgpu_sriov_vf(smu->adev)) - return 0; - - ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t)); - if (ret) + ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false); + if (ret) { + dev_err(smu->adev->dev, "Failed to get overdrive table!\n"); return ret; + } - od_table = (OverDriveTable_t *)smu->smu_table.overdrive_table; - boot_od_table = (OverDriveTable_t *)smu->smu_table.boot_overdrive_table; - if (initialize) { - ret = navi10_setup_od_limits(smu); - if (ret) { - pr_err("Failed to retrieve board OD limits\n"); + if (!od_table->GfxclkVolt1) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt1, + od_table->GfxclkFreq1); + if (ret) return ret; - } - if (od_table) { - if (!od_table->GfxclkVolt1) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt1, - od_table->GfxclkFreq1); - if (ret) - od_table->GfxclkVolt1 = 0; - if (boot_od_table) - boot_od_table->GfxclkVolt1 = od_table->GfxclkVolt1; - } - - if (!od_table->GfxclkVolt2) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt2, - od_table->GfxclkFreq2); - if (ret) - od_table->GfxclkVolt2 = 0; - if (boot_od_table) - boot_od_table->GfxclkVolt2 = od_table->GfxclkVolt2; - } + } - if (!od_table->GfxclkVolt3) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt3, - od_table->GfxclkFreq3); - if (ret) - od_table->GfxclkVolt3 = 0; - if (boot_od_table) - boot_od_table->GfxclkVolt3 = od_table->GfxclkVolt3; - } - } + if (!od_table->GfxclkVolt2) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt2, + od_table->GfxclkFreq2); + if (ret) + return ret; } - if (od_table) { - navi10_dump_od_table(od_table); + if (!od_table->GfxclkVolt3) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt3, + od_table->GfxclkFreq3); + if (ret) + return ret; } - return ret; + memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t)); + + navi10_dump_od_table(smu, od_table); + + return 0; } static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) { @@ -2025,12 +2024,12 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL od_table = (OverDriveTable_t *)table_context->overdrive_table; if (!smu->od_enabled) { - pr_warn("OverDrive is not enabled!\n"); + dev_warn(smu->adev->dev, "OverDrive is not enabled!\n"); return -EINVAL; } if (!smu->od_settings) { - pr_err("OD board limits are not set!\n"); + dev_err(smu->adev->dev, "OD board limits are not set!\n"); return -ENOENT; } @@ -2039,16 +2038,16 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL switch (type) { case PP_OD_EDIT_SCLK_VDDC_TABLE: if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { - pr_warn("GFXCLK_LIMITS not supported!\n"); + dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n"); return -ENOTSUPP; } if (!table_context->overdrive_table) { - pr_err("Overdrive is not initialized\n"); + dev_err(smu->adev->dev, "Overdrive is not initialized\n"); return -EINVAL; } for (i = 0; i < size; i += 2) { if (i + 2 > size) { - pr_info("invalid number of input parameters %d\n", size); + dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size); return -EINVAL; } switch (input[i]) { @@ -2056,7 +2055,7 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN; freq_ptr = &od_table->GfxclkFmin; if (input[i + 1] > od_table->GfxclkFmax) { - pr_info("GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n", + dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n", input[i + 1], od_table->GfxclkFmin); return -EINVAL; @@ -2066,18 +2065,18 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX; freq_ptr = &od_table->GfxclkFmax; if (input[i + 1] < od_table->GfxclkFmin) { - pr_info("GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n", + dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n", input[i + 1], od_table->GfxclkFmax); return -EINVAL; } break; default: - pr_info("Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]); - pr_info("Supported indices: [0:min,1:max]\n"); + dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]); + dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n"); return -EINVAL; } - ret = navi10_od_setting_check_range(od_settings, freq_setting, input[i + 1]); + ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]); if (ret) return ret; *freq_ptr = input[i + 1]; @@ -2085,56 +2084,49 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL break; case PP_OD_EDIT_MCLK_VDDC_TABLE: if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { - pr_warn("UCLK_MAX not supported!\n"); + dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n"); return -ENOTSUPP; } if (size < 2) { - pr_info("invalid number of parameters: %d\n", size); + dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); return -EINVAL; } if (input[0] != 1) { - pr_info("Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]); - pr_info("Supported indices: [1:max]\n"); + dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]); + dev_info(smu->adev->dev, "Supported indices: [1:max]\n"); return -EINVAL; } - ret = navi10_od_setting_check_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]); + ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]); if (ret) return ret; od_table->UclkFmax = input[1]; break; case PP_OD_RESTORE_DEFAULT_TABLE: if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) { - pr_err("Overdrive table was not initialized!\n"); + dev_err(smu->adev->dev, "Overdrive table was not initialized!\n"); return -EINVAL; } memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t)); break; case PP_OD_COMMIT_DPM_TABLE: - navi10_dump_od_table(od_table); - ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true); - if (ret) { - pr_err("Failed to import overdrive table!\n"); - return ret; - } - // no lock needed because smu_od_edit_dpm_table has it - ret = smu_handle_task(smu, smu->smu_dpm.dpm_level, - AMD_PP_TASK_READJUST_POWER_STATE, - false); + navi10_dump_od_table(smu, od_table); + ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true); if (ret) { + dev_err(smu->adev->dev, "Failed to import overdrive table!\n"); return ret; } break; case PP_OD_EDIT_VDDC_CURVE: if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { - pr_warn("GFXCLK_CURVE not supported!\n"); + dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n"); return -ENOTSUPP; } if (size < 3) { - pr_info("invalid number of parameters: %d\n", size); + dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); return -EINVAL; } if (!od_table) { - pr_info("Overdrive is not initialized\n"); + dev_info(smu->adev->dev, "Overdrive is not initialized\n"); return -EINVAL; } @@ -2158,28 +2150,28 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL voltage_ptr = &od_table->GfxclkVolt3; break; default: - pr_info("Invalid VDDC_CURVE index: %ld\n", input[0]); - pr_info("Supported indices: [0, 1, 2]\n"); + dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]); + dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n"); return -EINVAL; } - ret = navi10_od_setting_check_range(od_settings, freq_setting, input[1]); + ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]); if (ret) return ret; // Allow setting zero to disable the OverDrive VDDC curve if (input[2] != 0) { - ret = navi10_od_setting_check_range(od_settings, voltage_setting, input[2]); + ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]); if (ret) return ret; *freq_ptr = input[1]; *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE; - pr_debug("OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr); + dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr); } else { // If setting 0, disable all voltage curve settings od_table->GfxclkVolt1 = 0; od_table->GfxclkVolt2 = 0; od_table->GfxclkVolt3 = 0; } - navi10_dump_od_table(od_table); + navi10_dump_od_table(smu, od_table); break; default: return -ENOSYS; @@ -2191,9 +2183,9 @@ static int navi10_run_btc(struct smu_context *smu) { int ret = 0; - ret = smu_send_smc_msg(smu, SMU_MSG_RunBtc, NULL); + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunBtc, NULL); if (ret) - pr_err("RunBtc failed!\n"); + dev_err(smu->adev->dev, "RunBtc failed!\n"); return ret; } @@ -2203,20 +2195,38 @@ static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable) int result = 0; if (!enable) - result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); + result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); else - result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); + result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); return result; } +static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev) +{ + if (adev->asic_type != CHIP_NAVI10) + return false; + + if (adev->pdev->device == 0x731f && + (adev->pdev->revision == 0xc2 || + adev->pdev->revision == 0xc3 || + adev->pdev->revision == 0xca || + adev->pdev->revision == 0xcb)) + return true; + else + return false; +} + static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) { uint32_t uclk_count, uclk_min, uclk_max; uint32_t smu_version; int ret = 0; - ret = smu_get_smc_version(smu, NULL, &smu_version); + if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) + return 0; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); if (ret) return ret; @@ -2224,25 +2234,25 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) if (smu_version < 0x2A3200) return 0; - ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); + ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); if (ret) return ret; - ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); if (ret) return ret; - ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); if (ret) return ret; /* Force UCLK out of the highest DPM */ - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_min); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min); if (ret) return ret; /* Revert the UCLK Hardmax */ - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_max); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max); if (ret) return ret; @@ -2253,23 +2263,245 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) return navi10_dummy_pstate_control(smu, true); } +static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, + uint8_t address, uint32_t numbytes, + uint8_t *data) +{ + int i; + + BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); + + req->I2CcontrollerPort = 0; + req->I2CSpeed = 2; + req->SlaveAddress = address; + req->NumCmds = numbytes; + + for (i = 0; i < numbytes; i++) { + SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; + + /* First 2 bytes are always write for lower 2b EEPROM address */ + if (i < 2) + cmd->Cmd = 1; + else + cmd->Cmd = write; + + + /* Add RESTART for read after address filled */ + cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; + + /* Add STOP in the end */ + cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; + + /* Fill with data regardless if read or write to simplify code */ + cmd->RegisterAddr = data[i]; + } +} + +static int navi10_i2c_read_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t i, ret = 0; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_table *table = &smu_table->driver_table; + + memset(&req, 0, sizeof(req)); + navi10_fill_i2c_req(&req, false, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + /* Now read data starting with that address */ + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, + true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; + + /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ + for (i = 0; i < numbytes; i++) + data[i] = res->SwI2cCmds[i].Data; + + dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + } else + dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret); + + return ret; +} + +static int navi10_i2c_write_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t ret; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + + memset(&req, 0, sizeof(req)); + navi10_fill_i2c_req(&req, true, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + /* + * According to EEPROM spec there is a MAX of 10 ms required for + * EEPROM to flush internal RX buffer after STOP was issued at the + * end of write transaction. During this time the EEPROM will not be + * responsive to any more commands - so wait a bit more. + */ + msleep(10); + + } else + dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret); + + return ret; +} + +static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; + uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; + + for (i = 0; i < num; i++) { + /* + * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at + * once and hence the data needs to be spliced into chunks and sent each + * chunk separately + */ + data_size = msgs[i].len - 2; + data_chunk_size = MAX_SW_I2C_COMMANDS - 2; + next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); + data_ptr = msgs[i].buf + 2; + + for (j = 0; j < data_size / data_chunk_size; j++) { + /* Insert the EEPROM dest addess, bits 0-15 */ + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = navi10_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + + memcpy(data_ptr, data_chunk + 2, data_chunk_size); + } else { + + memcpy(data_chunk + 2, data_ptr, data_chunk_size); + + ret = navi10_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + } + + if (ret) { + num = -EIO; + goto fail; + } + + next_eeprom_addr += data_chunk_size; + data_ptr += data_chunk_size; + } + + if (data_size % data_chunk_size) { + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = navi10_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + + memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); + } else { + memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); + + ret = navi10_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + } + + if (ret) { + num = -EIO; + goto fail; + } + } + } + +fail: + return num; +} + +static u32 navi10_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + + +static const struct i2c_algorithm navi10_i2c_algo = { + .master_xfer = navi10_i2c_xfer, + .functionality = navi10_i2c_func, +}; + +static bool navi10_i2c_adapter_is_added(struct i2c_adapter *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + + return control->dev.parent == &adev->pdev->dev; +} + +static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + int res; + + /* smu_i2c_eeprom_init may be called twice in sriov */ + if (navi10_i2c_adapter_is_added(control)) + return 0; + + control->owner = THIS_MODULE; + control->class = I2C_CLASS_SPD; + control->dev.parent = &adev->pdev->dev; + control->algo = &navi10_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + + res = i2c_add_adapter(control); + if (res) + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + + return res; +} + +static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +{ + if (!navi10_i2c_adapter_is_added(control)) + return; + + i2c_del_adapter(control); +} + + 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, + .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable, .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable, - .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table, + .i2c_init = navi10_i2c_control_init, + .i2c_fini = navi10_i2c_control_fini, .print_clk_levels = navi10_print_clk_levels, .force_clk_levels = navi10_force_clk_levels, .populate_umd_state_clk = navi10_populate_umd_state_clk, @@ -2277,53 +2509,48 @@ static const struct pptable_funcs navi10_ppt_funcs = { .pre_display_config_changed = navi10_pre_display_config_changed, .display_config_changed = navi10_display_config_changed, .notify_smc_display_config = navi10_notify_smc_display_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_fan_speed_rpm = navi10_get_fan_speed_rpm, .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, - .set_performance_level = navi10_set_performance_level, + .set_performance_level = smu_v11_0_set_performance_level, .get_thermal_temperature_range = navi10_get_thermal_temperature_range, .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, .get_power_limit = navi10_get_power_limit, .update_pcie_parameters = navi10_update_pcie_parameters, .init_microcode = smu_v11_0_init_microcode, .load_microcode = smu_v11_0_load_microcode, - .init_smc_tables = smu_v11_0_init_smc_tables, + .fini_microcode = smu_v11_0_fini_microcode, + .init_smc_tables = navi10_init_smc_tables, .fini_smc_tables = smu_v11_0_fini_smc_tables, .init_power = smu_v11_0_init_power, .fini_power = smu_v11_0_fini_power, .check_fw_status = smu_v11_0_check_fw_status, - .setup_pptable = smu_v11_0_setup_pptable, + .setup_pptable = navi10_setup_pptable, .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, - .get_clk_info_from_vbios = smu_v11_0_get_clk_info_from_vbios, - .check_pptable = smu_v11_0_check_pptable, - .parse_pptable = smu_v11_0_parse_pptable, - .populate_smc_tables = smu_v11_0_populate_smc_pptable, .check_fw_version = smu_v11_0_check_fw_version, - .write_pptable = smu_v11_0_write_pptable, - .set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep, + .write_pptable = smu_cmn_write_pptable, .set_driver_table_location = smu_v11_0_set_driver_table_location, .set_tool_table_location = smu_v11_0_set_tool_table_location, .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .system_features_control = smu_v11_0_system_features_control, - .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, + .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, + .send_smc_msg = smu_cmn_send_smc_msg, .init_display_count = smu_v11_0_init_display_count, .set_allowed_mask = smu_v11_0_set_allowed_mask, - .get_enabled_mask = smu_v11_0_get_enabled_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, .notify_display_change = smu_v11_0_notify_display_change, .set_power_limit = smu_v11_0_set_power_limit, - .get_current_clk_freq = smu_v11_0_get_current_clk_freq, .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, - .start_thermal_control = smu_v11_0_start_thermal_control, - .stop_thermal_control = smu_v11_0_stop_thermal_control, - .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk, + .enable_thermal_alert = smu_v11_0_enable_thermal_alert, + .disable_thermal_alert = smu_v11_0_disable_thermal_alert, + .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk, .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, @@ -2341,16 +2568,22 @@ static const struct pptable_funcs navi10_ppt_funcs = { .baco_exit = smu_v11_0_baco_exit, .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .override_pcie_parameters = smu_v11_0_override_pcie_parameters, .set_default_od_settings = navi10_set_default_od_settings, .od_edit_dpm_table = navi10_od_edit_dpm_table, - .get_pptable_power_limit = navi10_get_pptable_power_limit, .run_btc = navi10_run_btc, .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround, .set_power_source = smu_v11_0_set_power_source, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, }; void navi10_set_ppt_funcs(struct smu_context *smu) { smu->ppt_funcs = &navi10_ppt_funcs; + smu->message_map = navi10_message_map; + smu->clock_map = navi10_clk_map; + smu->feature_map = navi10_feature_mask_map; + smu->table_map = navi10_table_map; + smu->pwr_src_map = navi10_pwr_src_map; + smu->workload_map = navi10_workload_map; } |