diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 115d26b762cc..ed66062ae9d0 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
28 | #endif | 28 | #endif |
29 | #include <linux/power_supply.h> | 29 | #include <linux/power_supply.h> |
30 | #include <linux/hwmon.h> | ||
31 | #include <linux/hwmon-sysfs.h> | ||
30 | 32 | ||
31 | #define RADEON_IDLE_LOOP_MS 100 | 33 | #define RADEON_IDLE_LOOP_MS 100 |
32 | #define RADEON_RECLOCK_DELAY_MS 200 | 34 | #define RADEON_RECLOCK_DELAY_MS 200 |
@@ -423,6 +425,82 @@ fail: | |||
423 | static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); | 425 | static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); |
424 | static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); | 426 | static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); |
425 | 427 | ||
428 | static ssize_t radeon_hwmon_show_temp(struct device *dev, | ||
429 | struct device_attribute *attr, | ||
430 | char *buf) | ||
431 | { | ||
432 | struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | ||
433 | struct radeon_device *rdev = ddev->dev_private; | ||
434 | u32 temp; | ||
435 | |||
436 | switch (rdev->pm.int_thermal_type) { | ||
437 | case THERMAL_TYPE_RV6XX: | ||
438 | temp = rv6xx_get_temp(rdev); | ||
439 | break; | ||
440 | case THERMAL_TYPE_RV770: | ||
441 | temp = rv770_get_temp(rdev); | ||
442 | break; | ||
443 | case THERMAL_TYPE_EVERGREEN: | ||
444 | temp = evergreen_get_temp(rdev); | ||
445 | break; | ||
446 | default: | ||
447 | temp = 0; | ||
448 | break; | ||
449 | } | ||
450 | |||
451 | return snprintf(buf, PAGE_SIZE, "%d\n", temp); | ||
452 | } | ||
453 | |||
454 | static ssize_t radeon_hwmon_show_name(struct device *dev, | ||
455 | struct device_attribute *attr, | ||
456 | char *buf) | ||
457 | { | ||
458 | return sprintf(buf, "radeon\n"); | ||
459 | } | ||
460 | |||
461 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); | ||
462 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0); | ||
463 | |||
464 | static struct attribute *hwmon_attributes[] = { | ||
465 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
466 | &sensor_dev_attr_name.dev_attr.attr, | ||
467 | NULL | ||
468 | }; | ||
469 | |||
470 | static const struct attribute_group hwmon_attrgroup = { | ||
471 | .attrs = hwmon_attributes, | ||
472 | }; | ||
473 | |||
474 | static void radeon_hwmon_init(struct radeon_device *rdev) | ||
475 | { | ||
476 | int err; | ||
477 | |||
478 | rdev->pm.int_hwmon_dev = NULL; | ||
479 | |||
480 | switch (rdev->pm.int_thermal_type) { | ||
481 | case THERMAL_TYPE_RV6XX: | ||
482 | case THERMAL_TYPE_RV770: | ||
483 | case THERMAL_TYPE_EVERGREEN: | ||
484 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); | ||
485 | dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); | ||
486 | err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, | ||
487 | &hwmon_attrgroup); | ||
488 | if (err) | ||
489 | DRM_ERROR("Unable to create hwmon sysfs file: %d\n", err); | ||
490 | break; | ||
491 | default: | ||
492 | break; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | static void radeon_hwmon_fini(struct radeon_device *rdev) | ||
497 | { | ||
498 | if (rdev->pm.int_hwmon_dev) { | ||
499 | sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup); | ||
500 | hwmon_device_unregister(rdev->pm.int_hwmon_dev); | ||
501 | } | ||
502 | } | ||
503 | |||
426 | void radeon_pm_suspend(struct radeon_device *rdev) | 504 | void radeon_pm_suspend(struct radeon_device *rdev) |
427 | { | 505 | { |
428 | bool flush_wq = false; | 506 | bool flush_wq = false; |
@@ -470,6 +548,7 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
470 | rdev->pm.dynpm_can_downclock = true; | 548 | rdev->pm.dynpm_can_downclock = true; |
471 | rdev->pm.current_sclk = rdev->clock.default_sclk; | 549 | rdev->pm.current_sclk = rdev->clock.default_sclk; |
472 | rdev->pm.current_mclk = rdev->clock.default_mclk; | 550 | rdev->pm.current_mclk = rdev->clock.default_mclk; |
551 | rdev->pm.int_thermal_type = THERMAL_TYPE_NONE; | ||
473 | 552 | ||
474 | if (rdev->bios) { | 553 | if (rdev->bios) { |
475 | if (rdev->is_atom_bios) | 554 | if (rdev->is_atom_bios) |
@@ -480,6 +559,8 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
480 | radeon_pm_init_profile(rdev); | 559 | radeon_pm_init_profile(rdev); |
481 | } | 560 | } |
482 | 561 | ||
562 | /* set up the internal thermal sensor if applicable */ | ||
563 | radeon_hwmon_init(rdev); | ||
483 | if (rdev->pm.num_power_states > 1) { | 564 | if (rdev->pm.num_power_states > 1) { |
484 | /* where's the best place to put these? */ | 565 | /* where's the best place to put these? */ |
485 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); | 566 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); |
@@ -535,6 +616,7 @@ void radeon_pm_fini(struct radeon_device *rdev) | |||
535 | #endif | 616 | #endif |
536 | } | 617 | } |
537 | 618 | ||
619 | radeon_hwmon_fini(rdev); | ||
538 | if (rdev->pm.i2c_bus) | 620 | if (rdev->pm.i2c_bus) |
539 | radeon_i2c_destroy(rdev->pm.i2c_bus); | 621 | radeon_i2c_destroy(rdev->pm.i2c_bus); |
540 | } | 622 | } |