diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 94 |
1 files changed, 74 insertions, 20 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index ee738a524639..53d6e1bb48dc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -361,6 +361,11 @@ static ssize_t radeon_set_pm_profile(struct device *dev, | |||
361 | struct drm_device *ddev = dev_get_drvdata(dev); | 361 | struct drm_device *ddev = dev_get_drvdata(dev); |
362 | struct radeon_device *rdev = ddev->dev_private; | 362 | struct radeon_device *rdev = ddev->dev_private; |
363 | 363 | ||
364 | /* Can't set profile when the card is off */ | ||
365 | if ((rdev->flags & RADEON_IS_PX) && | ||
366 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
367 | return -EINVAL; | ||
368 | |||
364 | mutex_lock(&rdev->pm.mutex); | 369 | mutex_lock(&rdev->pm.mutex); |
365 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | 370 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { |
366 | if (strncmp("default", buf, strlen("default")) == 0) | 371 | if (strncmp("default", buf, strlen("default")) == 0) |
@@ -409,6 +414,13 @@ static ssize_t radeon_set_pm_method(struct device *dev, | |||
409 | struct drm_device *ddev = dev_get_drvdata(dev); | 414 | struct drm_device *ddev = dev_get_drvdata(dev); |
410 | struct radeon_device *rdev = ddev->dev_private; | 415 | struct radeon_device *rdev = ddev->dev_private; |
411 | 416 | ||
417 | /* Can't set method when the card is off */ | ||
418 | if ((rdev->flags & RADEON_IS_PX) && | ||
419 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { | ||
420 | count = -EINVAL; | ||
421 | goto fail; | ||
422 | } | ||
423 | |||
412 | /* we don't support the legacy modes with dpm */ | 424 | /* we don't support the legacy modes with dpm */ |
413 | if (rdev->pm.pm_method == PM_METHOD_DPM) { | 425 | if (rdev->pm.pm_method == PM_METHOD_DPM) { |
414 | count = -EINVAL; | 426 | count = -EINVAL; |
@@ -446,6 +458,10 @@ static ssize_t radeon_get_dpm_state(struct device *dev, | |||
446 | struct radeon_device *rdev = ddev->dev_private; | 458 | struct radeon_device *rdev = ddev->dev_private; |
447 | enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; | 459 | enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; |
448 | 460 | ||
461 | if ((rdev->flags & RADEON_IS_PX) && | ||
462 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
463 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
464 | |||
449 | return snprintf(buf, PAGE_SIZE, "%s\n", | 465 | return snprintf(buf, PAGE_SIZE, "%s\n", |
450 | (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : | 466 | (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : |
451 | (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); | 467 | (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); |
@@ -459,6 +475,11 @@ static ssize_t radeon_set_dpm_state(struct device *dev, | |||
459 | struct drm_device *ddev = dev_get_drvdata(dev); | 475 | struct drm_device *ddev = dev_get_drvdata(dev); |
460 | struct radeon_device *rdev = ddev->dev_private; | 476 | struct radeon_device *rdev = ddev->dev_private; |
461 | 477 | ||
478 | /* Can't set dpm state when the card is off */ | ||
479 | if ((rdev->flags & RADEON_IS_PX) && | ||
480 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
481 | return -EINVAL; | ||
482 | |||
462 | mutex_lock(&rdev->pm.mutex); | 483 | mutex_lock(&rdev->pm.mutex); |
463 | if (strncmp("battery", buf, strlen("battery")) == 0) | 484 | if (strncmp("battery", buf, strlen("battery")) == 0) |
464 | rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; | 485 | rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; |
@@ -485,6 +506,10 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev, | |||
485 | struct radeon_device *rdev = ddev->dev_private; | 506 | struct radeon_device *rdev = ddev->dev_private; |
486 | enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; | 507 | enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; |
487 | 508 | ||
509 | if ((rdev->flags & RADEON_IS_PX) && | ||
510 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
511 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
512 | |||
488 | return snprintf(buf, PAGE_SIZE, "%s\n", | 513 | return snprintf(buf, PAGE_SIZE, "%s\n", |
489 | (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" : | 514 | (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" : |
490 | (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); | 515 | (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); |
@@ -500,6 +525,11 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev, | |||
500 | enum radeon_dpm_forced_level level; | 525 | enum radeon_dpm_forced_level level; |
501 | int ret = 0; | 526 | int ret = 0; |
502 | 527 | ||
528 | /* Can't force performance level when the card is off */ | ||
529 | if ((rdev->flags & RADEON_IS_PX) && | ||
530 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
531 | return -EINVAL; | ||
532 | |||
503 | mutex_lock(&rdev->pm.mutex); | 533 | mutex_lock(&rdev->pm.mutex); |
504 | if (strncmp("low", buf, strlen("low")) == 0) { | 534 | if (strncmp("low", buf, strlen("low")) == 0) { |
505 | level = RADEON_DPM_FORCED_LEVEL_LOW; | 535 | level = RADEON_DPM_FORCED_LEVEL_LOW; |
@@ -538,8 +568,14 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, | |||
538 | char *buf) | 568 | char *buf) |
539 | { | 569 | { |
540 | struct radeon_device *rdev = dev_get_drvdata(dev); | 570 | struct radeon_device *rdev = dev_get_drvdata(dev); |
571 | struct drm_device *ddev = rdev->ddev; | ||
541 | int temp; | 572 | int temp; |
542 | 573 | ||
574 | /* Can't get temperature when the card is off */ | ||
575 | if ((rdev->flags & RADEON_IS_PX) && | ||
576 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
577 | return -EINVAL; | ||
578 | |||
543 | if (rdev->asic->pm.get_temperature) | 579 | if (rdev->asic->pm.get_temperature) |
544 | temp = radeon_get_temperature(rdev); | 580 | temp = radeon_get_temperature(rdev); |
545 | else | 581 | else |
@@ -603,7 +639,6 @@ static const struct attribute_group *hwmon_groups[] = { | |||
603 | static int radeon_hwmon_init(struct radeon_device *rdev) | 639 | static int radeon_hwmon_init(struct radeon_device *rdev) |
604 | { | 640 | { |
605 | int err = 0; | 641 | int err = 0; |
606 | struct device *hwmon_dev; | ||
607 | 642 | ||
608 | switch (rdev->pm.int_thermal_type) { | 643 | switch (rdev->pm.int_thermal_type) { |
609 | case THERMAL_TYPE_RV6XX: | 644 | case THERMAL_TYPE_RV6XX: |
@@ -616,11 +651,11 @@ static int radeon_hwmon_init(struct radeon_device *rdev) | |||
616 | case THERMAL_TYPE_KV: | 651 | case THERMAL_TYPE_KV: |
617 | if (rdev->asic->pm.get_temperature == NULL) | 652 | if (rdev->asic->pm.get_temperature == NULL) |
618 | return err; | 653 | return err; |
619 | hwmon_dev = hwmon_device_register_with_groups(rdev->dev, | 654 | rdev->pm.int_hwmon_dev = hwmon_device_register_with_groups(rdev->dev, |
620 | "radeon", rdev, | 655 | "radeon", rdev, |
621 | hwmon_groups); | 656 | hwmon_groups); |
622 | if (IS_ERR(hwmon_dev)) { | 657 | if (IS_ERR(rdev->pm.int_hwmon_dev)) { |
623 | err = PTR_ERR(hwmon_dev); | 658 | err = PTR_ERR(rdev->pm.int_hwmon_dev); |
624 | dev_err(rdev->dev, | 659 | dev_err(rdev->dev, |
625 | "Unable to register hwmon device: %d\n", err); | 660 | "Unable to register hwmon device: %d\n", err); |
626 | } | 661 | } |
@@ -632,6 +667,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev) | |||
632 | return err; | 667 | return err; |
633 | } | 668 | } |
634 | 669 | ||
670 | static void radeon_hwmon_fini(struct radeon_device *rdev) | ||
671 | { | ||
672 | if (rdev->pm.int_hwmon_dev) | ||
673 | hwmon_device_unregister(rdev->pm.int_hwmon_dev); | ||
674 | } | ||
675 | |||
635 | static void radeon_dpm_thermal_work_handler(struct work_struct *work) | 676 | static void radeon_dpm_thermal_work_handler(struct work_struct *work) |
636 | { | 677 | { |
637 | struct radeon_device *rdev = | 678 | struct radeon_device *rdev = |
@@ -1257,6 +1298,7 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
1257 | case CHIP_RV670: | 1298 | case CHIP_RV670: |
1258 | case CHIP_RS780: | 1299 | case CHIP_RS780: |
1259 | case CHIP_RS880: | 1300 | case CHIP_RS880: |
1301 | case CHIP_RV770: | ||
1260 | case CHIP_BARTS: | 1302 | case CHIP_BARTS: |
1261 | case CHIP_TURKS: | 1303 | case CHIP_TURKS: |
1262 | case CHIP_CAICOS: | 1304 | case CHIP_CAICOS: |
@@ -1273,7 +1315,6 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
1273 | else | 1315 | else |
1274 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1316 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
1275 | break; | 1317 | break; |
1276 | case CHIP_RV770: | ||
1277 | case CHIP_RV730: | 1318 | case CHIP_RV730: |
1278 | case CHIP_RV710: | 1319 | case CHIP_RV710: |
1279 | case CHIP_RV740: | 1320 | case CHIP_RV740: |
@@ -1295,6 +1336,7 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
1295 | case CHIP_KABINI: | 1336 | case CHIP_KABINI: |
1296 | case CHIP_KAVERI: | 1337 | case CHIP_KAVERI: |
1297 | case CHIP_HAWAII: | 1338 | case CHIP_HAWAII: |
1339 | case CHIP_MULLINS: | ||
1298 | /* DPM requires the RLC, RV770+ dGPU requires SMC */ | 1340 | /* DPM requires the RLC, RV770+ dGPU requires SMC */ |
1299 | if (!rdev->rlc_fw) | 1341 | if (!rdev->rlc_fw) |
1300 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1342 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
@@ -1353,6 +1395,8 @@ static void radeon_pm_fini_old(struct radeon_device *rdev) | |||
1353 | device_remove_file(rdev->dev, &dev_attr_power_method); | 1395 | device_remove_file(rdev->dev, &dev_attr_power_method); |
1354 | } | 1396 | } |
1355 | 1397 | ||
1398 | radeon_hwmon_fini(rdev); | ||
1399 | |||
1356 | if (rdev->pm.power_state) | 1400 | if (rdev->pm.power_state) |
1357 | kfree(rdev->pm.power_state); | 1401 | kfree(rdev->pm.power_state); |
1358 | } | 1402 | } |
@@ -1372,6 +1416,8 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev) | |||
1372 | } | 1416 | } |
1373 | radeon_dpm_fini(rdev); | 1417 | radeon_dpm_fini(rdev); |
1374 | 1418 | ||
1419 | radeon_hwmon_fini(rdev); | ||
1420 | |||
1375 | if (rdev->pm.power_state) | 1421 | if (rdev->pm.power_state) |
1376 | kfree(rdev->pm.power_state); | 1422 | kfree(rdev->pm.power_state); |
1377 | } | 1423 | } |
@@ -1397,12 +1443,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev) | |||
1397 | 1443 | ||
1398 | rdev->pm.active_crtcs = 0; | 1444 | rdev->pm.active_crtcs = 0; |
1399 | rdev->pm.active_crtc_count = 0; | 1445 | rdev->pm.active_crtc_count = 0; |
1400 | list_for_each_entry(crtc, | 1446 | if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { |
1401 | &ddev->mode_config.crtc_list, head) { | 1447 | list_for_each_entry(crtc, |
1402 | radeon_crtc = to_radeon_crtc(crtc); | 1448 | &ddev->mode_config.crtc_list, head) { |
1403 | if (radeon_crtc->enabled) { | 1449 | radeon_crtc = to_radeon_crtc(crtc); |
1404 | rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); | 1450 | if (radeon_crtc->enabled) { |
1405 | rdev->pm.active_crtc_count++; | 1451 | rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); |
1452 | rdev->pm.active_crtc_count++; | ||
1453 | } | ||
1406 | } | 1454 | } |
1407 | } | 1455 | } |
1408 | 1456 | ||
@@ -1469,12 +1517,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev) | |||
1469 | /* update active crtc counts */ | 1517 | /* update active crtc counts */ |
1470 | rdev->pm.dpm.new_active_crtcs = 0; | 1518 | rdev->pm.dpm.new_active_crtcs = 0; |
1471 | rdev->pm.dpm.new_active_crtc_count = 0; | 1519 | rdev->pm.dpm.new_active_crtc_count = 0; |
1472 | list_for_each_entry(crtc, | 1520 | if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { |
1473 | &ddev->mode_config.crtc_list, head) { | 1521 | list_for_each_entry(crtc, |
1474 | radeon_crtc = to_radeon_crtc(crtc); | 1522 | &ddev->mode_config.crtc_list, head) { |
1475 | if (crtc->enabled) { | 1523 | radeon_crtc = to_radeon_crtc(crtc); |
1476 | rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id); | 1524 | if (crtc->enabled) { |
1477 | rdev->pm.dpm.new_active_crtc_count++; | 1525 | rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id); |
1526 | rdev->pm.dpm.new_active_crtc_count++; | ||
1527 | } | ||
1478 | } | 1528 | } |
1479 | } | 1529 | } |
1480 | 1530 | ||
@@ -1600,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) | |||
1600 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 1650 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
1601 | struct drm_device *dev = node->minor->dev; | 1651 | struct drm_device *dev = node->minor->dev; |
1602 | struct radeon_device *rdev = dev->dev_private; | 1652 | struct radeon_device *rdev = dev->dev_private; |
1653 | struct drm_device *ddev = rdev->ddev; | ||
1603 | 1654 | ||
1604 | if (rdev->pm.dpm_enabled) { | 1655 | if ((rdev->flags & RADEON_IS_PX) && |
1656 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { | ||
1657 | seq_printf(m, "PX asic powered off\n"); | ||
1658 | } else if (rdev->pm.dpm_enabled) { | ||
1605 | mutex_lock(&rdev->pm.mutex); | 1659 | mutex_lock(&rdev->pm.mutex); |
1606 | if (rdev->asic->dpm.debugfs_print_current_performance_level) | 1660 | if (rdev->asic->dpm.debugfs_print_current_performance_level) |
1607 | radeon_dpm_debugfs_print_current_performance_level(rdev, m); | 1661 | radeon_dpm_debugfs_print_current_performance_level(rdev, m); |