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

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

drm/amdgpu: add the common code to support mclk OD



This implements mclk OverDrive(OD) through sysfs.
The new entry pp_mclk_od is read/write. The value of input/output
is an integer of the overclocking percentage.

Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarEric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6bb6b297
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -1563,6 +1563,8 @@ struct amdgpu_dpm_funcs {
	int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
	int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
	int (*get_sclk_od)(struct amdgpu_device *adev);
	int (*get_sclk_od)(struct amdgpu_device *adev);
	int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
	int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
	int (*get_mclk_od)(struct amdgpu_device *adev);
	int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value);
};
};


struct amdgpu_dpm {
struct amdgpu_dpm {
@@ -2351,6 +2353,12 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_dpm_set_sclk_od(adev, value) \
#define amdgpu_dpm_set_sclk_od(adev, value) \
	(adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)
	(adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)


#define amdgpu_dpm_get_mclk_od(adev) \
	((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle))

#define amdgpu_dpm_set_mclk_od(adev, value) \
	((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))

#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)		\
#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)		\
	(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
	(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))


+55 −0
Original line number Original line Diff line number Diff line
@@ -527,6 +527,52 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev,
	return count;
	return count;
}
}


static ssize_t amdgpu_get_pp_mclk_od(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct drm_device *ddev = dev_get_drvdata(dev);
	struct amdgpu_device *adev = ddev->dev_private;
	uint32_t value = 0;

	if (adev->pp_enabled)
		value = amdgpu_dpm_get_mclk_od(adev);
	else if (adev->pm.funcs->get_mclk_od)
		value = adev->pm.funcs->get_mclk_od(adev);

	return snprintf(buf, PAGE_SIZE, "%d\n", value);
}

static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t count)
{
	struct drm_device *ddev = dev_get_drvdata(dev);
	struct amdgpu_device *adev = ddev->dev_private;
	int ret;
	long int value;

	ret = kstrtol(buf, 0, &value);

	if (ret) {
		count = -EINVAL;
		goto fail;
	}

	if (adev->pp_enabled) {
		amdgpu_dpm_set_mclk_od(adev, (uint32_t)value);
		amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL);
	} else if (adev->pm.funcs->set_mclk_od) {
		adev->pm.funcs->set_mclk_od(adev, (uint32_t)value);
		adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
		amdgpu_pm_compute_clocks(adev);
	}

fail:
	return count;
}

static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
		   amdgpu_get_dpm_forced_performance_level,
		   amdgpu_get_dpm_forced_performance_level,
@@ -551,6 +597,9 @@ static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR,
		amdgpu_get_pp_sclk_od,
		amdgpu_get_pp_sclk_od,
		amdgpu_set_pp_sclk_od);
		amdgpu_set_pp_sclk_od);
static DEVICE_ATTR(pp_mclk_od, S_IRUGO | S_IWUSR,
		amdgpu_get_pp_mclk_od,
		amdgpu_set_pp_mclk_od);


static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
				      struct device_attribute *attr,
				      struct device_attribute *attr,
@@ -1191,6 +1240,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
		DRM_ERROR("failed to create device file pp_sclk_od\n");
		DRM_ERROR("failed to create device file pp_sclk_od\n");
		return ret;
		return ret;
	}
	}
	ret = device_create_file(adev->dev, &dev_attr_pp_mclk_od);
	if (ret) {
		DRM_ERROR("failed to create device file pp_mclk_od\n");
		return ret;
	}


	ret = amdgpu_debugfs_pm_init(adev);
	ret = amdgpu_debugfs_pm_init(adev);
	if (ret) {
	if (ret) {
@@ -1219,6 +1273,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
	device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
	device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
	device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
	device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
	device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
	device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
	device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
}
}


void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
+40 −0
Original line number Original line Diff line number Diff line
@@ -848,6 +848,44 @@ static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
	return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
	return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
}
}


static int pp_dpm_get_mclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;

	if (!handle)
		return -EINVAL;

	hwmgr = ((struct pp_instance *)handle)->hwmgr;

	PP_CHECK_HW(hwmgr);

	if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
		printk(KERN_INFO "%s was not implemented.\n", __func__);
		return 0;
	}

	return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
}

static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;

	if (!handle)
		return -EINVAL;

	hwmgr = ((struct pp_instance *)handle)->hwmgr;

	PP_CHECK_HW(hwmgr);

	if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
		printk(KERN_INFO "%s was not implemented.\n", __func__);
		return 0;
	}

	return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
}

const struct amd_powerplay_funcs pp_dpm_funcs = {
const struct amd_powerplay_funcs pp_dpm_funcs = {
	.get_temperature = pp_dpm_get_temperature,
	.get_temperature = pp_dpm_get_temperature,
	.load_firmware = pp_dpm_load_fw,
	.load_firmware = pp_dpm_load_fw,
@@ -872,6 +910,8 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
	.print_clock_levels = pp_dpm_print_clock_levels,
	.print_clock_levels = pp_dpm_print_clock_levels,
	.get_sclk_od = pp_dpm_get_sclk_od,
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
};
};


static int amd_pp_instance_init(struct amd_pp_init *pp_init,
static int amd_pp_instance_init(struct amd_pp_init *pp_init,
+2 −0
Original line number Original line Diff line number Diff line
@@ -345,6 +345,8 @@ struct amd_powerplay_funcs {
	int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
	int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
	int (*get_sclk_od)(void *handle);
	int (*get_sclk_od)(void *handle);
	int (*set_sclk_od)(void *handle, uint32_t value);
	int (*set_sclk_od)(void *handle, uint32_t value);
	int (*get_mclk_od)(void *handle);
	int (*set_mclk_od)(void *handle, uint32_t value);
};
};


struct amd_powerplay {
struct amd_powerplay {
+2 −0
Original line number Original line Diff line number Diff line
@@ -340,6 +340,8 @@ struct pp_hwmgr_func {
	int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable);
	int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable);
	int (*get_sclk_od)(struct pp_hwmgr *hwmgr);
	int (*get_sclk_od)(struct pp_hwmgr *hwmgr);
	int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
	int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
	int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
	int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
};
};


struct pp_table_func {
struct pp_table_func {