xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/i915/display/intel_vga.c (revision 9e5fbd4f7f25d0a357b482f4591196ee62d90ed5)
1 /*	$NetBSD: intel_vga.c,v 1.4 2021/12/19 11:49:11 riastradh Exp $	*/
2 
3 // SPDX-License-Identifier: MIT
4 /*
5  * Copyright © 2019 Intel Corporation
6  */
7 
8 #include <sys/cdefs.h>
9 __KERNEL_RCSID(0, "$NetBSD: intel_vga.c,v 1.4 2021/12/19 11:49:11 riastradh Exp $");
10 
11 #include <linux/pci.h>
12 #include <linux/vgaarb.h>
13 
14 #include <drm/i915_drm.h>
15 
16 #include "i915_drv.h"
17 #include "intel_vga.h"
18 
intel_vga_cntrl_reg(struct drm_i915_private * i915)19 static i915_reg_t intel_vga_cntrl_reg(struct drm_i915_private *i915)
20 {
21 	if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
22 		return VLV_VGACNTRL;
23 	else if (INTEL_GEN(i915) >= 5)
24 		return CPU_VGACNTRL;
25 	else
26 		return VGACNTRL;
27 }
28 
29 /* Disable the VGA plane that we never use */
intel_vga_disable(struct drm_i915_private * dev_priv)30 void intel_vga_disable(struct drm_i915_private *dev_priv)
31 {
32 	struct pci_dev *pdev = dev_priv->drm.pdev;
33 	i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
34 	u8 sr1;
35 
36 #ifdef __NetBSD__
37     {
38 	const bus_addr_t vgabase = 0x3c0;
39 	const bus_space_tag_t iot = pdev->pd_pa.pa_iot;
40 	bus_space_handle_t ioh;
41 	int error;
42 
43 	error = bus_space_map(iot, vgabase, 0x10, 0, &ioh);
44 	if (error) {
45 		aprint_error_dev(pdev->pd_dev,
46 		    "unable to map VGA registers: %d\n", error);
47 	} else {
48 		BUILD_BUG_ON(!(vgabase <= VGA_SR_INDEX));
49 		BUILD_BUG_ON(!(vgabase <= VGA_SR_DATA));
50 		bus_space_write_1(iot, ioh, VGA_SR_INDEX - vgabase, SR01);
51 		sr1 = bus_space_read_1(iot, ioh, VGA_SR_DATA - vgabase);
52 		bus_space_write_1(iot, ioh, VGA_SR_DATA - vgabase,
53 		    (sr1 | __BIT(5)));
54 		bus_space_unmap(iot, ioh, 0x10);
55 	}
56     }
57 #else
58 	/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
59 	vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
60 	outb(SR01, VGA_SR_INDEX);
61 	sr1 = inb(VGA_SR_DATA);
62 	outb(sr1 | 1 << 5, VGA_SR_DATA);
63 	vga_put(pdev, VGA_RSRC_LEGACY_IO);
64 #endif
65 	udelay(300);
66 
67 	I915_WRITE(vga_reg, VGA_DISP_DISABLE);
68 	POSTING_READ(vga_reg);
69 }
70 
intel_vga_redisable_power_on(struct drm_i915_private * dev_priv)71 void intel_vga_redisable_power_on(struct drm_i915_private *dev_priv)
72 {
73 	i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
74 
75 	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
76 		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
77 		intel_vga_disable(dev_priv);
78 	}
79 }
80 
intel_vga_redisable(struct drm_i915_private * i915)81 void intel_vga_redisable(struct drm_i915_private *i915)
82 {
83 	intel_wakeref_t wakeref;
84 
85 	/*
86 	 * This function can be called both from intel_modeset_setup_hw_state or
87 	 * at a very early point in our resume sequence, where the power well
88 	 * structures are not yet restored. Since this function is at a very
89 	 * paranoid "someone might have enabled VGA while we were not looking"
90 	 * level, just check if the power well is enabled instead of trying to
91 	 * follow the "don't touch the power well if we don't need it" policy
92 	 * the rest of the driver uses.
93 	 */
94 	wakeref = intel_display_power_get_if_enabled(i915, POWER_DOMAIN_VGA);
95 	if (!wakeref)
96 		return;
97 
98 	intel_vga_redisable_power_on(i915);
99 
100 	intel_display_power_put(i915, POWER_DOMAIN_VGA, wakeref);
101 }
102 
intel_vga_reset_io_mem(struct drm_i915_private * i915)103 void intel_vga_reset_io_mem(struct drm_i915_private *i915)
104 {
105 	struct pci_dev *pdev = i915->drm.pdev;
106 
107 	/*
108 	 * After we re-enable the power well, if we touch VGA register 0x3d5
109 	 * we'll get unclaimed register interrupts. This stops after we write
110 	 * anything to the VGA MSR register. The vgacon module uses this
111 	 * register all the time, so if we unbind our driver and, as a
112 	 * consequence, bind vgacon, we'll get stuck in an infinite loop at
113 	 * console_unlock(). So make here we touch the VGA MSR register, making
114 	 * sure vgacon can keep working normally without triggering interrupts
115 	 * and error messages.
116 	 */
117 #ifdef __NetBSD__
118     {
119 	const bus_addr_t vgabase = 0x3c0;
120 	const bus_space_tag_t iot = pdev->pd_pa.pa_iot;
121 	bus_space_handle_t ioh;
122 	int error;
123 
124 	error = bus_space_map(iot, vgabase, 0x10, 0, &ioh);
125 	if (error) {
126 		aprint_error_dev(pdev->pd_dev,
127 		    "unable to map VGA registers: %d\n", error);
128 	} else {
129 		BUILD_BUG_ON(!(vgabase <= VGA_MSR_READ));
130 		BUILD_BUG_ON(!(vgabase <= VGA_MSR_WRITE));
131 		bus_space_write_1(iot, ioh, VGA_MSR_WRITE,
132 		    bus_space_read_1(iot, ioh, VGA_MSR_READ));
133 		bus_space_unmap(iot, ioh, 0x10);
134 	}
135     }
136 #else
137 	vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
138 	outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
139 	vga_put(pdev, VGA_RSRC_LEGACY_IO);
140 #endif
141 }
142 
143 #ifndef __NetBSD__
144 static int
intel_vga_set_state(struct drm_i915_private * i915,bool enable_decode)145 intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode)
146 {
147 	unsigned int reg = INTEL_GEN(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
148 	u16 gmch_ctrl;
149 
150 	if (pci_read_config_word(i915->bridge_dev, reg, &gmch_ctrl)) {
151 		DRM_ERROR("failed to read control word\n");
152 		return -EIO;
153 	}
154 
155 	if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode)
156 		return 0;
157 
158 	if (enable_decode)
159 		gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
160 	else
161 		gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
162 
163 	if (pci_write_config_word(i915->bridge_dev, reg, gmch_ctrl)) {
164 		DRM_ERROR("failed to write control word\n");
165 		return -EIO;
166 	}
167 
168 	return 0;
169 }
170 
171 static unsigned int
intel_vga_set_decode(void * cookie,bool enable_decode)172 intel_vga_set_decode(void *cookie, bool enable_decode)
173 {
174 	struct drm_i915_private *i915 = cookie;
175 
176 	intel_vga_set_state(i915, enable_decode);
177 
178 	if (enable_decode)
179 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
180 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
181 	else
182 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
183 }
184 #endif	/* __NetBSD__ */
185 
intel_vga_register(struct drm_i915_private * i915)186 int intel_vga_register(struct drm_i915_private *i915)
187 {
188 #ifndef __NetBSD__
189 	struct pci_dev *pdev = i915->drm.pdev;
190 	int ret;
191 
192 	/*
193 	 * If we have > 1 VGA cards, then we need to arbitrate access to the
194 	 * common VGA resources.
195 	 *
196 	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
197 	 * then we do not take part in VGA arbitration and the
198 	 * vga_client_register() fails with -ENODEV.
199 	 */
200 	ret = vga_client_register(pdev, i915, NULL, intel_vga_set_decode);
201 	if (ret && ret != -ENODEV)
202 		return ret;
203 #endif
204 
205 	return 0;
206 }
207 
intel_vga_unregister(struct drm_i915_private * i915)208 void intel_vga_unregister(struct drm_i915_private *i915)
209 {
210 #ifndef __NetBSD__
211 	struct pci_dev *pdev = i915->drm.pdev;
212 
213 	vga_client_register(pdev, NULL, NULL, NULL);
214 #endif	/* __NetBSD__ */
215 }
216