diff -rupN linux-3.2.1-a/drivers/gpu/drm/radeon/radeon_pm.c linux-3.2.1-b/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-3.2.1-a/drivers/gpu/drm/radeon/radeon_pm.c 2012-01-12 20:42:45.000000000 +0100
+++ linux-3.2.1-b/drivers/gpu/drm/radeon/radeon_pm.c 2012-01-25 12:12:31.474705253 +0100
@@ -19,6 +19,7 @@
*
* Authors: Rafał Miłecki <zajec5@gmail.com>
* Alex Deucher <alexdeucher@gmail.com>
+ * Modified: 2012-01-24 Andrée Ekroth
*/
#include "drmP.h"
#include "radeon.h"
@@ -245,11 +246,6 @@ static void radeon_pm_set_clocks(struct
{
int i;
- /* no need to take locks, etc. if nothing's going to change */
- if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
- (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
- return;
-
mutex_lock(&rdev->ddev->struct_mutex);
mutex_lock(&rdev->vram_mutex);
mutex_lock(&rdev->cp.mutex);
@@ -442,8 +438,119 @@ fail:
return count;
}
+static ssize_t radeon_set_engine(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+ struct radeon_device *rdev = ddev->dev_private;
+ struct radeon_power_state *power_state;
+ struct radeon_pm_clock_info *clock_info;
+ int i, j;
+ uint32_t speed = (uint32_t)simple_strtoul(buf, NULL, 0);
+
+ if (speed == 0)
+ {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ DRM_DEBUG_DRIVER("Setting engine speed: %d MHz", speed);
+
+ mutex_lock(&rdev->pm.mutex);
+ for (i = 0; i < rdev->pm.num_power_states; i++) {
+ power_state = &rdev->pm.power_state[i];
+ for (j = 0; j < power_state->num_clock_modes; j++) {
+ clock_info = &(power_state->clock_info[j]);
+ clock_info->sclk = speed * 100;
+ }
+ }
+ mutex_unlock(&rdev->pm.mutex);
+
+ radeon_pm_update_profile(rdev);
+ radeon_pm_set_clocks(rdev);
+fail:
+ return count;
+}
+
+static ssize_t radeon_set_memory(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+ struct radeon_device *rdev = ddev->dev_private;
+ struct radeon_power_state *power_state;
+ struct radeon_pm_clock_info *clock_info;
+ int i, j;
+ uint32_t speed = (uint32_t)simple_strtoul(buf, NULL, 0);
+
+ if (speed == 0 || (rdev->flags & RADEON_IS_IGP))
+ {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ DRM_DEBUG_DRIVER("Setting memory speed: %d MHz", speed);
+
+ mutex_lock(&rdev->pm.mutex);
+ for (i = 0; i < rdev->pm.num_power_states; i++) {
+ power_state = &rdev->pm.power_state[i];
+ for (j = 0; j < power_state->num_clock_modes; j++) {
+ clock_info = &(power_state->clock_info[j]);
+ clock_info->mclk = speed * 100;
+ }
+ }
+ mutex_unlock(&rdev->pm.mutex);
+
+ radeon_pm_update_profile(rdev);
+ radeon_pm_set_clocks(rdev);
+fail:
+ return count;
+}
+
+static ssize_t radeon_set_voltage(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+ struct radeon_device *rdev = ddev->dev_private;
+ struct radeon_power_state *power_state;
+ struct radeon_pm_clock_info *clock_info;
+ int i, j;
+ uint32_t speed = (uint32_t)simple_strtoul(buf, NULL, 0);
+
+ if (speed == 0 || (rdev->flags & RADEON_IS_IGP))
+ {
+ count = -EINVAL;
+ goto fail;
+ }
+
+ DRM_DEBUG_DRIVER("Setting voltage: %d mV", speed);
+
+ mutex_lock(&rdev->pm.mutex);
+ for (i = 0; i < rdev->pm.num_power_states; i++) {
+ power_state = &rdev->pm.power_state[i];
+ for (j = 0; j < power_state->num_clock_modes; j++) {
+ clock_info = &(power_state->clock_info[j]);
+ clock_info->voltage.voltage = speed;
+ }
+ }
+ mutex_unlock(&rdev->pm.mutex);
+
+ radeon_pm_update_profile(rdev);
+ radeon_pm_set_clocks(rdev);
+fail:
+ return count;
+}
+
static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile);
static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method);
+static DEVICE_ATTR(engine, S_IWUSR, 0, radeon_set_engine);
+static DEVICE_ATTR(memory, S_IWUSR, 0, radeon_set_memory);
+static DEVICE_ATTR(voltage, S_IWUSR, 0, radeon_set_voltage);
static ssize_t radeon_hwmon_show_temp(struct device *dev,
struct device_attribute *attr,
@@ -637,6 +744,15 @@ int radeon_pm_init(struct radeon_device
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
+ ret = device_create_file(rdev->dev, &dev_attr_engine);
+ if (ret)
+ DRM_ERROR("failed to create device file for engine\n");
+ ret = device_create_file(rdev->dev, &dev_attr_memory);
+ if (ret)
+ DRM_ERROR("failed to create device file for memory\n");
+ ret = device_create_file(rdev->dev, &dev_attr_voltage);
+ if (ret)
+ DRM_ERROR("failed to create device file for voltage\n");
#ifdef CONFIG_ACPI
rdev->acpi_nb.notifier_call = radeon_acpi_event;
@@ -646,6 +762,7 @@ int radeon_pm_init(struct radeon_device
DRM_ERROR("Failed to register debugfs file for PM!\n");
}
+ DRM_INFO("radeon: glakke overclock initialized\n");
DRM_INFO("radeon: power management initialized\n");
}
@@ -672,6 +789,9 @@ void radeon_pm_fini(struct radeon_device
device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_power_method);
+ device_remove_file(rdev->dev, &dev_attr_engine);
+ device_remove_file(rdev->dev, &dev_attr_memory);
+ device_remove_file(rdev->dev, &dev_attr_voltage);
#ifdef CONFIG_ACPI
unregister_acpi_notifier(&rdev->acpi_nb);
#endif