drm/amd/powerplay: support runtime ppfeatures setting on Navi10

Submitted by Quan, Evan on June 25, 2019, 8:49 a.m.

Details

Message ID 20190625084927.27738-1-evan.quan@amd.com
State Accepted
Commit 505ac3039a184b53ddb16f25cd10cab67af633f5
Headers show
Series "drm/amd/powerplay: support runtime ppfeatures setting on Navi10" ( rev: 1 ) in AMD X.Org drivers

Not browsing as part of any series.

Commit Message

Quan, Evan June 25, 2019, 8:49 a.m.
Implement Navi10 backend for runtime ppfeatures status retrieving
and setting support.

Change-Id: Ib498b934c260e351c6cafedcd865fd931319e7a3
Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 165 +++++++++++++++++++++
 1 file changed, 165 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index ac4b3fc97a8d..3d61372db551 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -1275,6 +1275,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,
@@ -1308,6 +1471,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)