From: Dave Airlie <airlied@xxxxxxxxxx> This adds the start of dynamic power off support to radeon, it probably turns off way to many GPUs but is an initial implementation I've tested on an gm45/rv635 combination laptop. Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> --- drivers/gpu/drm/radeon/radeon.h | 3 +++ drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/gpu/drm/radeon/radeon_drv.c | 6 ++++++ drivers/gpu/drm/radeon/radeon_pm.c | 37 +++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 59a1531..0abad51 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1839,6 +1839,9 @@ extern int radeon_acpi_init(struct radeon_device *rdev); static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } #endif +extern bool radeon_dynamic_power_check(struct drm_device *dev); +extern int radeon_dynamic_power_set_state(struct drm_device *dev, int state); + #include "radeon_object.h" #endif diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 857cf5b..c58849c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1093,7 +1093,7 @@ int radeon_device_init(struct radeon_device *rdev, /* this will fail for cards that aren't VGA class devices, just * ignore it */ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, false); + vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, true); r = radeon_init(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8c593ea..b0a7211 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -118,6 +118,9 @@ struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, struct drm_gem_object *radeon_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); +bool radeon_dynamic_power_check(struct drm_device *dev); +int radeon_dynamic_power_set_state(struct drm_device *dev, int state); + #if defined(CONFIG_DEBUG_FS) int radeon_debugfs_init(struct drm_minor *minor); void radeon_debugfs_cleanup(struct drm_minor *minor); @@ -385,6 +388,9 @@ static struct drm_driver kms_driver = { .gem_prime_export = radeon_gem_prime_export, .gem_prime_import = radeon_gem_prime_import, + .dynamic_off_check = radeon_dynamic_power_check, + .dynamic_set_state = radeon_dynamic_power_set_state, + .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 7ae6066..2763ff1 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -30,7 +30,7 @@ #include <linux/power_supply.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> - +#include <linux/vga_switcheroo.h> #define RADEON_IDLE_LOOP_MS 100 #define RADEON_RECLOCK_DELAY_MS 200 #define RADEON_WAIT_VBLANK_TIMEOUT 200 @@ -643,6 +643,8 @@ int radeon_pm_init(struct radeon_device *rdev) DRM_INFO("radeon: power management initialized\n"); } + drm_dynamic_power_init(rdev->ddev); + return 0; } @@ -877,3 +879,36 @@ static int radeon_debugfs_pm_init(struct radeon_device *rdev) return 0; #endif } + +bool radeon_dynamic_power_check(struct drm_device *dev) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->enabled) { + DRM_DEBUG_DRIVER("failing to power off - crtc active\n"); + return false; + } + } + return true; +} + +int radeon_dynamic_power_set_state(struct drm_device *dev, int state) +{ + pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; + + if (state == DRM_SWITCH_POWER_DYNAMIC_OFF) { + dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; + vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_OFF, false); + drm_kms_helper_poll_disable(dev); + radeon_suspend_kms(dev, pmm); + vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_OFF, true); + } else { + vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_ON, true); + radeon_resume_kms(dev); + vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_ON, false); + drm_kms_helper_poll_enable(dev); + dev->switch_power_state = DRM_SWITCH_POWER_ON; + } + return 0; +} -- 1.7.12 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel