Commit 7457cf02 authored by Huang Rui's avatar Huang Rui Committed by Alex Deucher
Browse files

drm/amd/powerplay: add get_max_sustainable_clock function



This patch adds get_max_sustainable_clock function for smu11.

Signed-off-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 86ac8803
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -393,6 +393,10 @@ static int smu_smc_table_hw_init(struct smu_context *smu)
	if (ret)
		return ret;

	ret = smu_init_max_sustainable_clocks(smu);
	if (ret)
		return ret;

	ret = smu_populate_umd_state_clk(smu);
	if (ret)
		return ret;
@@ -539,6 +543,11 @@ static int smu_hw_fini(void *handle)
		return -EINVAL;
	kfree(table_context->driver_pptable);

	if (table_context->max_sustainable_clocks) {
		kfree(table_context->max_sustainable_clocks);
		table_context->max_sustainable_clocks = NULL;
	}

	ret = smu_fini_fb_allocations(smu);
	if (ret)
		return ret;
+4 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ struct smu_table_context
	void				*power_play_table;
	uint32_t			power_play_table_size;

	void				*max_sustainable_clocks;
	struct smu_bios_boot_up_values	boot_values;
	void                            *driver_pptable;
	struct smu_table		*tables;
@@ -253,6 +254,7 @@ struct smu_funcs
	int (*notify_display_change)(struct smu_context *smu);
	int (*get_power_limit)(struct smu_context *smu);
	int (*get_current_clk_freq)(struct smu_context *smu, uint32_t clk_id, uint32_t *value);
	int (*init_max_sustainable_clocks)(struct smu_context *smu);
};

#define smu_init_microcode(smu) \
@@ -297,6 +299,8 @@ struct smu_funcs
	((smu)->funcs->set_last_dcef_min_deep_sleep_clk ? (smu)->funcs->set_last_dcef_min_deep_sleep_clk((smu)) : 0)
#define smu_system_features_control(smu, en) \
	((smu)->funcs->system_features_control ? (smu)->funcs->system_features_control((smu), (en)) : 0)
#define smu_init_max_sustainable_clocks(smu) \
	((smu)->funcs->init_max_sustainable_clocks ? (smu)->funcs->init_max_sustainable_clocks((smu)) : 0)
#define smu_send_smc_msg(smu, msg) \
	((smu)->funcs->send_smc_msg? (smu)->funcs->send_smc_msg((smu), (msg)) : 0)
#define smu_send_smc_msg_with_param(smu, msg, param) \
+8 −0
Original line number Diff line number Diff line
@@ -36,6 +36,14 @@
#define smnMP0_FW_INTF			0x30101c0
#define smnMP1_PUB_CTRL			0x3010b14

struct smu_11_0_max_sustainable_clocks {
	uint32_t display_clock;
	uint32_t phy_clock;
	uint32_t pixel_clock;
	uint32_t uclock;
	uint32_t dcef_clock;
	uint32_t soc_clock;
};

struct smu_11_0_dpm_table {
	uint32_t    min;        /* MHz */
+114 −0
Original line number Diff line number Diff line
@@ -738,6 +738,119 @@ static int smu_v11_0_notify_display_change(struct smu_context *smu)
	return ret;
}

static int
smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
				    PPCLK_e clock_select)
{
	int ret = 0;

	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq,
					  clock_select << 16);
	if (ret) {
		pr_err("[GetMaxSustainableClock] Failed to get max DC clock from SMC!");
		return ret;
	}

	ret = smu_read_smc_arg(smu, clock);
	if (ret)
		return ret;

	if (*clock != 0)
		return 0;

	/* if DC limit is zero, return AC limit */
	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq,
					  clock_select << 16);
	if (ret) {
		pr_err("[GetMaxSustainableClock] failed to get max AC clock from SMC!");
		return ret;
	}

	ret = smu_read_smc_arg(smu, clock);

	return ret;
}

static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
{
	struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
	int ret = 0;

	max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
					 GFP_KERNEL);
	smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;

	max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
	max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100;
	max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100;
	max_sustainable_clocks->display_clock = 0xFFFFFFFF;
	max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
	max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;

	if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->uclock),
							  PPCLK_UCLK);
		if (ret) {
			pr_err("[%s] failed to get max UCLK from SMC!",
			       __func__);
			return ret;
		}
	}

	if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->soc_clock),
							  PPCLK_SOCCLK);
		if (ret) {
			pr_err("[%s] failed to get max SOCCLK from SMC!",
			       __func__);
			return ret;
		}
	}

	if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->dcef_clock),
							  PPCLK_DCEFCLK);
		if (ret) {
			pr_err("[%s] failed to get max DCEFCLK from SMC!",
			       __func__);
			return ret;
		}

		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->display_clock),
							  PPCLK_DISPCLK);
		if (ret) {
			pr_err("[%s] failed to get max DISPCLK from SMC!",
			       __func__);
			return ret;
		}
		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->phy_clock),
							  PPCLK_PHYCLK);
		if (ret) {
			pr_err("[%s] failed to get max PHYCLK from SMC!",
			       __func__);
			return ret;
		}
		ret = smu_v11_0_get_max_sustainable_clock(smu,
							  &(max_sustainable_clocks->pixel_clock),
							  PPCLK_PIXCLK);
		if (ret) {
			pr_err("[%s] failed to get max PIXCLK from SMC!",
			       __func__);
			return ret;
		}
	}

	if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
		max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;

	return 0;
}

static int smu_v11_0_get_power_limit(struct smu_context *smu)
{
	int ret;
@@ -810,6 +923,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
	.notify_display_change = smu_v11_0_notify_display_change,
	.get_power_limit = smu_v11_0_get_power_limit,
	.get_current_clk_freq = smu_v11_0_get_current_clk_freq,
	.init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
};

void smu_v11_0_set_smu_funcs(struct smu_context *smu)