aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-07-02 18:38:02 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-07-05 18:09:19 -0400
commit70d01a5ee29fcb23a6b5948227b1aee212922ade (patch)
treef2087b3fa9b4c6942686367c4390b4a04b6904c4 /drivers/gpu/drm
parent67d5ced503db5b44cb82f378c9cb3f0e77a94e7f (diff)
drm/radeon/dpm: add infrastructure to force performance levels
This allows you to force specific power levels within a power state. Due to hardware restrictions between generations, the interface is limited to the following 3 selections: auto: all levels enabled low: forced to the lowest power level high: forced to the highest power level Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/radeon.h10
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c52
2 files changed, 62 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 08cececb376d..b4681313646c 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1335,6 +1335,12 @@ enum radeon_pcie_gen {
1335 RADEON_PCIE_GEN_INVALID = 0xffff 1335 RADEON_PCIE_GEN_INVALID = 0xffff
1336}; 1336};
1337 1337
1338enum radeon_dpm_forced_level {
1339 RADEON_DPM_FORCED_LEVEL_AUTO = 0,
1340 RADEON_DPM_FORCED_LEVEL_LOW = 1,
1341 RADEON_DPM_FORCED_LEVEL_HIGH = 2,
1342};
1343
1338struct radeon_dpm { 1344struct radeon_dpm {
1339 struct radeon_ps *ps; 1345 struct radeon_ps *ps;
1340 /* number of valid power states */ 1346 /* number of valid power states */
@@ -1374,6 +1380,8 @@ struct radeon_dpm {
1374 bool uvd_active; 1380 bool uvd_active;
1375 /* thermal handling */ 1381 /* thermal handling */
1376 struct radeon_dpm_thermal thermal; 1382 struct radeon_dpm_thermal thermal;
1383 /* forced levels */
1384 enum radeon_dpm_forced_level forced_level;
1377}; 1385};
1378 1386
1379void radeon_dpm_enable_power_state(struct radeon_device *rdev, 1387void radeon_dpm_enable_power_state(struct radeon_device *rdev,
@@ -1669,6 +1677,7 @@ struct radeon_asic {
1669 u32 (*get_mclk)(struct radeon_device *rdev, bool low); 1677 u32 (*get_mclk)(struct radeon_device *rdev, bool low);
1670 void (*print_power_state)(struct radeon_device *rdev, struct radeon_ps *ps); 1678 void (*print_power_state)(struct radeon_device *rdev, struct radeon_ps *ps);
1671 void (*debugfs_print_current_performance_level)(struct radeon_device *rdev, struct seq_file *m); 1679 void (*debugfs_print_current_performance_level)(struct radeon_device *rdev, struct seq_file *m);
1680 int (*force_performance_level)(struct radeon_device *rdev, enum radeon_dpm_forced_level level);
1672 } dpm; 1681 } dpm;
1673 /* pageflipping */ 1682 /* pageflipping */
1674 struct { 1683 struct {
@@ -2436,6 +2445,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
2436#define radeon_dpm_get_mclk(rdev, l) rdev->asic->dpm.get_mclk((rdev), (l)) 2445#define radeon_dpm_get_mclk(rdev, l) rdev->asic->dpm.get_mclk((rdev), (l))
2437#define radeon_dpm_print_power_state(rdev, ps) rdev->asic->dpm.print_power_state((rdev), (ps)) 2446#define radeon_dpm_print_power_state(rdev, ps) rdev->asic->dpm.print_power_state((rdev), (ps))
2438#define radeon_dpm_debugfs_print_current_performance_level(rdev, m) rdev->asic->dpm.debugfs_print_current_performance_level((rdev), (m)) 2447#define radeon_dpm_debugfs_print_current_performance_level(rdev, m) rdev->asic->dpm.debugfs_print_current_performance_level((rdev), (m))
2448#define radeon_dpm_force_performance_level(rdev, l) rdev->asic->dpm.force_performance_level((rdev), (l))
2439 2449
2440/* Common functions */ 2450/* Common functions */
2441/* AGP */ 2451/* AGP */
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index aaafb931922f..2557e8bab5cc 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -468,9 +468,57 @@ fail:
468 return count; 468 return count;
469} 469}
470 470
471static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev,
472 struct device_attribute *attr,
473 char *buf)
474{
475 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
476 struct radeon_device *rdev = ddev->dev_private;
477 enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
478
479 return snprintf(buf, PAGE_SIZE, "%s\n",
480 (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" :
481 (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
482}
483
484static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev,
485 struct device_attribute *attr,
486 const char *buf,
487 size_t count)
488{
489 struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
490 struct radeon_device *rdev = ddev->dev_private;
491 enum radeon_dpm_forced_level level;
492 int ret = 0;
493
494 mutex_lock(&rdev->pm.mutex);
495 if (strncmp("low", buf, strlen("low")) == 0) {
496 level = RADEON_DPM_FORCED_LEVEL_LOW;
497 } else if (strncmp("high", buf, strlen("high")) == 0) {
498 level = RADEON_DPM_FORCED_LEVEL_HIGH;
499 } else if (strncmp("auto", buf, strlen("auto")) == 0) {
500 level = RADEON_DPM_FORCED_LEVEL_AUTO;
501 } else {
502 mutex_unlock(&rdev->pm.mutex);
503 count = -EINVAL;
504 goto fail;
505 }
506 if (rdev->asic->dpm.force_performance_level) {
507 ret = radeon_dpm_force_performance_level(rdev, level);
508 if (ret)
509 count = -EINVAL;
510 }
511 mutex_unlock(&rdev->pm.mutex);
512fail:
513 return count;
514}
515
471static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); 516static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile);
472static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); 517static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method);
473static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state); 518static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state);
519static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
520 radeon_get_dpm_forced_performance_level,
521 radeon_set_dpm_forced_performance_level);
474 522
475static ssize_t radeon_hwmon_show_temp(struct device *dev, 523static ssize_t radeon_hwmon_show_temp(struct device *dev,
476 struct device_attribute *attr, 524 struct device_attribute *attr,
@@ -1066,6 +1114,9 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
1066 ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); 1114 ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
1067 if (ret) 1115 if (ret)
1068 DRM_ERROR("failed to create device file for dpm state\n"); 1116 DRM_ERROR("failed to create device file for dpm state\n");
1117 ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
1118 if (ret)
1119 DRM_ERROR("failed to create device file for dpm state\n");
1069 /* XXX: these are noops for dpm but are here for backwards compat */ 1120 /* XXX: these are noops for dpm but are here for backwards compat */
1070 ret = device_create_file(rdev->dev, &dev_attr_power_profile); 1121 ret = device_create_file(rdev->dev, &dev_attr_power_profile);
1071 if (ret) 1122 if (ret)
@@ -1170,6 +1221,7 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
1170 mutex_unlock(&rdev->pm.mutex); 1221 mutex_unlock(&rdev->pm.mutex);
1171 1222
1172 device_remove_file(rdev->dev, &dev_attr_power_dpm_state); 1223 device_remove_file(rdev->dev, &dev_attr_power_dpm_state);
1224 device_remove_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
1173 /* XXX backwards compat */ 1225 /* XXX backwards compat */
1174 device_remove_file(rdev->dev, &dev_attr_power_profile); 1226 device_remove_file(rdev->dev, &dev_attr_power_profile);
1175 device_remove_file(rdev->dev, &dev_attr_power_method); 1227 device_remove_file(rdev->dev, &dev_attr_power_method);