Commit 5e2d3881 authored by Huang Rui's avatar Huang Rui Committed by Alex Deucher
Browse files

drm/amd/powerplay: add interface to get current clocks for display



This patch fills the amd_pp_clock_info data for display, it will get the current
info in that structure.

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 8021816c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -497,6 +497,8 @@ bool dm_pp_get_static_clocks(
		ret = adev->powerplay.pp_funcs->get_current_clocks(
			adev->powerplay.pp_handle,
			&pp_clk_info);
	else if (adev->smu.funcs)
		ret = smu_get_current_clocks(&adev->smu, &pp_clk_info);
	if (ret)
		return false;

+78 −0
Original line number Diff line number Diff line
@@ -814,6 +814,84 @@ int smu_display_configuration_change(struct smu_context *smu,
	return 0;
}

static int smu_get_clock_info(struct smu_context *smu,
			      struct smu_clock_info *clk_info,
			      enum smu_perf_level_designation designation)
{
	int ret;
	struct smu_performance_level level = {0};

	if (!clk_info)
		return -EINVAL;

	ret = smu_get_perf_level(smu, PERF_LEVEL_ACTIVITY, &level);
	if (ret)
		return -EINVAL;

	clk_info->min_mem_clk = level.memory_clock;
	clk_info->min_eng_clk = level.core_clock;
	clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width;

	ret = smu_get_perf_level(smu, designation, &level);
	if (ret)
		return -EINVAL;

	clk_info->min_mem_clk = level.memory_clock;
	clk_info->min_eng_clk = level.core_clock;
	clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width;

	return 0;
}

int smu_get_current_clocks(struct smu_context *smu,
			   struct amd_pp_clock_info *clocks)
{
	struct amd_pp_simple_clock_info simple_clocks = {0};
	struct smu_clock_info hw_clocks;
	int ret = 0;

	if (!is_support_sw_smu(smu->adev))
		return -EINVAL;

	mutex_lock(&smu->mutex);

	smu_get_dal_power_level(smu, &simple_clocks);

	if (smu->support_power_containment)
		ret = smu_get_clock_info(smu, &hw_clocks,
					 PERF_LEVEL_POWER_CONTAINMENT);
	else
		ret = smu_get_clock_info(smu, &hw_clocks, PERF_LEVEL_ACTIVITY);

	if (ret) {
		pr_err("Error in smu_get_clock_info\n");
		goto failed;
	}

	clocks->min_engine_clock = hw_clocks.min_eng_clk;
	clocks->max_engine_clock = hw_clocks.max_eng_clk;
	clocks->min_memory_clock = hw_clocks.min_mem_clk;
	clocks->max_memory_clock = hw_clocks.max_mem_clk;
	clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
	clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
	clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
	clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;

        if (simple_clocks.level == 0)
                clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
        else
                clocks->max_clocks_state = simple_clocks.level;

        if (!smu_get_current_shallow_sleep_clocks(smu, &hw_clocks)) {
                clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
                clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
        }

failed:
	mutex_unlock(&smu->mutex);
	return ret;
}

static int smu_set_clockgating_state(void *handle,
				     enum amd_clockgating_state state)
{
+4 −0
Original line number Diff line number Diff line
@@ -233,6 +233,8 @@ struct smu_context

	uint32_t power_limit;
	uint32_t default_power_limit;

	bool support_power_containment;
};

struct pptable_funcs {
@@ -465,5 +467,7 @@ enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu);
extern int smu_display_configuration_change(struct smu_context *smu, const
					    struct amd_pp_display_configuration
					    *display_config);
extern int smu_get_current_clocks(struct smu_context *smu,
				  struct amd_pp_clock_info *clocks);

#endif