aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c145
2 files changed, 147 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index db81f5513daa..6a471458d61a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -150,6 +150,8 @@ typedef struct drm_i915_private {
150 drm_local_map_t hws_map; 150 drm_local_map_t hws_map;
151 struct drm_gem_object *hws_obj; 151 struct drm_gem_object *hws_obj;
152 152
153 struct resource mch_res;
154
153 unsigned int cpp; 155 unsigned int cpp;
154 int back_offset; 156 int back_offset;
155 int front_offset; 157 int front_offset;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 07d976bf4931..9a05cadaa4ad 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -25,6 +25,8 @@
25 * 25 *
26 */ 26 */
27 27
28#include <linux/acpi.h>
29#include <linux/pnp.h>
28#include "linux/string.h" 30#include "linux/string.h"
29#include "linux/bitops.h" 31#include "linux/bitops.h"
30#include "drmP.h" 32#include "drmP.h"
@@ -81,6 +83,143 @@
81 * to match what the GPU expects. 83 * to match what the GPU expects.
82 */ 84 */
83 85
86#define MCHBAR_I915 0x44
87#define MCHBAR_I965 0x48
88#define MCHBAR_SIZE (4*4096)
89
90#define DEVEN_REG 0x54
91#define DEVEN_MCHBAR_EN (1 << 28)
92
93/* Allocate space for the MCH regs if needed, return nonzero on error */
94static int
95intel_alloc_mchbar_resource(struct drm_device *dev)
96{
97 struct pci_dev *bridge_dev;
98 drm_i915_private_t *dev_priv = dev->dev_private;
99 int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
100 u32 temp_lo, temp_hi = 0;
101 u64 mchbar_addr;
102 int ret = 0;
103
104 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
105 if (!bridge_dev) {
106 DRM_DEBUG("no bridge dev?!\n");
107 ret = -ENODEV;
108 goto out;
109 }
110
111 if (IS_I965G(dev))
112 pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
113 pci_read_config_dword(bridge_dev, reg, &temp_lo);
114 mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
115
116 /* If ACPI doesn't have it, assume we need to allocate it ourselves */
117 if (mchbar_addr &&
118 pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
119 ret = 0;
120 goto out_put;
121 }
122
123 /* Get some space for it */
124 ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
125 MCHBAR_SIZE, MCHBAR_SIZE,
126 PCIBIOS_MIN_MEM,
127 0, pcibios_align_resource,
128 bridge_dev);
129 if (ret) {
130 DRM_DEBUG("failed bus alloc: %d\n", ret);
131 dev_priv->mch_res.start = 0;
132 goto out_put;
133 }
134
135 if (IS_I965G(dev))
136 pci_write_config_dword(bridge_dev, reg + 4,
137 upper_32_bits(dev_priv->mch_res.start));
138
139 pci_write_config_dword(bridge_dev, reg,
140 lower_32_bits(dev_priv->mch_res.start));
141out_put:
142 pci_dev_put(bridge_dev);
143out:
144 return ret;
145}
146
147/* Setup MCHBAR if possible, return true if we should disable it again */
148static bool
149intel_setup_mchbar(struct drm_device *dev)
150{
151 struct pci_dev *bridge_dev;
152 int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
153 u32 temp;
154 bool need_disable = false, enabled;
155
156 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
157 if (!bridge_dev) {
158 DRM_DEBUG("no bridge dev?!\n");
159 goto out;
160 }
161
162 if (IS_I915G(dev) || IS_I915GM(dev)) {
163 pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
164 enabled = !!(temp & DEVEN_MCHBAR_EN);
165 } else {
166 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
167 enabled = temp & 1;
168 }
169
170 /* If it's already enabled, don't have to do anything */
171 if (enabled)
172 goto out_put;
173
174 if (intel_alloc_mchbar_resource(dev))
175 goto out_put;
176
177 need_disable = true;
178
179 /* Space is allocated or reserved, so enable it. */
180 if (IS_I915G(dev) || IS_I915GM(dev)) {
181 pci_write_config_dword(bridge_dev, DEVEN_REG,
182 temp | DEVEN_MCHBAR_EN);
183 } else {
184 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
185 pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
186 }
187out_put:
188 pci_dev_put(bridge_dev);
189out:
190 return need_disable;
191}
192
193static void
194intel_teardown_mchbar(struct drm_device *dev, bool disable)
195{
196 drm_i915_private_t *dev_priv = dev->dev_private;
197 struct pci_dev *bridge_dev;
198 int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
199 u32 temp;
200
201 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
202 if (!bridge_dev) {
203 DRM_DEBUG("no bridge dev?!\n");
204 return;
205 }
206
207 if (disable) {
208 if (IS_I915G(dev) || IS_I915GM(dev)) {
209 pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
210 temp &= ~DEVEN_MCHBAR_EN;
211 pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
212 } else {
213 pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
214 temp &= ~1;
215 pci_write_config_dword(bridge_dev, mchbar_reg, temp);
216 }
217 }
218
219 if (dev_priv->mch_res.start)
220 release_resource(&dev_priv->mch_res);
221}
222
84/** 223/**
85 * Detects bit 6 swizzling of address lookup between IGD access and CPU 224 * Detects bit 6 swizzling of address lookup between IGD access and CPU
86 * access through main memory. 225 * access through main memory.
@@ -91,6 +230,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
91 drm_i915_private_t *dev_priv = dev->dev_private; 230 drm_i915_private_t *dev_priv = dev->dev_private;
92 uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; 231 uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
93 uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; 232 uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
233 bool need_disable;
94 234
95 if (!IS_I9XX(dev)) { 235 if (!IS_I9XX(dev)) {
96 /* As far as we know, the 865 doesn't have these bit 6 236 /* As far as we know, the 865 doesn't have these bit 6
@@ -101,6 +241,9 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
101 } else if (IS_MOBILE(dev)) { 241 } else if (IS_MOBILE(dev)) {
102 uint32_t dcc; 242 uint32_t dcc;
103 243
244 /* Try to make sure MCHBAR is enabled before poking at it */
245 need_disable = intel_setup_mchbar(dev);
246
104 /* On mobile 9xx chipsets, channel interleave by the CPU is 247 /* On mobile 9xx chipsets, channel interleave by the CPU is
105 * determined by DCC. For single-channel, neither the CPU 248 * determined by DCC. For single-channel, neither the CPU
106 * nor the GPU do swizzling. For dual channel interleaved, 249 * nor the GPU do swizzling. For dual channel interleaved,
@@ -140,6 +283,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
140 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; 283 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
141 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; 284 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
142 } 285 }
286
287 intel_teardown_mchbar(dev, need_disable);
143 } else { 288 } else {
144 /* The 965, G33, and newer, have a very flexible memory 289 /* The 965, G33, and newer, have a very flexible memory
145 * configuration. It will enable dual-channel mode 290 * configuration. It will enable dual-channel mode