Commit 3ffb1939 authored by shikaguo's avatar shikaguo Committed by Alex Deucher
Browse files

drm/amd/pm: enable more Pstates profile levels for yellow_carp



This patch enables following UMD stable Pstates profile levels for
power_dpm_force_performance_level interface.

- profile_peak
- profile_min_mclk
- profile_min_sclk
- profile_standard

Signed-off-by: default avatarshikaguo <shikai.guo@amd.com>
Reviewed-by: default avatarTim Huang <Tim.Huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 80e709ee
Loading
Loading
Loading
Loading
+137 −4
Original line number Diff line number Diff line
@@ -47,6 +47,14 @@
#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK		0x00000006L
#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT          0x1L

#define SMU_13_0_8_UMD_PSTATE_GFXCLK                   533
#define SMU_13_0_8_UMD_PSTATE_SOCCLK                   533
#define SMU_13_0_8_UMD_PSTATE_FCLK                     800

#define SMU_13_0_1_UMD_PSTATE_GFXCLK					700
#define SMU_13_0_1_UMD_PSTATE_SOCCLK		              678
#define SMU_13_0_1_UMD_PSTATE_FCLK			          1800

#define FEATURE_MASK(feature) (1ULL << feature)
#define SMC_DPM_FEATURE ( \
	FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
@@ -957,6 +965,9 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
							uint32_t max)
{
	enum smu_message_type msg_set_min, msg_set_max;
	uint32_t min_clk = min;
	uint32_t max_clk = max;

	int ret = 0;

	if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type))
@@ -985,11 +996,17 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
		return -EINVAL;
	}

	ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
	if (clk_type == SMU_VCLK) {
		min_clk = min << SMU_13_VCLK_SHIFT;
		max_clk = max << SMU_13_VCLK_SHIFT;
	}

	ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min_clk, NULL);

	if (ret)
		goto out;

	ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL);
	ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max_clk, NULL);
	if (ret)
		goto out;

@@ -997,12 +1014,49 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
	return ret;
}

static uint32_t yellow_carp_get_umd_pstate_clk_default(struct smu_context *smu,
					enum smu_clk_type clk_type)
{
	uint32_t clk_limit = 0;
	struct amdgpu_device *adev = smu->adev;

	switch (clk_type) {
	case SMU_GFXCLK:
	case SMU_SCLK:
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
			clk_limit = SMU_13_0_8_UMD_PSTATE_GFXCLK;
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
			(adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
			clk_limit = SMU_13_0_1_UMD_PSTATE_GFXCLK;
		break;
	case SMU_SOCCLK:
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
			clk_limit = SMU_13_0_8_UMD_PSTATE_SOCCLK;
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
			(adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
			clk_limit = SMU_13_0_1_UMD_PSTATE_SOCCLK;
		break;
	case SMU_FCLK:
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
			clk_limit = SMU_13_0_8_UMD_PSTATE_FCLK;
		if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
			(adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
			clk_limit = SMU_13_0_1_UMD_PSTATE_FCLK;
		break;
	default:
		break;
	}

	return clk_limit;
}

static int yellow_carp_print_clk_levels(struct smu_context *smu,
				enum smu_clk_type clk_type, char *buf)
{
	int i, idx, size = 0, ret = 0;
	uint32_t cur_value = 0, value = 0, count = 0;
	uint32_t min, max;
	uint32_t clk_limit = 0;

	smu_cmn_get_sysfs_buf(&buf, &size);

@@ -1044,6 +1098,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
		break;
	case SMU_GFXCLK:
	case SMU_SCLK:
		clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type);
		ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value);
		if (ret)
			goto print_clk_out;
@@ -1058,7 +1113,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
		size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
				i == 0 ? "*" : "");
		size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
				i == 1 ? cur_value : YELLOW_CARP_UMD_PSTATE_GFXCLK,
				i == 1 ? cur_value : clk_limit,
				i == 1 ? "*" : "");
		size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
				i == 2 ? "*" : "");
@@ -1107,6 +1162,49 @@ static int yellow_carp_force_clk_levels(struct smu_context *smu,
	return ret;
}

static int yellow_carp_get_dpm_profile_freq(struct smu_context *smu,
					enum amd_dpm_forced_level level,
					enum smu_clk_type clk_type,
					uint32_t *min_clk,
					uint32_t *max_clk)
{
	int ret = 0;
	uint32_t clk_limit = 0;

	clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type);

	switch (clk_type) {
	case SMU_GFXCLK:
	case SMU_SCLK:
		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
			yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
			yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
		break;
	case SMU_SOCCLK:
		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
			yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
		break;
	case SMU_FCLK:
		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
			yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
			yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL);
		break;
	case SMU_VCLK:
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
		break;
	case SMU_DCLK:
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
		break;
	default:
		ret = -EINVAL;
		break;
	}
	*min_clk = *max_clk = clk_limit;
	return ret;
}

static int yellow_carp_set_performance_level(struct smu_context *smu,
						enum amd_dpm_forced_level level)
{
@@ -1114,6 +1212,9 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
	uint32_t sclk_min = 0, sclk_max = 0;
	uint32_t fclk_min = 0, fclk_max = 0;
	uint32_t socclk_min = 0, socclk_max = 0;
	uint32_t vclk_min = 0, vclk_max = 0;
	uint32_t dclk_min = 0, dclk_max = 0;

	int ret = 0;

	switch (level) {
@@ -1121,28 +1222,42 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
		sclk_min = sclk_max;
		fclk_min = fclk_max;
		socclk_min = socclk_max;
		vclk_min = vclk_max;
		dclk_min = dclk_max;
		break;
	case AMD_DPM_FORCED_LEVEL_LOW:
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
		sclk_max = sclk_min;
		fclk_max = fclk_min;
		socclk_max = socclk_min;
		vclk_max = vclk_min;
		dclk_max = dclk_min;
		break;
	case AMD_DPM_FORCED_LEVEL_AUTO:
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
		yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
		break;
	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
		/* Temporarily do nothing since the optimal clocks haven't been provided yet */
		yellow_carp_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
		yellow_carp_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max);
		yellow_carp_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max);
		yellow_carp_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
		yellow_carp_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
		break;
	case AMD_DPM_FORCED_LEVEL_MANUAL:
	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@@ -1182,6 +1297,24 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
			return ret;
	}

	if (vclk_min && vclk_max) {
		ret = yellow_carp_set_soft_freq_limited_range(smu,
							      SMU_VCLK,
							      vclk_min,
							      vclk_max);
		if (ret)
			return ret;
	}

	if (dclk_min && dclk_max) {
		ret = yellow_carp_set_soft_freq_limited_range(smu,
							      SMU_DCLK,
							      dclk_min,
							      dclk_max);
		if (ret)
			return ret;
	}

	return ret;
}

+0 −1
Original line number Diff line number Diff line
@@ -24,6 +24,5 @@
#define __YELLOW_CARP_PPT_H__

extern void yellow_carp_set_ppt_funcs(struct smu_context *smu);
#define YELLOW_CARP_UMD_PSTATE_GFXCLK       1100

#endif