Commit 505ac303 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

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



Implement Navi10 backend for runtime ppfeatures status retrieving
and setting support.

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b2136465
Loading
Loading
Loading
Loading
+165 −0
Original line number Diff line number Diff line
@@ -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)