diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1db1ef30be2b..dedd121d8fe7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx"; | |||
| 147 | 147 | ||
| 148 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); | 148 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); |
| 149 | static void vmw_master_init(struct vmw_master *); | 149 | static void vmw_master_init(struct vmw_master *); |
| 150 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | ||
| 151 | void *ptr); | ||
| 150 | 152 | ||
| 151 | static void vmw_print_capabilities(uint32_t capabilities) | 153 | static void vmw_print_capabilities(uint32_t capabilities) |
| 152 | { | 154 | { |
| @@ -217,6 +219,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 217 | 219 | ||
| 218 | dev_priv->dev = dev; | 220 | dev_priv->dev = dev; |
| 219 | dev_priv->vmw_chipset = chipset; | 221 | dev_priv->vmw_chipset = chipset; |
| 222 | dev_priv->last_read_sequence = (uint32_t) -100; | ||
| 220 | mutex_init(&dev_priv->hw_mutex); | 223 | mutex_init(&dev_priv->hw_mutex); |
| 221 | mutex_init(&dev_priv->cmdbuf_mutex); | 224 | mutex_init(&dev_priv->cmdbuf_mutex); |
| 222 | rwlock_init(&dev_priv->resource_lock); | 225 | rwlock_init(&dev_priv->resource_lock); |
| @@ -351,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 351 | vmw_fb_init(dev_priv); | 354 | vmw_fb_init(dev_priv); |
| 352 | } | 355 | } |
| 353 | 356 | ||
| 357 | dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; | ||
| 358 | register_pm_notifier(&dev_priv->pm_nb); | ||
| 359 | |||
| 354 | return 0; | 360 | return 0; |
| 355 | 361 | ||
| 356 | out_no_device: | 362 | out_no_device: |
| @@ -385,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev) | |||
| 385 | 391 | ||
| 386 | DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); | 392 | DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); |
| 387 | 393 | ||
| 394 | unregister_pm_notifier(&dev_priv->pm_nb); | ||
| 395 | |||
| 388 | if (!dev_priv->stealth) { | 396 | if (!dev_priv->stealth) { |
| 389 | vmw_fb_close(dev_priv); | 397 | vmw_fb_close(dev_priv); |
| 390 | vmw_kms_close(dev_priv); | 398 | vmw_kms_close(dev_priv); |
| @@ -650,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev) | |||
| 650 | drm_put_dev(dev); | 658 | drm_put_dev(dev); |
| 651 | } | 659 | } |
| 652 | 660 | ||
| 661 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | ||
| 662 | void *ptr) | ||
| 663 | { | ||
| 664 | struct vmw_private *dev_priv = | ||
| 665 | container_of(nb, struct vmw_private, pm_nb); | ||
| 666 | struct vmw_master *vmaster = dev_priv->active_master; | ||
| 667 | |||
| 668 | switch (val) { | ||
| 669 | case PM_HIBERNATION_PREPARE: | ||
| 670 | case PM_SUSPEND_PREPARE: | ||
| 671 | ttm_suspend_lock(&vmaster->lock); | ||
| 672 | |||
| 673 | /** | ||
| 674 | * This empties VRAM and unbinds all GMR bindings. | ||
| 675 | * Buffer contents is moved to swappable memory. | ||
| 676 | */ | ||
| 677 | ttm_bo_swapout_all(&dev_priv->bdev); | ||
| 678 | break; | ||
| 679 | case PM_POST_HIBERNATION: | ||
| 680 | case PM_POST_SUSPEND: | ||
| 681 | ttm_suspend_unlock(&vmaster->lock); | ||
| 682 | break; | ||
| 683 | case PM_RESTORE_PREPARE: | ||
| 684 | break; | ||
| 685 | case PM_POST_RESTORE: | ||
| 686 | break; | ||
| 687 | default: | ||
| 688 | break; | ||
| 689 | } | ||
| 690 | return 0; | ||
| 691 | } | ||
| 692 | |||
| 693 | /** | ||
| 694 | * These might not be needed with the virtual SVGA device. | ||
| 695 | */ | ||
| 696 | |||
| 697 | int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 698 | { | ||
| 699 | pci_save_state(pdev); | ||
| 700 | pci_disable_device(pdev); | ||
| 701 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 702 | return 0; | ||
| 703 | } | ||
| 704 | |||
| 705 | int vmw_pci_resume(struct pci_dev *pdev) | ||
| 706 | { | ||
| 707 | pci_set_power_state(pdev, PCI_D0); | ||
| 708 | pci_restore_state(pdev); | ||
| 709 | return pci_enable_device(pdev); | ||
| 710 | } | ||
| 711 | |||
| 653 | static struct drm_driver driver = { | 712 | static struct drm_driver driver = { |
| 654 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 713 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
| 655 | DRIVER_MODESET, | 714 | DRIVER_MODESET, |
| @@ -689,7 +748,9 @@ static struct drm_driver driver = { | |||
| 689 | .name = VMWGFX_DRIVER_NAME, | 748 | .name = VMWGFX_DRIVER_NAME, |
| 690 | .id_table = vmw_pci_id_list, | 749 | .id_table = vmw_pci_id_list, |
| 691 | .probe = vmw_probe, | 750 | .probe = vmw_probe, |
| 692 | .remove = vmw_remove | 751 | .remove = vmw_remove, |
| 752 | .suspend = vmw_pci_suspend, | ||
| 753 | .resume = vmw_pci_resume | ||
| 693 | }, | 754 | }, |
| 694 | .name = VMWGFX_DRIVER_NAME, | 755 | .name = VMWGFX_DRIVER_NAME, |
| 695 | .desc = VMWGFX_DRIVER_DESC, | 756 | .desc = VMWGFX_DRIVER_DESC, |
