diff options
author | Evan Quan <evan.quan@amd.com> | 2020-07-07 14:06:40 +0800 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2020-07-21 15:37:38 -0400 |
commit | 7dbf78051f75f15df7308dde6d55e757b6ec918c (patch) | |
tree | f4b8cc79f3df18bbf8763aa56f0822759ff4fcf6 /drivers/gpu/drm/amd/powerplay/smu_cmn.c | |
parent | 28251d726b2be5f9f982b649c8cc00f20936a326 (diff) |
drm/amd/powerplay: move ppfeature mask setting to smu_cmn.c
Considering they are shared by all ASICs. And we are moving
to centralize all feature enablement/support checking and
setting APIs in smu_cmn.c.
Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smu_cmn.c')
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/smu_cmn.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index 4a8511c1051f..d0293b3dc9ab 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -23,6 +23,7 @@ #include "amdgpu.h" #include "amdgpu_smu.h" #include "smu_cmn.h" +#include "smu_internal.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -192,3 +193,165 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, return ret; } + +static int smu_cmn_feature_update_enable_state(struct smu_context *smu, + uint64_t feature_mask, + bool enabled) +{ + struct smu_feature *feature = &smu->smu_feature; + int ret = 0; + + if (enabled) { + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_EnableSmuFeaturesLow, + lower_32_bits(feature_mask), + NULL); + if (ret) + return ret; + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_EnableSmuFeaturesHigh, + upper_32_bits(feature_mask), + NULL); + if (ret) + return ret; + } else { + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_DisableSmuFeaturesLow, + lower_32_bits(feature_mask), + NULL); + if (ret) + return ret; + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_DisableSmuFeaturesHigh, + upper_32_bits(feature_mask), + NULL); + if (ret) + return ret; + } + + mutex_lock(&feature->mutex); + if (enabled) + bitmap_or(feature->enabled, feature->enabled, + (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); + else + bitmap_andnot(feature->enabled, feature->enabled, + (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); + mutex_unlock(&feature->mutex); + + return ret; +} + +int smu_cmn_feature_set_enabled(struct smu_context *smu, + enum smu_feature_mask mask, + bool enable) +{ + struct smu_feature *feature = &smu->smu_feature; + int feature_id; + + feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + mask); + if (feature_id < 0) + return -EINVAL; + + WARN_ON(feature_id > feature->feature_num); + + return smu_cmn_feature_update_enable_state(smu, + 1ULL << feature_id, + enable); +} + +#undef __SMU_DUMMY_MAP +#define __SMU_DUMMY_MAP(fea) #fea +static const char* __smu_feature_names[] = { + SMU_FEATURE_MASKS +}; + +static const char *smu_get_feature_name(struct smu_context *smu, + enum smu_feature_mask feature) +{ + if (feature < 0 || feature >= SMU_FEATURE_COUNT) + return "unknown smu feature"; + return __smu_feature_names[feature]; +} + +size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, + char *buf) +{ + uint32_t feature_mask[2] = { 0 }; + int32_t feature_index = 0; + uint32_t count = 0; + uint32_t sort_feature[SMU_FEATURE_COUNT]; + uint64_t hw_feature_count = 0; + size_t size = 0; + int ret = 0, i; + + ret = smu_cmn_get_enabled_mask(smu, + feature_mask, + 2); + if (ret) + return 0; + + size = sprintf(buf + size, "features high: 0x%08x low: 0x%08x\n", + feature_mask[1], feature_mask[0]); + + for (i = 0; i < SMU_FEATURE_COUNT; i++) { + feature_index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + i); + if (feature_index < 0) + continue; + sort_feature[feature_index] = i; + hw_feature_count++; + } + + for (i = 0; i < hw_feature_count; i++) { + size += sprintf(buf + size, "%02d. %-20s (%2d) : %s\n", + count++, + smu_get_feature_name(smu, sort_feature[i]), + i, + !!smu_cmn_feature_is_enabled(smu, sort_feature[i]) ? + "enabled" : "disabled"); + } + + return size; +} + +int smu_cmn_set_pp_feature_mask(struct smu_context *smu, + uint64_t new_mask) +{ + int ret = 0; + uint32_t feature_mask[2] = { 0 }; + uint64_t feature_2_enabled = 0; + uint64_t feature_2_disabled = 0; + uint64_t feature_enables = 0; + + ret = smu_cmn_get_enabled_mask(smu, + feature_mask, + 2); + if (ret) + return ret; + + feature_enables = ((uint64_t)feature_mask[1] << 32 | + (uint64_t)feature_mask[0]); + + feature_2_enabled = ~feature_enables & new_mask; + feature_2_disabled = feature_enables & ~new_mask; + + if (feature_2_enabled) { + ret = smu_cmn_feature_update_enable_state(smu, + feature_2_enabled, + true); + if (ret) + return ret; + } + if (feature_2_disabled) { + ret = smu_cmn_feature_update_enable_state(smu, + feature_2_disabled, + false); + if (ret) + return ret; + } + + return ret; +} |