Commit c16df976 authored by Likun Gao's avatar Likun Gao Committed by Alex Deucher
Browse files

drm/amd/powerplay: adjust power state when set od_clk



Expose the function of adjust_power_state_dynamic to make it common to
other functions.
Add the operate of adjust powet state when set od percentage or
overdrive commit dpm table.

Signed-off-by: default avatarLikun Gao <Likun.Gao@amd.com>
Reviewed-by: default avatarHuang Rui <ray.huang@amd.com>
Reviewed-by: default avatarKevin Wang <kevin1.wang@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e388cc47
Loading
Loading
Loading
Loading
+56 −24
Original line number Original line Diff line number Diff line
@@ -1764,44 +1764,35 @@ static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context
	return smu_dpm_ctx->dpm_level;
	return smu_dpm_ctx->dpm_level;
}
}


static int
static int vega20_adjust_power_state_dynamic(struct smu_context *smu,
vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
					     enum amd_dpm_forced_level level)
{
{
	int ret = 0;
	int ret = 0;
	int index = 0;
	int index = 0;
	int i = 0;
	uint32_t sclk_mask, mclk_mask, soc_mask;
	uint32_t sclk_mask, mclk_mask, soc_mask;
	long workload;
	long workload;
	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
	if (!smu_dpm_ctx->dpm_context)
		return -EINVAL;


	for (i = 0; i < smu->adev->num_ip_blocks; i++) {
		if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
			break;
	}
	mutex_lock(&smu->mutex);
	smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
	ret = vega20_display_config_changed(smu);
	ret = vega20_display_config_changed(smu);
	if (ret) {
	if (ret) {
		pr_err("Failed to change display config!");
		pr_err("Failed to change display config!");
		goto failed;
		return ret;
	}
	}
	ret = vega20_apply_clocks_adjust_rules(smu);
	ret = vega20_apply_clocks_adjust_rules(smu);
	if (ret) {
	if (ret) {
		pr_err("Failed to apply clocks adjust rules!");
		pr_err("Failed to apply clocks adjust rules!");
		goto failed;
		return ret;
	}
	}
	ret = vega20_notify_smc_dispaly_config(smu);
	ret = vega20_notify_smc_dispaly_config(smu);
	if (ret) {
	if (ret) {
		pr_err("Failed to notify smc display config!");
		pr_err("Failed to notify smc display config!");
		goto failed;
		return ret;
	}
	}

	switch (level) {
	switch (level) {
	case AMD_DPM_FORCED_LEVEL_HIGH:
	case AMD_DPM_FORCED_LEVEL_HIGH:
		ret = vega20_force_dpm_highest(smu);
		ret = vega20_force_dpm_highest(smu);
		break;
		break;

	case AMD_DPM_FORCED_LEVEL_LOW:
	case AMD_DPM_FORCED_LEVEL_LOW:
		ret = vega20_force_dpm_lowest(smu);
		ret = vega20_force_dpm_lowest(smu);
		break;
		break;
@@ -1819,7 +1810,7 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve
						    &mclk_mask,
						    &mclk_mask,
						    &soc_mask);
						    &soc_mask);
		if (ret)
		if (ret)
			goto failed;
			return ret;
		vega20_force_clk_levels(smu, PP_SCLK, 1 << sclk_mask);
		vega20_force_clk_levels(smu, PP_SCLK, 1 << sclk_mask);
		vega20_force_clk_levels(smu, PP_MCLK, 1 << mclk_mask);
		vega20_force_clk_levels(smu, PP_MCLK, 1 << mclk_mask);
		break;
		break;
@@ -1842,8 +1833,31 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve
			smu->funcs->set_power_profile_mode(smu, &workload, 0);
			smu->funcs->set_power_profile_mode(smu, &workload, 0);
	}
	}


failed:
	return ret;
}

static int
vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
{
	int ret = 0;
	int i;
	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);

	if (!smu_dpm_ctx->dpm_context)
		return -EINVAL;

	for (i = 0; i < smu->adev->num_ip_blocks; i++) {
		if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
			break;
	}

	mutex_lock(&smu->mutex);

	smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
	ret = vega20_adjust_power_state_dynamic(smu, level);

	mutex_unlock(&smu->mutex);
	mutex_unlock(&smu->mutex);

	return ret;
	return ret;
}
}


@@ -1934,9 +1948,12 @@ static int vega20_set_od_percentage(struct smu_context *smu,
	struct vega20_single_dpm_table *single_dpm_table;
	struct vega20_single_dpm_table *single_dpm_table;
	struct vega20_single_dpm_table *golden_dpm_table;
	struct vega20_single_dpm_table *golden_dpm_table;
	uint32_t od_clk, index;
	uint32_t od_clk, index;
	int ret, feature_enabled;
	int ret = 0;
	int feature_enabled;
	PPCLK_e clk_id;
	PPCLK_e clk_id;


	mutex_lock(&(smu->mutex));

	dpm_table = smu_dpm->dpm_context;
	dpm_table = smu_dpm->dpm_context;
	golden_table = smu_dpm->golden_dpm_context;
	golden_table = smu_dpm->golden_dpm_context;


@@ -1956,10 +1973,13 @@ static int vega20_set_od_percentage(struct smu_context *smu,
		index = OD8_SETTING_UCLK_FMAX;
		index = OD8_SETTING_UCLK_FMAX;
		break;
		break;
	default:
	default:
		return -EINVAL;
		ret = -EINVAL;
		break;
		break;
	}
	}


	if (ret)
		goto set_od_failed;

	od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
	od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
	od_clk /= 100;
	od_clk /= 100;
	od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
	od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
@@ -1967,7 +1987,7 @@ static int vega20_set_od_percentage(struct smu_context *smu,
	ret = smu_update_od8_settings(smu, index, od_clk);
	ret = smu_update_od8_settings(smu, index, od_clk);
	if (ret) {
	if (ret) {
		pr_err("[Setoverdrive] failed to set od clk!\n");
		pr_err("[Setoverdrive] failed to set od clk!\n");
		return ret;
		goto set_od_failed;
	}
	}


	if (feature_enabled) {
	if (feature_enabled) {
@@ -1975,14 +1995,19 @@ static int vega20_set_od_percentage(struct smu_context *smu,
						  clk_id);
						  clk_id);
		if (ret) {
		if (ret) {
			pr_err("[Setoverdrive] failed to refresh dpm table!\n");
			pr_err("[Setoverdrive] failed to refresh dpm table!\n");
			return ret;
			goto set_od_failed;
		}
		}
	} else {
	} else {
		single_dpm_table->count = 1;
		single_dpm_table->count = 1;
		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
		single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
	}
	}


	return 0;
	ret = vega20_adjust_power_state_dynamic(smu, smu_dpm->dpm_level);

set_od_failed:
	mutex_unlock(&(smu->mutex));

	return ret;
}
}


static int vega20_odn_edit_dpm_table(struct smu_context *smu,
static int vega20_odn_edit_dpm_table(struct smu_context *smu,
@@ -1999,7 +2024,8 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
		(struct vega20_od8_settings *)table_context->od8_settings;
		(struct vega20_od8_settings *)table_context->od8_settings;
	struct pp_clock_levels_with_latency clocks;
	struct pp_clock_levels_with_latency clocks;
	int32_t input_index, input_clk, input_vol, i;
	int32_t input_index, input_clk, input_vol, i;
	int od8_id, ret;
	int od8_id;
	int ret = 0;


	dpm_table = smu_dpm->dpm_context;
	dpm_table = smu_dpm->dpm_context;


@@ -2204,7 +2230,13 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
		return -EINVAL;
		return -EINVAL;
	}
	}


	return 0;
	if (type == PP_OD_COMMIT_DPM_TABLE) {
		mutex_lock(&(smu->mutex));
		ret = vega20_adjust_power_state_dynamic(smu, smu_dpm->dpm_level);
		mutex_unlock(&(smu->mutex));
	}

	return ret;
}
}


static const struct pptable_funcs vega20_ppt_funcs = {
static const struct pptable_funcs vega20_ppt_funcs = {