diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 768b1509fa03..cb8d9a1dd69c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <drm/drm_crtc_helper.h> | 30 | #include <drm/drm_crtc_helper.h> |
31 | #include <drm/radeon_drm.h> | 31 | #include <drm/radeon_drm.h> |
32 | #include <linux/vgaarb.h> | 32 | #include <linux/vgaarb.h> |
33 | #include <linux/vga_switcheroo.h> | ||
33 | #include "radeon_reg.h" | 34 | #include "radeon_reg.h" |
34 | #include "radeon.h" | 35 | #include "radeon.h" |
35 | #include "radeon_asic.h" | 36 | #include "radeon_asic.h" |
@@ -613,6 +614,36 @@ void radeon_check_arguments(struct radeon_device *rdev) | |||
613 | } | 614 | } |
614 | } | 615 | } |
615 | 616 | ||
617 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | ||
618 | { | ||
619 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
620 | struct radeon_device *rdev = dev->dev_private; | ||
621 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; | ||
622 | if (state == VGA_SWITCHEROO_ON) { | ||
623 | printk(KERN_INFO "radeon: switched on\n"); | ||
624 | /* don't suspend or resume card normally */ | ||
625 | rdev->powered_down = false; | ||
626 | radeon_resume_kms(dev); | ||
627 | } else { | ||
628 | printk(KERN_INFO "radeon: switched off\n"); | ||
629 | radeon_suspend_kms(dev, pmm); | ||
630 | /* don't suspend or resume card normally */ | ||
631 | rdev->powered_down = true; | ||
632 | } | ||
633 | } | ||
634 | |||
635 | static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) | ||
636 | { | ||
637 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
638 | bool can_switch; | ||
639 | |||
640 | spin_lock(&dev->count_lock); | ||
641 | can_switch = (dev->open_count == 0); | ||
642 | spin_unlock(&dev->count_lock); | ||
643 | return can_switch; | ||
644 | } | ||
645 | |||
646 | |||
616 | int radeon_device_init(struct radeon_device *rdev, | 647 | int radeon_device_init(struct radeon_device *rdev, |
617 | struct drm_device *ddev, | 648 | struct drm_device *ddev, |
618 | struct pci_dev *pdev, | 649 | struct pci_dev *pdev, |
@@ -692,6 +723,9 @@ int radeon_device_init(struct radeon_device *rdev, | |||
692 | /* this will fail for cards that aren't VGA class devices, just | 723 | /* this will fail for cards that aren't VGA class devices, just |
693 | * ignore it */ | 724 | * ignore it */ |
694 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); | 725 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); |
726 | vga_switcheroo_register_client(rdev->pdev, | ||
727 | radeon_switcheroo_set_state, | ||
728 | radeon_switcheroo_can_switch); | ||
695 | 729 | ||
696 | r = radeon_init(rdev); | 730 | r = radeon_init(rdev); |
697 | if (r) | 731 | if (r) |
@@ -723,6 +757,7 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
723 | rdev->shutdown = true; | 757 | rdev->shutdown = true; |
724 | radeon_fini(rdev); | 758 | radeon_fini(rdev); |
725 | destroy_workqueue(rdev->wq); | 759 | destroy_workqueue(rdev->wq); |
760 | vga_switcheroo_unregister_client(rdev->pdev); | ||
726 | vga_client_register(rdev->pdev, NULL, NULL, NULL); | 761 | vga_client_register(rdev->pdev, NULL, NULL, NULL); |
727 | iounmap(rdev->rmmio); | 762 | iounmap(rdev->rmmio); |
728 | rdev->rmmio = NULL; | 763 | rdev->rmmio = NULL; |
@@ -746,6 +781,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
746 | } | 781 | } |
747 | rdev = dev->dev_private; | 782 | rdev = dev->dev_private; |
748 | 783 | ||
784 | if (rdev->powered_down) | ||
785 | return 0; | ||
749 | /* unpin the front buffers */ | 786 | /* unpin the front buffers */ |
750 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 787 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
751 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); | 788 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); |
@@ -791,6 +828,9 @@ int radeon_resume_kms(struct drm_device *dev) | |||
791 | { | 828 | { |
792 | struct radeon_device *rdev = dev->dev_private; | 829 | struct radeon_device *rdev = dev->dev_private; |
793 | 830 | ||
831 | if (rdev->powered_down) | ||
832 | return 0; | ||
833 | |||
794 | acquire_console_sem(); | 834 | acquire_console_sem(); |
795 | pci_set_power_state(dev->pdev, PCI_D0); | 835 | pci_set_power_state(dev->pdev, PCI_D0); |
796 | pci_restore_state(dev->pdev); | 836 | pci_restore_state(dev->pdev); |