aboutsummarylogtreecommitdiffstats
path: root/i915-vga-arbiter.patch
blob: a1050ce00cec8513b00a18d17dd24e7978eada27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
From c3466f73ee88a129b5955d4f2049e79688183e96 Mon Sep 17 00:00:00 2001
From: Mark Weiman <mark.weiman@markzz.com>
Date: Thu, 22 Jun 2017 21:27:07 -0400
Subject: [PATCH] i915: Add module option to support VGA arbiter on HD devices

---
 drivers/gpu/drm/i915/i915_drv.c      | 22 +++++++++++++++++++---
 drivers/gpu/drm/i915/i915_params.c   |  5 +++++
 drivers/gpu/drm/i915/i915_params.h   |  1 +
 drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 5 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index edacd31ae1a1..c45b8c6e5883 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -573,10 +573,20 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
 	 * then we do not take part in VGA arbitration and the
 	 * vga_client_register() fails with -ENODEV.
+ 	 *
+ 	 * NB. The set_decode callback here actually works on GMCH
+	 * devices, on newer HD devices we can only disable VGA MMIO space.
+	 * Disabling VGA I/O space requires disabling I/O in the PCI command
+	 * register.  Nonetheless, we like to pretend that we participate in
+	 * VGA arbitration and can dynamically disable VGA I/O space because
+	 * this makes X happy, even though it's a complete lie.
 	 */
-	ret = vga_client_register(pdev, dev_priv, NULL, i915_vga_set_decode);
-	if (ret && ret != -ENODEV)
-		goto out;
+	if (!i915.enable_hd_vgaarb || !HAS_PCH_SPLIT(dev_priv)) {
+		ret = vga_client_register(pdev, dev, NULL,
+					  i915_vga_set_decode);
+		if (ret && ret != -ENODEV)
+			goto out;
+	}
 
 	intel_register_dsm_handler();
 
@@ -619,6 +629,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	if (ret)
 		goto cleanup_gem;
 
+	/*
+	 * Must do this after fbcon init so that
+	 * vgacon_save_screen() works during the handover.
+	 */
+	i915_disable_vga_mem(dev_priv);
+
 	/* Only enable hotplug handling once the fbdev is fully set up. */
 	intel_hpd_init(dev_priv);
 
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 0e280fbd52f1..f47675d24bf8 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -51,6 +51,7 @@ struct i915_params i915 __read_mostly = {
 	.invert_brightness = 0,
 	.disable_display = 0,
 	.enable_cmd_parser = true,
+	.enable_hd_vgaarb = false,
 	.use_mmio_flip = 0,
 	.mmio_debug = 0,
 	.verbose_state_checks = 1,
@@ -192,6 +193,10 @@ module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, bool, 0400)
 MODULE_PARM_DESC(enable_cmd_parser,
 		 "Enable command parsing (true=enabled [default], false=disabled)");
 
+module_param_named(enable_hd_vgaarb, i915.enable_hd_vgaarb, bool, 0444);
+MODULE_PARM_DESC(enable_hd_vgaarb,
+	"Enable support for VGA arbitration on Intel HD IGD. (default: false)");
+
 module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600);
 MODULE_PARM_DESC(use_mmio_flip,
 		 "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 8e433de04679..e3c294cdfebf 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -61,6 +61,7 @@ struct i915_params {
 	bool reset;
 	bool error_capture;
 	bool disable_display;
+	bool enable_hd_vgaarb;
 	bool verbose_state_checks;
 	bool nuclear_pageflip;
 	bool enable_dp_mst;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5370dbec7a7d..f25eb8eea591 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -16525,6 +16525,37 @@ static void i915_disable_vga(struct drm_i915_private *dev_priv)
 	POSTING_READ(vga_reg);
 }
 
+static void i915_enable_vga_mem(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+
+	/* Enable VGA memory on Intel HD */
+	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev_priv)) {
+		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
+		outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE);
+		vga_set_legacy_decoding(pdev, VGA_RSRC_LEGACY_IO |
+						   VGA_RSRC_LEGACY_MEM |
+						   VGA_RSRC_NORMAL_IO |
+						   VGA_RSRC_NORMAL_MEM);
+		vga_put(pdev, VGA_RSRC_LEGACY_IO);
+	}
+}
+
+void i915_disable_vga_mem(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+
+	/* Disable VGA memory on Intel HD */
+	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev_priv)) {
+		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
+		outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
+		vga_set_legacy_decoding(pdev, VGA_RSRC_LEGACY_IO |
+						   VGA_RSRC_NORMAL_IO |
+						   VGA_RSRC_NORMAL_MEM);
+		vga_put(pdev, VGA_RSRC_LEGACY_IO);
+	}
+}
+
 void intel_modeset_init_hw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -16967,6 +16998,7 @@ void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
 	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
 		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
 		i915_disable_vga(dev_priv);
+		i915_disable_vga_mem(dev_priv);
 	}
 }
 
@@ -17296,6 +17328,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
+	i915_enable_vga_mem(dev_priv);
+
 	flush_work(&dev_priv->atomic_helper.free_work);
 	WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 344f238b283f..f70cab001517 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1240,6 +1240,7 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
 void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv);
 void lpt_disable_iclkip(struct drm_i915_private *dev_priv);
 extern const struct drm_plane_funcs intel_plane_funcs;
+extern void i915_disable_vga_mem(struct drm_i915_private *dev_priv);
 void intel_init_display_hooks(struct drm_i915_private *dev_priv);
 unsigned int intel_fb_xy_to_linear(int x, int y,
 				   const struct intel_plane_state *state,
-- 
2.13.1