xref: /linux/drivers/gpu/drm/nouveau/nouveau_vga.c (revision ffe315012510165ce82e4dd4767f0a5dba9edbf7)
1 #include <linux/vgaarb.h>
2 #include <linux/vga_switcheroo.h>
3 
4 #include <drm/drmP.h>
5 #include <drm/drm_crtc_helper.h>
6 
7 #include "nouveau_drm.h"
8 #include "nouveau_acpi.h"
9 #include "nouveau_fbcon.h"
10 #include "nouveau_vga.h"
11 
12 static unsigned int
13 nouveau_vga_set_decode(void *priv, bool state)
14 {
15 	struct nouveau_device *device = nouveau_dev(priv);
16 
17 	if (device->chipset >= 0x40)
18 		nv_wr32(device, 0x088054, state);
19 	else
20 		nv_wr32(device, 0x001854, state);
21 
22 	if (state)
23 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
24 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
25 	else
26 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
27 }
28 
29 static void
30 nouveau_switcheroo_set_state(struct pci_dev *pdev,
31 			     enum vga_switcheroo_state state)
32 {
33 	struct drm_device *dev = pci_get_drvdata(pdev);
34 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
35 
36 	if (state == VGA_SWITCHEROO_ON) {
37 		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
38 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
39 		nouveau_drm_resume(pdev);
40 		drm_kms_helper_poll_enable(dev);
41 		dev->switch_power_state = DRM_SWITCH_POWER_ON;
42 	} else {
43 		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
44 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
45 		drm_kms_helper_poll_disable(dev);
46 		nouveau_switcheroo_optimus_dsm();
47 		nouveau_drm_suspend(pdev, pmm);
48 		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
49 	}
50 }
51 
52 static void
53 nouveau_switcheroo_reprobe(struct pci_dev *pdev)
54 {
55 	struct drm_device *dev = pci_get_drvdata(pdev);
56 	nouveau_fbcon_output_poll_changed(dev);
57 }
58 
59 static bool
60 nouveau_switcheroo_can_switch(struct pci_dev *pdev)
61 {
62 	struct drm_device *dev = pci_get_drvdata(pdev);
63 	bool can_switch;
64 
65 	spin_lock(&dev->count_lock);
66 	can_switch = (dev->open_count == 0);
67 	spin_unlock(&dev->count_lock);
68 	return can_switch;
69 }
70 
71 static const struct vga_switcheroo_client_ops
72 nouveau_switcheroo_ops = {
73 	.set_gpu_state = nouveau_switcheroo_set_state,
74 	.reprobe = nouveau_switcheroo_reprobe,
75 	.can_switch = nouveau_switcheroo_can_switch,
76 };
77 
78 void
79 nouveau_vga_init(struct nouveau_drm *drm)
80 {
81 	struct drm_device *dev = drm->dev;
82 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
83 	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops);
84 }
85 
86 void
87 nouveau_vga_fini(struct nouveau_drm *drm)
88 {
89 	struct drm_device *dev = drm->dev;
90 	vga_switcheroo_unregister_client(dev->pdev);
91 	vga_client_register(dev->pdev, NULL, NULL, NULL);
92 }
93 
94 
95 void
96 nouveau_vga_lastclose(struct drm_device *dev)
97 {
98 	vga_switcheroo_process_delayed_switch();
99 }
100