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

Commit 19fbc43a authored by Eric Huang's avatar Eric Huang Committed by Alex Deucher
Browse files

drm/amdgpu: add the CI code to enable clock level selection

parent 8b2e574d
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -6414,6 +6414,118 @@ static int ci_dpm_set_powergating_state(void *handle,
	return 0;
}

static int ci_dpm_print_clock_levels(struct amdgpu_device *adev,
		enum pp_clock_type type, char *buf)
{
	struct ci_power_info *pi = ci_get_pi(adev);
	struct ci_single_dpm_table *sclk_table = &pi->dpm_table.sclk_table;
	struct ci_single_dpm_table *mclk_table = &pi->dpm_table.mclk_table;
	struct ci_single_dpm_table *pcie_table = &pi->dpm_table.pcie_speed_table;

	int i, now, size = 0;
	uint32_t clock, pcie_speed;

	switch (type) {
	case PP_SCLK:
		amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_API_GetSclkFrequency);
		clock = RREG32(mmSMC_MSG_ARG_0);

		for (i = 0; i < sclk_table->count; i++) {
			if (clock > sclk_table->dpm_levels[i].value)
				continue;
			break;
		}
		now = i;

		for (i = 0; i < sclk_table->count; i++)
			size += sprintf(buf + size, "%d: %uMhz %s\n",
					i, sclk_table->dpm_levels[i].value / 100,
					(i == now) ? "*" : "");
		break;
	case PP_MCLK:
		amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_API_GetMclkFrequency);
		clock = RREG32(mmSMC_MSG_ARG_0);

		for (i = 0; i < mclk_table->count; i++) {
			if (clock > mclk_table->dpm_levels[i].value)
				continue;
			break;
		}
		now = i;

		for (i = 0; i < mclk_table->count; i++)
			size += sprintf(buf + size, "%d: %uMhz %s\n",
					i, mclk_table->dpm_levels[i].value / 100,
					(i == now) ? "*" : "");
		break;
	case PP_PCIE:
		pcie_speed = ci_get_current_pcie_speed(adev);
		for (i = 0; i < pcie_table->count; i++) {
			if (pcie_speed != pcie_table->dpm_levels[i].value)
				continue;
			break;
		}
		now = i;

		for (i = 0; i < pcie_table->count; i++)
			size += sprintf(buf + size, "%d: %s %s\n", i,
					(pcie_table->dpm_levels[i].value == 0) ? "2.5GB, x1" :
					(pcie_table->dpm_levels[i].value == 1) ? "5.0GB, x16" :
					(pcie_table->dpm_levels[i].value == 2) ? "8.0GB, x16" : "",
					(i == now) ? "*" : "");
		break;
	default:
		break;
	}

	return size;
}

static int ci_dpm_force_clock_level(struct amdgpu_device *adev,
		enum pp_clock_type type, uint32_t mask)
{
	struct ci_power_info *pi = ci_get_pi(adev);

	if (adev->pm.dpm.forced_level
			!= AMDGPU_DPM_FORCED_LEVEL_MANUAL)
		return -EINVAL;

	switch (type) {
	case PP_SCLK:
		if (!pi->sclk_dpm_key_disabled)
			amdgpu_ci_send_msg_to_smc_with_parameter(adev,
					PPSMC_MSG_SCLKDPM_SetEnabledMask,
					pi->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
		break;

	case PP_MCLK:
		if (!pi->mclk_dpm_key_disabled)
			amdgpu_ci_send_msg_to_smc_with_parameter(adev,
					PPSMC_MSG_MCLKDPM_SetEnabledMask,
					pi->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
		break;

	case PP_PCIE:
	{
		uint32_t tmp = mask & pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
		uint32_t level = 0;

		while (tmp >>= 1)
			level++;

		if (!pi->pcie_dpm_key_disabled)
			amdgpu_ci_send_msg_to_smc_with_parameter(adev,
					PPSMC_MSG_PCIeDPM_ForceLevel,
					level);
		break;
	}
	default:
		break;
	}

	return 0;
}

const struct amd_ip_funcs ci_dpm_ip_funcs = {
	.name = "ci_dpm",
	.early_init = ci_dpm_early_init,
@@ -6448,6 +6560,8 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = {
	.get_fan_control_mode = &ci_dpm_get_fan_control_mode,
	.set_fan_speed_percent = &ci_dpm_set_fan_speed_percent,
	.get_fan_speed_percent = &ci_dpm_get_fan_speed_percent,
	.print_clock_levels = ci_dpm_print_clock_levels,
	.force_clock_level = ci_dpm_force_clock_level,
};

static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)