]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/nouveau/nouveau_vga.c
Merge remote-tracking branch 'regulator/fix/max77802' into regulator-linus
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / nouveau / nouveau_vga.c
CommitLineData
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 6
4dc28134 7#include "nouveau_drv.h"
77145f1c
BS
8#include "nouveau_acpi.h"
9#include "nouveau_fbcon.h"
5b8a43ae 10#include "nouveau_vga.h"
77145f1c
BS
11
12static unsigned int
13nouveau_vga_set_decode(void *priv, bool state)
14{
a01ca78c 15 struct nouveau_drm *drm = nouveau_drm(priv);
1167c6bc 16 struct nvif_object *device = &drm->client.device.object;
77145f1c 17
1167c6bc
BS
18 if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE &&
19 drm->client.device.info.chipset >= 0x4c)
db2bec18 20 nvif_wr32(device, 0x088060, state);
77145f1c 21 else
1167c6bc 22 if (drm->client.device.info.chipset >= 0x40)
db2bec18
BS
23 nvif_wr32(device, 0x088054, state);
24 else
25 nvif_wr32(device, 0x001854, state);
77145f1c
BS
26
27 if (state)
28 return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
29 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
30 else
31 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
32}
33
34static void
35nouveau_switcheroo_set_state(struct pci_dev *pdev,
36 enum vga_switcheroo_state state)
37{
38 struct drm_device *dev = pci_get_drvdata(pdev);
77145f1c 39
5addcf0a
DA
40 if ((nouveau_is_optimus() || nouveau_is_v1_dsm()) && state == VGA_SWITCHEROO_OFF)
41 return;
42
77145f1c 43 if (state == VGA_SWITCHEROO_ON) {
8dfe162a 44 pr_err("VGA switcheroo: switched nouveau on\n");
77145f1c 45 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
2d8b9ccb 46 nouveau_pmops_resume(&pdev->dev);
77145f1c
BS
47 drm_kms_helper_poll_enable(dev);
48 dev->switch_power_state = DRM_SWITCH_POWER_ON;
49 } else {
8dfe162a 50 pr_err("VGA switcheroo: switched nouveau off\n");
77145f1c
BS
51 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
52 drm_kms_helper_poll_disable(dev);
53 nouveau_switcheroo_optimus_dsm();
2d8b9ccb 54 nouveau_pmops_suspend(&pdev->dev);
77145f1c
BS
55 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
56 }
57}
58
59static void
60nouveau_switcheroo_reprobe(struct pci_dev *pdev)
61{
62 struct drm_device *dev = pci_get_drvdata(pdev);
63 nouveau_fbcon_output_poll_changed(dev);
64}
65
66static bool
67nouveau_switcheroo_can_switch(struct pci_dev *pdev)
68{
69 struct drm_device *dev = pci_get_drvdata(pdev);
77145f1c 70
fc8fd40e
DV
71 /*
72 * FIXME: open_count is protected by drm_global_mutex but that would lead to
73 * locking inversion with the driver load path. And the access here is
74 * completely racy anyway. So don't bother with locking for now.
75 */
76 return dev->open_count == 0;
77145f1c
BS
77}
78
79static const struct vga_switcheroo_client_ops
80nouveau_switcheroo_ops = {
81 .set_gpu_state = nouveau_switcheroo_set_state,
82 .reprobe = nouveau_switcheroo_reprobe,
83 .can_switch = nouveau_switcheroo_can_switch,
84};
85
86void
87nouveau_vga_init(struct nouveau_drm *drm)
88{
89 struct drm_device *dev = drm->dev;
321f5c5f 90 bool runtime = nouveau_pmops_runtime();
420b9469
AC
91
92 /* only relevant for PCI devices */
93 if (!dev->pdev)
94 return;
95
77145f1c 96 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
5addcf0a 97
1d3c1103
LW
98 /* don't register Thunderbolt eGPU with vga_switcheroo */
99 if (pci_is_thunderbolt_attached(dev->pdev))
100 return;
101
5addcf0a
DA
102 vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);
103
104 if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
105 vga_switcheroo_init_domain_pm_ops(drm->dev->dev, &drm->vga_pm_domain);
77145f1c
BS
106}
107
108void
109nouveau_vga_fini(struct nouveau_drm *drm)
110{
111 struct drm_device *dev = drm->dev;
321f5c5f 112 bool runtime = nouveau_pmops_runtime();
53beaa01 113
1d3c1103
LW
114 vga_client_register(dev->pdev, NULL, NULL, NULL);
115
116 if (pci_is_thunderbolt_attached(dev->pdev))
117 return;
118
77145f1c 119 vga_switcheroo_unregister_client(dev->pdev);
53beaa01
AD
120 if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
121 vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
77145f1c
BS
122}
123
124
125void
126nouveau_vga_lastclose(struct drm_device *dev)
127{
128 vga_switcheroo_process_delayed_switch();
129}