Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d83b1e81 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu/cz: add code to enable forcing UVD clocks



UVD DPM works similarly to SCLK DPM.  Add a similar interface
for UVD for forcing the UVD clocks.

Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 888c9e33
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
@@ -1078,6 +1078,37 @@ static uint32_t cz_get_eclk_level(struct amdgpu_device *adev,
	return i;
}

static uint32_t cz_get_uvd_level(struct amdgpu_device *adev,
				 uint32_t clock, uint16_t msg)
{
	int i = 0;
	struct amdgpu_uvd_clock_voltage_dependency_table *table =
		&adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;

	switch (msg) {
	case PPSMC_MSG_SetUvdSoftMin:
	case PPSMC_MSG_SetUvdHardMin:
		for (i = 0; i < table->count; i++)
			if (clock <= table->entries[i].vclk)
				break;
		if (i == table->count)
			i = table->count - 1;
		break;
	case PPSMC_MSG_SetUvdSoftMax:
	case PPSMC_MSG_SetUvdHardMax:
		for (i = table->count - 1; i >= 0; i--)
			if (clock >= table->entries[i].vclk)
				break;
		if (i < 0)
			i = 0;
		break;
	default:
		break;
	}

	return i;
}

static int cz_program_bootup_state(struct amdgpu_device *adev)
{
	struct cz_power_info *pi = cz_get_pi(adev);
@@ -1739,6 +1770,104 @@ static int cz_dpm_unforce_dpm_levels(struct amdgpu_device *adev)
	return 0;
}


static int cz_dpm_uvd_force_highest(struct amdgpu_device *adev)
{
	struct cz_power_info *pi = cz_get_pi(adev);
	int ret = 0;

	if (pi->uvd_dpm.soft_min_clk != pi->uvd_dpm.soft_max_clk) {
		pi->uvd_dpm.soft_min_clk =
			pi->uvd_dpm.soft_max_clk;
		ret = cz_send_msg_to_smc_with_parameter(adev,
				PPSMC_MSG_SetUvdSoftMin,
				cz_get_uvd_level(adev,
					pi->uvd_dpm.soft_min_clk,
					PPSMC_MSG_SetUvdSoftMin));
		if (ret)
			return ret;
	}

	return ret;
}

static int cz_dpm_uvd_force_lowest(struct amdgpu_device *adev)
{
	struct cz_power_info *pi = cz_get_pi(adev);
	int ret = 0;

	if (pi->uvd_dpm.soft_max_clk != pi->uvd_dpm.soft_min_clk) {
		pi->uvd_dpm.soft_max_clk = pi->uvd_dpm.soft_min_clk;
		ret = cz_send_msg_to_smc_with_parameter(adev,
				PPSMC_MSG_SetUvdSoftMax,
				cz_get_uvd_level(adev,
					pi->uvd_dpm.soft_max_clk,
					PPSMC_MSG_SetUvdSoftMax));
		if (ret)
			return ret;
	}

	return ret;
}

static uint32_t cz_dpm_get_max_uvd_level(struct amdgpu_device *adev)
{
	struct cz_power_info *pi = cz_get_pi(adev);

	if (!pi->max_uvd_level) {
		cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel);
		pi->max_uvd_level = cz_get_argument(adev) + 1;
	}

	if (pi->max_uvd_level > CZ_MAX_HARDWARE_POWERLEVELS) {
		DRM_ERROR("Invalid max uvd level!\n");
		return -EINVAL;
	}

	return pi->max_uvd_level;
}

static int cz_dpm_unforce_uvd_dpm_levels(struct amdgpu_device *adev)
{
	struct cz_power_info *pi = cz_get_pi(adev);
	struct amdgpu_uvd_clock_voltage_dependency_table *dep_table =
		&adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
	uint32_t level = 0;
	int ret = 0;

	pi->uvd_dpm.soft_min_clk = dep_table->entries[0].vclk;
	level = cz_dpm_get_max_uvd_level(adev) - 1;
	if (level < dep_table->count)
		pi->uvd_dpm.soft_max_clk = dep_table->entries[level].vclk;
	else
		pi->uvd_dpm.soft_max_clk =
			dep_table->entries[dep_table->count - 1].vclk;

	/* get min/max sclk soft value
	 * notify SMU to execute */
	ret = cz_send_msg_to_smc_with_parameter(adev,
				PPSMC_MSG_SetUvdSoftMin,
				cz_get_uvd_level(adev,
					pi->uvd_dpm.soft_min_clk,
					PPSMC_MSG_SetUvdSoftMin));
	if (ret)
		return ret;

	ret = cz_send_msg_to_smc_with_parameter(adev,
				PPSMC_MSG_SetUvdSoftMax,
				cz_get_uvd_level(adev,
					pi->uvd_dpm.soft_max_clk,
					PPSMC_MSG_SetUvdSoftMax));
	if (ret)
		return ret;

	DRM_DEBUG("DPM uvd unforce state min=%d, max=%d.\n",
		  pi->uvd_dpm.soft_min_clk,
		  pi->uvd_dpm.soft_max_clk);

	return 0;
}

static int cz_dpm_force_dpm_level(struct amdgpu_device *adev,
				  enum amdgpu_dpm_forced_level level)
{
+1 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ struct cz_power_info {
	uint32_t voltage_drop_threshold;
	uint32_t gfx_pg_threshold;
	uint32_t max_sclk_level;
	uint32_t max_uvd_level;
	/* flags */
	bool didt_enabled;
	bool video_start;