Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT
2 : : /*
3 : : * Copyright © 2019 Intel Corporation
4 : : */
5 : :
6 : : #include <linux/pci.h>
7 : : #include <linux/vgaarb.h>
8 : :
9 : : #include <drm/i915_drm.h>
10 : :
11 : : #include "i915_drv.h"
12 : : #include "intel_vga.h"
13 : :
14 : 0 : static i915_reg_t intel_vga_cntrl_reg(struct drm_i915_private *i915)
15 : : {
16 [ # # # # ]: 0 : if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
17 : : return VLV_VGACNTRL;
18 [ # # # # ]: 0 : else if (INTEL_GEN(i915) >= 5)
19 : : return CPU_VGACNTRL;
20 : : else
21 : 0 : return VGACNTRL;
22 : : }
23 : :
24 : : /* Disable the VGA plane that we never use */
25 : 0 : void intel_vga_disable(struct drm_i915_private *dev_priv)
26 : : {
27 : 0 : struct pci_dev *pdev = dev_priv->drm.pdev;
28 [ # # ]: 0 : i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
29 : 0 : u8 sr1;
30 : :
31 : : /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
32 : 0 : vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
33 : 0 : outb(SR01, VGA_SR_INDEX);
34 : 0 : sr1 = inb(VGA_SR_DATA);
35 : 0 : outb(sr1 | 1 << 5, VGA_SR_DATA);
36 : 0 : vga_put(pdev, VGA_RSRC_LEGACY_IO);
37 : 0 : udelay(300);
38 : :
39 : 0 : I915_WRITE(vga_reg, VGA_DISP_DISABLE);
40 : 0 : POSTING_READ(vga_reg);
41 : 0 : }
42 : :
43 : 0 : void intel_vga_redisable_power_on(struct drm_i915_private *dev_priv)
44 : : {
45 [ # # ]: 0 : i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
46 : :
47 [ # # ]: 0 : if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
48 : 0 : DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
49 : 0 : intel_vga_disable(dev_priv);
50 : : }
51 : 0 : }
52 : :
53 : 0 : void intel_vga_redisable(struct drm_i915_private *i915)
54 : : {
55 : 0 : intel_wakeref_t wakeref;
56 : :
57 : : /*
58 : : * This function can be called both from intel_modeset_setup_hw_state or
59 : : * at a very early point in our resume sequence, where the power well
60 : : * structures are not yet restored. Since this function is at a very
61 : : * paranoid "someone might have enabled VGA while we were not looking"
62 : : * level, just check if the power well is enabled instead of trying to
63 : : * follow the "don't touch the power well if we don't need it" policy
64 : : * the rest of the driver uses.
65 : : */
66 : 0 : wakeref = intel_display_power_get_if_enabled(i915, POWER_DOMAIN_VGA);
67 [ # # ]: 0 : if (!wakeref)
68 : : return;
69 : :
70 : 0 : intel_vga_redisable_power_on(i915);
71 : :
72 : 0 : intel_display_power_put(i915, POWER_DOMAIN_VGA, wakeref);
73 : : }
74 : :
75 : 0 : void intel_vga_reset_io_mem(struct drm_i915_private *i915)
76 : : {
77 : 0 : struct pci_dev *pdev = i915->drm.pdev;
78 : :
79 : : /*
80 : : * After we re-enable the power well, if we touch VGA register 0x3d5
81 : : * we'll get unclaimed register interrupts. This stops after we write
82 : : * anything to the VGA MSR register. The vgacon module uses this
83 : : * register all the time, so if we unbind our driver and, as a
84 : : * consequence, bind vgacon, we'll get stuck in an infinite loop at
85 : : * console_unlock(). So make here we touch the VGA MSR register, making
86 : : * sure vgacon can keep working normally without triggering interrupts
87 : : * and error messages.
88 : : */
89 : 0 : vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
90 : 0 : outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
91 : 0 : vga_put(pdev, VGA_RSRC_LEGACY_IO);
92 : 0 : }
93 : :
94 : : static int
95 : 0 : intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode)
96 : : {
97 [ # # ]: 0 : unsigned int reg = INTEL_GEN(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
98 : 0 : u16 gmch_ctrl;
99 : :
100 [ # # ]: 0 : if (pci_read_config_word(i915->bridge_dev, reg, &gmch_ctrl)) {
101 : 0 : DRM_ERROR("failed to read control word\n");
102 : 0 : return -EIO;
103 : : }
104 : :
105 [ # # ]: 0 : if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !enable_decode)
106 : : return 0;
107 : :
108 [ # # ]: 0 : if (enable_decode)
109 : 0 : gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
110 : : else
111 : 0 : gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
112 : :
113 [ # # ]: 0 : if (pci_write_config_word(i915->bridge_dev, reg, gmch_ctrl)) {
114 : 0 : DRM_ERROR("failed to write control word\n");
115 : 0 : return -EIO;
116 : : }
117 : :
118 : : return 0;
119 : : }
120 : :
121 : : static unsigned int
122 : 0 : intel_vga_set_decode(void *cookie, bool enable_decode)
123 : : {
124 : 0 : struct drm_i915_private *i915 = cookie;
125 : :
126 : 0 : intel_vga_set_state(i915, enable_decode);
127 : :
128 [ # # ]: 0 : if (enable_decode)
129 : : return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
130 : : VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
131 : : else
132 : 0 : return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
133 : : }
134 : :
135 : 0 : int intel_vga_register(struct drm_i915_private *i915)
136 : : {
137 : 0 : struct pci_dev *pdev = i915->drm.pdev;
138 : 0 : int ret;
139 : :
140 : : /*
141 : : * If we have > 1 VGA cards, then we need to arbitrate access to the
142 : : * common VGA resources.
143 : : *
144 : : * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
145 : : * then we do not take part in VGA arbitration and the
146 : : * vga_client_register() fails with -ENODEV.
147 : : */
148 : 0 : ret = vga_client_register(pdev, i915, NULL, intel_vga_set_decode);
149 [ # # ]: 0 : if (ret && ret != -ENODEV)
150 : 0 : return ret;
151 : :
152 : : return 0;
153 : : }
154 : :
155 : 0 : void intel_vga_unregister(struct drm_i915_private *i915)
156 : : {
157 : 0 : struct pci_dev *pdev = i915->drm.pdev;
158 : :
159 : 0 : vga_client_register(pdev, NULL, NULL, NULL);
160 : 0 : }
|