From 61e2c3b487891fc346d7c6d89d9e436b82db8b85 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Jun 2019 11:06:08 +0800 Subject: [PATCH 2596/2940] drm/amd/powerplay: support runtime ppfeatures setting on Navi10 Implement Navi10 backend for runtime ppfeatures status retrieving and setting support. Change-Id: Ib498b934c260e351c6cafedcd865fd931319e7a3 Signed-off-by: Evan Quan Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 165 +++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index e2925e317201..99566de80572 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -1304,6 +1304,169 @@ static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_ return 0; } +static int navi10_get_ppfeature_status(struct smu_context *smu, + char *buf) +{ + static const char *ppfeature_name[] = { + "DPM_PREFETCHER", + "DPM_GFXCLK", + "DPM_GFX_PACE", + "DPM_UCLK", + "DPM_SOCCLK", + "DPM_MP0CLK", + "DPM_LINK", + "DPM_DCEFCLK", + "MEM_VDDCI_SCALING", + "MEM_MVDD_SCALING", + "DS_GFXCLK", + "DS_SOCCLK", + "DS_LCLK", + "DS_DCEFCLK", + "DS_UCLK", + "GFX_ULV", + "FW_DSTATE", + "GFXOFF", + "BACO", + "VCN_PG", + "JPEG_PG", + "USB_PG", + "RSMU_SMN_CG", + "PPT", + "TDC", + "GFX_EDC", + "APCC_PLUS", + "GTHR", + "ACDC", + "VR0HOT", + "VR1HOT", + "FW_CTF", + "FAN_CONTROL", + "THERMAL", + "GFX_DCS", + "RM", + "LED_DISPLAY", + "GFX_SS", + "OUT_OF_BAND_MONITOR", + "TEMP_DEPENDENT_VMIN", + "MMHUB_PG", + "ATHUB_PG"}; + static const char *output_title[] = { + "FEATURES", + "BITMASK", + "ENABLEMENT"}; + uint64_t features_enabled; + uint32_t feature_mask[2]; + int i; + int ret = 0; + int size = 0; + + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); + PP_ASSERT_WITH_CODE(!ret, + "[GetPPfeatureStatus] Failed to get enabled smc features!", + return ret); + features_enabled = (uint64_t)feature_mask[0] | + (uint64_t)feature_mask[1] << 32; + + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); + size += sprintf(buf + size, "%-19s %-22s %s\n", + output_title[0], + output_title[1], + output_title[2]); + for (i = 0; i < (sizeof(ppfeature_name) / sizeof(ppfeature_name[0])); i++) { + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", + ppfeature_name[i], + 1ULL << i, + (features_enabled & (1ULL << i)) ? "Y" : "N"); + } + + return size; +} + +static int navi10_enable_smc_features(struct smu_context *smu, + bool enabled, + uint64_t feature_masks) +{ + struct smu_feature *feature = &smu->smu_feature; + uint32_t feature_low, feature_high; + uint32_t feature_mask[2]; + int ret = 0; + + feature_low = (uint32_t)(feature_masks & 0xFFFFFFFF); + feature_high = (uint32_t)((feature_masks & 0xFFFFFFFF00000000ULL) >> 32); + + if (enabled) { + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow, + feature_low); + if (ret) + return ret; + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh, + feature_high); + if (ret) + return ret; + } else { + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow, + feature_low); + if (ret) + return ret; + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh, + feature_high); + if (ret) + return ret; + } + + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); + if (ret) + return ret; + + mutex_lock(&feature->mutex); + bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, + feature->feature_num); + mutex_unlock(&feature->mutex); + + return 0; +} + +static int navi10_set_ppfeature_status(struct smu_context *smu, + uint64_t new_ppfeature_masks) +{ + uint64_t features_enabled; + uint32_t feature_mask[2]; + uint64_t features_to_enable; + uint64_t features_to_disable; + int ret = 0; + + ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); + PP_ASSERT_WITH_CODE(!ret, + "[SetPPfeatureStatus] Failed to get enabled smc features!", + return ret); + features_enabled = (uint64_t)feature_mask[0] | + (uint64_t)feature_mask[1] << 32; + + features_to_disable = + features_enabled & ~new_ppfeature_masks; + features_to_enable = + ~features_enabled & new_ppfeature_masks; + + pr_debug("features_to_disable 0x%llx\n", features_to_disable); + pr_debug("features_to_enable 0x%llx\n", features_to_enable); + + if (features_to_disable) { + ret = navi10_enable_smc_features(smu, false, features_to_disable); + PP_ASSERT_WITH_CODE(!ret, + "[SetPPfeatureStatus] Failed to disable smc features!", + return ret); + } + + if (features_to_enable) { + ret = navi10_enable_smc_features(smu, true, features_to_enable); + PP_ASSERT_WITH_CODE(!ret, + "[SetPPfeatureStatus] Failed to enable smc features!", + return ret); + } + + return 0; +} + static const struct pptable_funcs navi10_ppt_funcs = { .tables_init = navi10_tables_init, .alloc_dpm_context = navi10_allocate_dpm_context, @@ -1337,6 +1500,8 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_watermarks_table = navi10_set_watermarks_table, .read_sensor = navi10_read_sensor, .get_uclk_dpm_states = navi10_get_uclk_dpm_states, + .get_ppfeature_status = navi10_get_ppfeature_status, + .set_ppfeature_status = navi10_set_ppfeature_status, }; void navi10_set_ppt_funcs(struct smu_context *smu) -- 2.17.1