diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 145 |
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 */ | ||
94 | static int | ||
95 | intel_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)); | ||
141 | out_put: | ||
142 | pci_dev_put(bridge_dev); | ||
143 | out: | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | /* Setup MCHBAR if possible, return true if we should disable it again */ | ||
148 | static bool | ||
149 | intel_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 | } | ||
187 | out_put: | ||
188 | pci_dev_put(bridge_dev); | ||
189 | out: | ||
190 | return need_disable; | ||
191 | } | ||
192 | |||
193 | static void | ||
194 | intel_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 |