diff options
25 files changed, 1103 insertions, 71 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3e658d6a6b7d..8bfc0bbf13e6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/vgaarb.h> | 37 | #include <linux/vgaarb.h> |
| 38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
| 39 | #include <linux/pnp.h> | 39 | #include <linux/pnp.h> |
| 40 | #include <linux/vga_switcheroo.h> | ||
| 40 | 41 | ||
| 41 | /* Really want an OS-independent resettable timer. Would like to have | 42 | /* Really want an OS-independent resettable timer. Would like to have |
| 42 | * this loop run for (eg) 3 sec, but have the timer reset every time | 43 | * 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) | |||
| 1381 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | 1382 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |
| 1382 | } | 1383 | } |
| 1383 | 1384 | ||
| 1385 | static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | ||
| 1386 | { | ||
| 1387 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
| 1388 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; | ||
| 1389 | if (state == VGA_SWITCHEROO_ON) { | ||
| 1390 | printk(KERN_INFO "i915: switched off\n"); | ||
| 1391 | /* i915 resume handler doesn't set to D0 */ | ||
| 1392 | pci_set_power_state(dev->pdev, PCI_D0); | ||
| 1393 | i915_resume(dev); | ||
| 1394 | } else { | ||
| 1395 | printk(KERN_ERR "i915: switched off\n"); | ||
| 1396 | i915_suspend(dev, pmm); | ||
| 1397 | } | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | static bool i915_switcheroo_can_switch(struct pci_dev *pdev) | ||
| 1401 | { | ||
| 1402 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
| 1403 | bool can_switch; | ||
| 1404 | |||
| 1405 | spin_lock(&dev->count_lock); | ||
| 1406 | can_switch = (dev->open_count == 0); | ||
| 1407 | spin_unlock(&dev->count_lock); | ||
| 1408 | return can_switch; | ||
| 1409 | } | ||
| 1410 | |||
| 1384 | static int i915_load_modeset_init(struct drm_device *dev, | 1411 | static int i915_load_modeset_init(struct drm_device *dev, |
| 1385 | unsigned long prealloc_start, | 1412 | unsigned long prealloc_start, |
| 1386 | unsigned long prealloc_size, | 1413 | unsigned long prealloc_size, |
| @@ -1442,6 +1469,12 @@ static int i915_load_modeset_init(struct drm_device *dev, | |||
| 1442 | if (ret) | 1469 | if (ret) |
| 1443 | goto destroy_ringbuffer; | 1470 | goto destroy_ringbuffer; |
| 1444 | 1471 | ||
| 1472 | ret = vga_switcheroo_register_client(dev->pdev, | ||
| 1473 | i915_switcheroo_set_state, | ||
| 1474 | i915_switcheroo_can_switch); | ||
| 1475 | if (ret) | ||
| 1476 | goto destroy_ringbuffer; | ||
| 1477 | |||
| 1445 | intel_modeset_init(dev); | 1478 | intel_modeset_init(dev); |
| 1446 | 1479 | ||
| 1447 | ret = drm_irq_install(dev); | 1480 | ret = drm_irq_install(dev); |
| @@ -1733,6 +1766,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1733 | dev_priv->child_dev_num = 0; | 1766 | dev_priv->child_dev_num = 0; |
| 1734 | } | 1767 | } |
| 1735 | drm_irq_uninstall(dev); | 1768 | drm_irq_uninstall(dev); |
| 1769 | vga_switcheroo_unregister_client(dev->pdev); | ||
| 1736 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 1770 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
| 1737 | } | 1771 | } |
| 1738 | 1772 | ||
| @@ -1802,6 +1836,7 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
| 1802 | 1836 | ||
| 1803 | if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { | 1837 | if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1804 | drm_fb_helper_restore(); | 1838 | drm_fb_helper_restore(); |
| 1839 | vga_switcheroo_process_delayed_switch(); | ||
| 1805 | return; | 1840 | return; |
| 1806 | } | 1841 | } |
| 1807 | 1842 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 85ad020125c8..1b2e95455c05 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -214,7 +214,7 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
| 214 | return 0; | 214 | return 0; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static int i915_suspend(struct drm_device *dev, pm_message_t state) | 217 | int i915_suspend(struct drm_device *dev, pm_message_t state) |
| 218 | { | 218 | { |
| 219 | int error; | 219 | int error; |
| 220 | 220 | ||
| @@ -268,7 +268,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
| 268 | return error; | 268 | return error; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | static int i915_resume(struct drm_device *dev) | 271 | int i915_resume(struct drm_device *dev) |
| 272 | { | 272 | { |
| 273 | if (pci_enable_device(dev->pdev)) | 273 | if (pci_enable_device(dev->pdev)) |
| 274 | return -EIO; | 274 | return -EIO; |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f97592609da4..979439cfb827 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -773,6 +773,8 @@ extern unsigned int i915_fbpercrtc; | |||
| 773 | extern unsigned int i915_powersave; | 773 | extern unsigned int i915_powersave; |
| 774 | extern unsigned int i915_lvds_downclock; | 774 | extern unsigned int i915_lvds_downclock; |
| 775 | 775 | ||
| 776 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); | ||
| 777 | extern int i915_resume(struct drm_device *dev); | ||
| 776 | extern void i915_save_display(struct drm_device *dev); | 778 | extern void i915_save_display(struct drm_device *dev); |
| 777 | extern void i915_restore_display(struct drm_device *dev); | 779 | extern void i915_restore_display(struct drm_device *dev); |
| 778 | extern int i915_master_create(struct drm_device *dev, struct drm_master *master); | 780 | extern int i915_master_create(struct drm_device *dev, struct drm_master *master); |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index aaabbcbe5905..8cd791dc5b29 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
| 36 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/vga_switcheroo.h> | ||
| 38 | 39 | ||
| 39 | #include "drmP.h" | 40 | #include "drmP.h" |
| 40 | #include "drm.h" | 41 | #include "drm.h" |
| @@ -235,6 +236,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 235 | obj_priv->gtt_offset, fbo); | 236 | obj_priv->gtt_offset, fbo); |
| 236 | 237 | ||
| 237 | mutex_unlock(&dev->struct_mutex); | 238 | mutex_unlock(&dev->struct_mutex); |
| 239 | vga_switcheroo_client_fb_set(dev->pdev, info); | ||
| 238 | return 0; | 240 | return 0; |
| 239 | 241 | ||
| 240 | out_unpin: | 242 | out_unpin: |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 48227e744753..0e0730a53137 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include "nouveau_drm.h" | 11 | #include "nouveau_drm.h" |
| 12 | #include "nv50_display.h" | 12 | #include "nv50_display.h" |
| 13 | 13 | ||
| 14 | #include <linux/vga_switcheroo.h> | ||
| 15 | |||
