1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- #include <linux/vgaarb.h>
- #include <linux/vga_switcheroo.h>
- #include <drm/drmP.h>
- #include <drm/drm_crtc_helper.h>
- #include "nouveau_drm.h"
- #include "nouveau_acpi.h"
- #include "nouveau_fbcon.h"
- #include "nouveau_vga.h"
- static unsigned int
- nouveau_vga_set_decode(void *priv, bool state)
- {
- struct nouveau_device *device = nouveau_dev(priv);
- if (device->chipset >= 0x40)
- nv_wr32(device, 0x088054, state);
- else
- nv_wr32(device, 0x001854, state);
- if (state)
- return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
- VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
- else
- return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
- }
- static void
- nouveau_switcheroo_set_state(struct pci_dev *pdev,
- enum vga_switcheroo_state state)
- {
- struct drm_device *dev = pci_get_drvdata(pdev);
- if (state == VGA_SWITCHEROO_ON) {
- printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
- dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- nouveau_pmops_resume(&pdev->dev);
- drm_kms_helper_poll_enable(dev);
- dev->switch_power_state = DRM_SWITCH_POWER_ON;
- } else {
- printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
- dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- drm_kms_helper_poll_disable(dev);
- nouveau_switcheroo_optimus_dsm();
- nouveau_pmops_suspend(&pdev->dev);
- dev->switch_power_state = DRM_SWITCH_POWER_OFF;
- }
- }
- static void
- nouveau_switcheroo_reprobe(struct pci_dev *pdev)
- {
- struct drm_device *dev = pci_get_drvdata(pdev);
- nouveau_fbcon_output_poll_changed(dev);
- }
- static bool
- nouveau_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 const struct vga_switcheroo_client_ops
- nouveau_switcheroo_ops = {
- .set_gpu_state = nouveau_switcheroo_set_state,
- .reprobe = nouveau_switcheroo_reprobe,
- .can_switch = nouveau_switcheroo_can_switch,
- };
- void
- nouveau_vga_init(struct nouveau_drm *drm)
- {
- struct drm_device *dev = drm->dev;
- vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
- vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops);
- }
- void
- nouveau_vga_fini(struct nouveau_drm *drm)
- {
- struct drm_device *dev = drm->dev;
- vga_switcheroo_unregister_client(dev->pdev);
- vga_client_register(dev->pdev, NULL, NULL, NULL);
- }
- void
- nouveau_vga_lastclose(struct drm_device *dev)
- {
- vga_switcheroo_process_delayed_switch();
- }
|