Commit | Line | Data |
---|---|---|
77145f1c BS |
1 | #include <linux/vgaarb.h> |
2 | #include <linux/vga_switcheroo.h> | |
3 | ||
612a9aab LT |
4 | #include <drm/drmP.h> |
5 | #include <drm/drm_crtc_helper.h> | |
77145f1c BS |
6 | |
7 | #include "nouveau_drm.h" | |
8 | #include "nouveau_acpi.h" | |
9 | #include "nouveau_fbcon.h" | |
5b8a43ae | 10 | #include "nouveau_vga.h" |
77145f1c BS |
11 | |
12 | static unsigned int | |
13 | nouveau_vga_set_decode(void *priv, bool state) | |
14 | { | |
15 | struct nouveau_device *device = nouveau_dev(priv); | |
16 | ||
b71313e1 IM |
17 | if (device->card_type == NV_40 && device->chipset >= 0x4c) |
18 | nv_wr32(device, 0x088060, state); | |
19 | else if (device->chipset >= 0x40) | |
77145f1c BS |
20 | nv_wr32(device, 0x088054, state); |
21 | else | |
22 | nv_wr32(device, 0x001854, state); | |
23 | ||
24 | if (state) | |
25 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | |
26 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | |
27 | else | |
28 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | |
29 | } | |
30 | ||
31 | static void | |
32 | nouveau_switcheroo_set_state(struct pci_dev *pdev, | |
33 | enum vga_switcheroo_state state) | |
34 | { | |
35 | struct drm_device *dev = pci_get_drvdata(pdev); | |
77145f1c | 36 | |
5addcf0a DA |
37 | if ((nouveau_is_optimus() || nouveau_is_v1_dsm()) && state == VGA_SWITCHEROO_OFF) |
38 | return; | |
39 | ||
77145f1c BS |
40 | if (state == VGA_SWITCHEROO_ON) { |
41 | printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); | |
42 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | |
2d8b9ccb | 43 | nouveau_pmops_resume(&pdev->dev); |
77145f1c BS |
44 | drm_kms_helper_poll_enable(dev); |
45 | dev->switch_power_state = DRM_SWITCH_POWER_ON; | |
46 | } else { | |
47 | printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); | |
48 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | |
49 | drm_kms_helper_poll_disable(dev); | |
50 | nouveau_switcheroo_optimus_dsm(); | |
2d8b9ccb | 51 | nouveau_pmops_suspend(&pdev->dev); |
77145f1c BS |
52 | dev->switch_power_state = DRM_SWITCH_POWER_OFF; |
53 | } | |
54 | } | |
55 | ||
56 | static void | |
57 | nouveau_switcheroo_reprobe(struct pci_dev *pdev) | |
58 | { | |
59 | struct drm_device *dev = pci_get_drvdata(pdev); | |
60 | nouveau_fbcon_output_poll_changed(dev); | |
61 | } | |
62 | ||
63 | static bool | |
64 | nouveau_switcheroo_can_switch(struct pci_dev *pdev) | |
65 | { | |
66 | struct drm_device *dev = pci_get_drvdata(pdev); | |
67 | bool can_switch; | |
68 | ||
69 | spin_lock(&dev->count_lock); | |
70 | can_switch = (dev->open_count == 0); | |
71 | spin_unlock(&dev->count_lock); | |
72 | return can_switch; | |
73 | } | |
74 | ||
75 | static const struct vga_switcheroo_client_ops | |
76 | nouveau_switcheroo_ops = { | |
77 | .set_gpu_state = nouveau_switcheroo_set_state, | |
78 | .reprobe = nouveau_switcheroo_reprobe, | |
79 | .can_switch = nouveau_switcheroo_can_switch, | |
80 | }; | |
81 | ||
82 | void | |
83 | nouveau_vga_init(struct nouveau_drm *drm) | |
84 | { | |
85 | struct drm_device *dev = drm->dev; | |
5addcf0a | 86 | bool runtime = false; |
77145f1c | 87 | vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); |
5addcf0a DA |
88 | |
89 | if (nouveau_runtime_pm == 1) | |
90 | runtime = true; | |
91 | if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) | |
92 | runtime = true; | |
93 | vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime); | |
94 | ||
95 | if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) | |
96 | vga_switcheroo_init_domain_pm_ops(drm->dev->dev, &drm->vga_pm_domain); | |
77145f1c BS |
97 | } |
98 | ||
99 | void | |
100 | nouveau_vga_fini(struct nouveau_drm *drm) | |
101 | { | |
102 | struct drm_device *dev = drm->dev; | |
103 | vga_switcheroo_unregister_client(dev->pdev); | |
104 | vga_client_register(dev->pdev, NULL, NULL, NULL); | |
105 | } | |
106 | ||
107 | ||
108 | void | |
109 | nouveau_vga_lastclose(struct drm_device *dev) | |
110 | { | |
111 | vga_switcheroo_process_delayed_switch(); | |
112 | } |