diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-01 16:22:38 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-01 16:22:38 +1000 |
commit | 1c62233508ef7104f8a78e571fdf5c72d0dc0200 (patch) | |
tree | 31e19cbff5c1080d3015d20b24dd43ee95f4ed8c /drivers/gpu/drm/i915/i915_dma.c | |
parent | 6d9c13513661c1991bf5f4e6e1363c721292d819 (diff) | |
parent | 6a9ee8af344e3bd7dbd61e67037096cdf7f83289 (diff) |
Merge branch 'gpu-switcher' of /ssd/git//linux-2.6 into drm-next-stage
* 'gpu-switcher' of /ssd/git//linux-2.6:
vga_switcheroo: initial implementation (v15)
fb: for framebuffer handover don't exit the loop early.
Conflicts:
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/radeon.h
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3e658d6a6b7..8bfc0bbf13e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -37,6 +37,7 @@ #include <linux/vgaarb.h> #include <linux/acpi.h> #include <linux/pnp.h> +#include <linux/vga_switcheroo.h> /* Really want an OS-independent resettable timer. Would like to have * this loop run for (eg) 3 sec, but have the timer reset every time @@ -1381,6 +1382,32 @@ static unsigned int i915_vga_set_decode(void *cookie, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } +static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; + if (state == VGA_SWITCHEROO_ON) { + printk(KERN_INFO "i915: switched off\n"); + /* i915 resume handler doesn't set to D0 */ + pci_set_power_state(dev->pdev, PCI_D0); + i915_resume(dev); + } else { + printk(KERN_ERR "i915: switched off\n"); + i915_suspend(dev, pmm); + } +} + +static bool i915_switcheroo_can_switch(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + bool can_switch; + + spin_lock(&dev->count_lock); + can_switch = (dev->open_count == 0); + spin_unlock(&dev->count_lock); + return can_switch; +} + static int i915_load_modeset_init(struct drm_device *dev, unsigned long prealloc_start, unsigned long prealloc_size, @@ -1442,6 +1469,12 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + ret = vga_switcheroo_register_client(dev->pdev, + i915_switcheroo_set_state, + i915_switcheroo_can_switch); + if (ret) + goto destroy_ringbuffer; + intel_modeset_init(dev); ret = drm_irq_install(dev); @@ -1733,6 +1766,7 @@ int i915_driver_unload(struct drm_device *dev) dev_priv->child_dev_num = 0; } drm_irq_uninstall(dev); + vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); } @@ -1802,6 +1836,7 @@ void i915_driver_lastclose(struct drm_device * dev) if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { drm_fb_helper_restore(); + vga_switcheroo_process_delayed_switch(); return; } |