blob: eab58db5f91cd9cfd6ffa5302761780ac8b3f373 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Intel AGPGART routines.
3 */
4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/module.h>
6#include <linux/pci.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09007#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <linux/init.h>
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02009#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/pagemap.h>
11#include <linux/agp_backend.h>
Borislav Petkov48a719c2010-01-22 16:01:04 +010012#include <asm/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include "agp.h"
Daniel Vetterff7cdd62010-04-14 00:29:51 +020014#include "intel-agp.h"
Zhenyu Wangf8f235e2010-08-27 11:08:57 +080015#include <linux/intel-gtt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
Daniel Vetterf51b7662010-04-14 00:29:52 +020017#include "intel-gtt.c"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +080019int intel_agp_enabled;
20EXPORT_SYMBOL(intel_agp_enabled);
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022static int intel_fetch_size(void)
23{
24 int i;
25 u16 temp;
26 struct aper_size_info_16 *values;
27
28 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
29 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
30
31 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
32 if (temp == values[i].size_value) {
33 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
34 agp_bridge->aperture_size_idx = i;
35 return values[i].size;
36 }
37 }
38
39 return 0;
40}
41
42static int __intel_8xx_fetch_size(u8 temp)
43{
44 int i;
45 struct aper_size_info_8 *values;
46
47 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
48
49 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
50 if (temp == values[i].size_value) {
51 agp_bridge->previous_size =
52 agp_bridge->current_size = (void *) (values + i);
53 agp_bridge->aperture_size_idx = i;
54 return values[i].size;
55 }
56 }
57 return 0;
58}
59
60static int intel_8xx_fetch_size(void)
61{
62 u8 temp;
63
64 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
65 return __intel_8xx_fetch_size(temp);
66}
67
68static int intel_815_fetch_size(void)
69{
70 u8 temp;
71
72 /* Intel 815 chipsets have a _weird_ APSIZE register with only
73 * one non-reserved bit, so mask the others out ... */
74 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
75 temp &= (1 << 3);
76
77 return __intel_8xx_fetch_size(temp);
78}
79
80static void intel_tlbflush(struct agp_memory *mem)
81{
82 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
83 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
84}
85
86
87static void intel_8xx_tlbflush(struct agp_memory *mem)
88{
89 u32 temp;
90 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
91 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
92 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
93 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
94}
95
96
97static void intel_cleanup(void)
98{
99 u16 temp;
100 struct aper_size_info_16 *previous_size;
101
102 previous_size = A_SIZE_16(agp_bridge->previous_size);
103 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
104 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
105 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
106}
107
108
109static void intel_8xx_cleanup(void)
110{
111 u16 temp;
112 struct aper_size_info_8 *previous_size;
113
114 previous_size = A_SIZE_8(agp_bridge->previous_size);
115 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
116 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
117 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
118}
119
120
121static int intel_configure(void)
122{
123 u32 temp;
124 u16 temp2;
125 struct aper_size_info_16 *current_size;
126
127 current_size = A_SIZE_16(agp_bridge->current_size);
128
129 /* aperture size */
130 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
131
132 /* address to map to */
133 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
134 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
135
136 /* attbase - aperture base */
137 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
138
139 /* agpctrl */
140 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
141
142 /* paccfg/nbxcfg */
143 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
144 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
145 (temp2 & ~(1 << 10)) | (1 << 9));
146 /* clear any possible error conditions */
147 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
148 return 0;
149}
150
151static int intel_815_configure(void)
152{
153 u32 temp, addr;
154 u8 temp2;
155 struct aper_size_info_8 *current_size;
156
157 /* attbase - aperture base */
158 /* the Intel 815 chipset spec. says that bits 29-31 in the
159 * ATTBASE register are reserved -> try not to write them */
160 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700161 dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 return -EINVAL;
163 }
164
165 current_size = A_SIZE_8(agp_bridge->current_size);
166
167 /* aperture size */
168 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
169 current_size->size_value);
170
171 /* address to map to */
172 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
173 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
174
175 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
176 addr &= INTEL_815_ATTBASE_MASK;
177 addr |= agp_bridge->gatt_bus_addr;
178 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
179
180 /* agpctrl */
181 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
182
183 /* apcont */
184 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
185 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
186
187 /* clear any possible error conditions */
188 /* Oddness : this chipset seems to have no ERRSTS register ! */
189 return 0;
190}
191
192static void intel_820_tlbflush(struct agp_memory *mem)
193{
194 return;
195}
196
197static void intel_820_cleanup(void)
198{
199 u8 temp;
200 struct aper_size_info_8 *previous_size;
201
202 previous_size = A_SIZE_8(agp_bridge->previous_size);
203 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
204 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
205 temp & ~(1 << 1));
206 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
207 previous_size->size_value);
208}
209
210
211static int intel_820_configure(void)
212{
213 u32 temp;
214 u8 temp2;
215 struct aper_size_info_8 *current_size;
216
217 current_size = A_SIZE_8(agp_bridge->current_size);
218
219 /* aperture size */
220 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
221
222 /* address to map to */
223 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
224 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
225
226 /* attbase - aperture base */
227 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
228
229 /* agpctrl */
230 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
231
232 /* global enable aperture access */
233 /* This flag is not accessed through MCHCFG register as in */
234 /* i850 chipset. */
235 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
236 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
237 /* clear any possible AGP-related error conditions */
238 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
239 return 0;
240}
241
242static int intel_840_configure(void)
243{
244 u32 temp;
245 u16 temp2;
246 struct aper_size_info_8 *current_size;
247
248 current_size = A_SIZE_8(agp_bridge->current_size);
249
250 /* aperture size */
251 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
252
253 /* address to map to */
254 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
255 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
256
257 /* attbase - aperture base */
258 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
259
260 /* agpctrl */
261 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
262
263 /* mcgcfg */
264 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
265 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
266 /* clear any possible error conditions */
267 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
268 return 0;
269}
270
271static int intel_845_configure(void)
272{
273 u32 temp;
274 u8 temp2;
275 struct aper_size_info_8 *current_size;
276
277 current_size = A_SIZE_8(agp_bridge->current_size);
278
279 /* aperture size */
280 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
281
Matthew Garrettb0825482005-07-29 14:03:39 -0700282 if (agp_bridge->apbase_config != 0) {
283 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
284 agp_bridge->apbase_config);
285 } else {
286 /* address to map to */
287 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
288 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
289 agp_bridge->apbase_config = temp;
290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 /* attbase - aperture base */
293 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
294
295 /* agpctrl */
296 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
297
298 /* agpm */
299 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
300 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
301 /* clear any possible error conditions */
302 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
303 return 0;
304}
305
306static int intel_850_configure(void)
307{
308 u32 temp;
309 u16 temp2;
310 struct aper_size_info_8 *current_size;
311
312 current_size = A_SIZE_8(agp_bridge->current_size);
313
314 /* aperture size */
315 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
316
317 /* address to map to */
318 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
319 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
320
321 /* attbase - aperture base */
322 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
323
324 /* agpctrl */
325 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
326
327 /* mcgcfg */
328 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
329 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
330 /* clear any possible AGP-related error conditions */
331 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
332 return 0;
333}
334
335static int intel_860_configure(void)
336{
337 u32 temp;
338 u16 temp2;
339 struct aper_size_info_8 *current_size;
340
341 current_size = A_SIZE_8(agp_bridge->current_size);
342
343 /* aperture size */
344 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
345
346 /* address to map to */
347 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
348 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
349
350 /* attbase - aperture base */
351 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
352
353 /* agpctrl */
354 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
355
356 /* mcgcfg */
357 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
358 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
359 /* clear any possible AGP-related error conditions */
360 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
361 return 0;
362}
363
364static int intel_830mp_configure(void)
365{
366 u32 temp;
367 u16 temp2;
368 struct aper_size_info_8 *current_size;
369
370 current_size = A_SIZE_8(agp_bridge->current_size);
371
372 /* aperture size */
373 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
374
375 /* address to map to */
376 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
377 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
378
379 /* attbase - aperture base */
380 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
381
382 /* agpctrl */
383 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
384
385 /* gmch */
386 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
387 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
388 /* clear any possible AGP-related error conditions */
389 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
390 return 0;
391}
392
393static int intel_7505_configure(void)
394{
395 u32 temp;
396 u16 temp2;
397 struct aper_size_info_8 *current_size;
398
399 current_size = A_SIZE_8(agp_bridge->current_size);
400
401 /* aperture size */
402 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
403
404 /* address to map to */
405 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
406 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
407
408 /* attbase - aperture base */
409 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
410
411 /* agpctrl */
412 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
413
414 /* mchcfg */
415 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
416 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
417
418 return 0;
419}
420
421/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -0500422static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 {.mask = 0x00000017, .type = 0}
425};
426
Dave Jonese5524f32007-02-22 18:41:28 -0500427static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
429 {64, 16384, 4, 0},
430 {32, 8192, 3, 8},
431};
432
Dave Jonese5524f32007-02-22 18:41:28 -0500433static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
435 {256, 65536, 6, 0},
436 {128, 32768, 5, 32},
437 {64, 16384, 4, 48},
438 {32, 8192, 3, 56},
439 {16, 4096, 2, 60},
440 {8, 2048, 1, 62},
441 {4, 1024, 0, 63}
442};
443
Dave Jonese5524f32007-02-22 18:41:28 -0500444static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
446 {256, 65536, 6, 0},
447 {128, 32768, 5, 32},
448 {64, 16384, 4, 48},
449 {32, 8192, 3, 56},
450 {16, 4096, 2, 60},
451 {8, 2048, 1, 62},
452 {4, 1024, 0, 63}
453};
454
Dave Jonese5524f32007-02-22 18:41:28 -0500455static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 {256, 65536, 6, 0},
458 {128, 32768, 5, 32},
459 {64, 16384, 4, 48},
460 {32, 8192, 3, 56}
461};
462
Dave Jonese5524f32007-02-22 18:41:28 -0500463static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 .owner = THIS_MODULE,
465 .aperture_sizes = intel_generic_sizes,
466 .size_type = U16_APER_SIZE,
467 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200468 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 .configure = intel_configure,
470 .fetch_size = intel_fetch_size,
471 .cleanup = intel_cleanup,
472 .tlb_flush = intel_tlbflush,
473 .mask_memory = agp_generic_mask_memory,
474 .masks = intel_generic_masks,
475 .agp_enable = agp_generic_enable,
476 .cache_flush = global_cache_flush,
477 .create_gatt_table = agp_generic_create_gatt_table,
478 .free_gatt_table = agp_generic_free_gatt_table,
479 .insert_memory = agp_generic_insert_memory,
480 .remove_memory = agp_generic_remove_memory,
481 .alloc_by_type = agp_generic_alloc_by_type,
482 .free_by_type = agp_generic_free_by_type,
483 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800484 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800486 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100487 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488};
489
Dave Jonese5524f32007-02-22 18:41:28 -0500490static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 .owner = THIS_MODULE,
492 .aperture_sizes = intel_815_sizes,
493 .size_type = U8_APER_SIZE,
494 .num_aperture_sizes = 2,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200495 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 .configure = intel_815_configure,
497 .fetch_size = intel_815_fetch_size,
498 .cleanup = intel_8xx_cleanup,
499 .tlb_flush = intel_8xx_tlbflush,
500 .mask_memory = agp_generic_mask_memory,
501 .masks = intel_generic_masks,
502 .agp_enable = agp_generic_enable,
503 .cache_flush = global_cache_flush,
504 .create_gatt_table = agp_generic_create_gatt_table,
505 .free_gatt_table = agp_generic_free_gatt_table,
506 .insert_memory = agp_generic_insert_memory,
507 .remove_memory = agp_generic_remove_memory,
508 .alloc_by_type = agp_generic_alloc_by_type,
509 .free_by_type = agp_generic_free_by_type,
510 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800511 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800513 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +1000514 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515};
516
Dave Jonese5524f32007-02-22 18:41:28 -0500517static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 .owner = THIS_MODULE,
519 .aperture_sizes = intel_8xx_sizes,
520 .size_type = U8_APER_SIZE,
521 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200522 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 .configure = intel_820_configure,
524 .fetch_size = intel_8xx_fetch_size,
525 .cleanup = intel_820_cleanup,
526 .tlb_flush = intel_820_tlbflush,
527 .mask_memory = agp_generic_mask_memory,
528 .masks = intel_generic_masks,
529 .agp_enable = agp_generic_enable,
530 .cache_flush = global_cache_flush,
531 .create_gatt_table = agp_generic_create_gatt_table,
532 .free_gatt_table = agp_generic_free_gatt_table,
533 .insert_memory = agp_generic_insert_memory,
534 .remove_memory = agp_generic_remove_memory,
535 .alloc_by_type = agp_generic_alloc_by_type,
536 .free_by_type = agp_generic_free_by_type,
537 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800538 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800540 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100541 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542};
543
Dave Jonese5524f32007-02-22 18:41:28 -0500544static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 .owner = THIS_MODULE,
546 .aperture_sizes = intel_830mp_sizes,
547 .size_type = U8_APER_SIZE,
548 .num_aperture_sizes = 4,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200549 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 .configure = intel_830mp_configure,
551 .fetch_size = intel_8xx_fetch_size,
552 .cleanup = intel_8xx_cleanup,
553 .tlb_flush = intel_8xx_tlbflush,
554 .mask_memory = agp_generic_mask_memory,
555 .masks = intel_generic_masks,
556 .agp_enable = agp_generic_enable,
557 .cache_flush = global_cache_flush,
558 .create_gatt_table = agp_generic_create_gatt_table,
559 .free_gatt_table = agp_generic_free_gatt_table,
560 .insert_memory = agp_generic_insert_memory,
561 .remove_memory = agp_generic_remove_memory,
562 .alloc_by_type = agp_generic_alloc_by_type,
563 .free_by_type = agp_generic_free_by_type,
564 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800565 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800567 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100568 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569};
570
Dave Jonese5524f32007-02-22 18:41:28 -0500571static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 .owner = THIS_MODULE,
573 .aperture_sizes = intel_8xx_sizes,
574 .size_type = U8_APER_SIZE,
575 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200576 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 .configure = intel_840_configure,
578 .fetch_size = intel_8xx_fetch_size,
579 .cleanup = intel_8xx_cleanup,
580 .tlb_flush = intel_8xx_tlbflush,
581 .mask_memory = agp_generic_mask_memory,
582 .masks = intel_generic_masks,
583 .agp_enable = agp_generic_enable,
584 .cache_flush = global_cache_flush,
585 .create_gatt_table = agp_generic_create_gatt_table,
586 .free_gatt_table = agp_generic_free_gatt_table,
587 .insert_memory = agp_generic_insert_memory,
588 .remove_memory = agp_generic_remove_memory,
589 .alloc_by_type = agp_generic_alloc_by_type,
590 .free_by_type = agp_generic_free_by_type,
591 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800592 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800594 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100595 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596};
597
Dave Jonese5524f32007-02-22 18:41:28 -0500598static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 .owner = THIS_MODULE,
600 .aperture_sizes = intel_8xx_sizes,
601 .size_type = U8_APER_SIZE,
602 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200603 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 .configure = intel_845_configure,
605 .fetch_size = intel_8xx_fetch_size,
606 .cleanup = intel_8xx_cleanup,
607 .tlb_flush = intel_8xx_tlbflush,
608 .mask_memory = agp_generic_mask_memory,
609 .masks = intel_generic_masks,
610 .agp_enable = agp_generic_enable,
611 .cache_flush = global_cache_flush,
612 .create_gatt_table = agp_generic_create_gatt_table,
613 .free_gatt_table = agp_generic_free_gatt_table,
614 .insert_memory = agp_generic_insert_memory,
615 .remove_memory = agp_generic_remove_memory,
616 .alloc_by_type = agp_generic_alloc_by_type,
617 .free_by_type = agp_generic_free_by_type,
618 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800619 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800621 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100622 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623};
624
Dave Jonese5524f32007-02-22 18:41:28 -0500625static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 .owner = THIS_MODULE,
627 .aperture_sizes = intel_8xx_sizes,
628 .size_type = U8_APER_SIZE,
629 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200630 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 .configure = intel_850_configure,
632 .fetch_size = intel_8xx_fetch_size,
633 .cleanup = intel_8xx_cleanup,
634 .tlb_flush = intel_8xx_tlbflush,
635 .mask_memory = agp_generic_mask_memory,
636 .masks = intel_generic_masks,
637 .agp_enable = agp_generic_enable,
638 .cache_flush = global_cache_flush,
639 .create_gatt_table = agp_generic_create_gatt_table,
640 .free_gatt_table = agp_generic_free_gatt_table,
641 .insert_memory = agp_generic_insert_memory,
642 .remove_memory = agp_generic_remove_memory,
643 .alloc_by_type = agp_generic_alloc_by_type,
644 .free_by_type = agp_generic_free_by_type,
645 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800646 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800648 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100649 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650};
651
Dave Jonese5524f32007-02-22 18:41:28 -0500652static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 .owner = THIS_MODULE,
654 .aperture_sizes = intel_8xx_sizes,
655 .size_type = U8_APER_SIZE,
656 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200657 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 .configure = intel_860_configure,
659 .fetch_size = intel_8xx_fetch_size,
660 .cleanup = intel_8xx_cleanup,
661 .tlb_flush = intel_8xx_tlbflush,
662 .mask_memory = agp_generic_mask_memory,
663 .masks = intel_generic_masks,
664 .agp_enable = agp_generic_enable,
665 .cache_flush = global_cache_flush,
666 .create_gatt_table = agp_generic_create_gatt_table,
667 .free_gatt_table = agp_generic_free_gatt_table,
668 .insert_memory = agp_generic_insert_memory,
669 .remove_memory = agp_generic_remove_memory,
670 .alloc_by_type = agp_generic_alloc_by_type,
671 .free_by_type = agp_generic_free_by_type,
672 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800673 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800675 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100676 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677};
678
Dave Jonese5524f32007-02-22 18:41:28 -0500679static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 .owner = THIS_MODULE,
681 .aperture_sizes = intel_8xx_sizes,
682 .size_type = U8_APER_SIZE,
683 .num_aperture_sizes = 7,
Jerome Glisse61cf0592010-04-20 17:43:34 +0200684 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 .configure = intel_7505_configure,
686 .fetch_size = intel_8xx_fetch_size,
687 .cleanup = intel_8xx_cleanup,
688 .tlb_flush = intel_8xx_tlbflush,
689 .mask_memory = agp_generic_mask_memory,
690 .masks = intel_generic_masks,
691 .agp_enable = agp_generic_enable,
692 .cache_flush = global_cache_flush,
693 .create_gatt_table = agp_generic_create_gatt_table,
694 .free_gatt_table = agp_generic_free_gatt_table,
695 .insert_memory = agp_generic_insert_memory,
696 .remove_memory = agp_generic_remove_memory,
697 .alloc_by_type = agp_generic_alloc_by_type,
698 .free_by_type = agp_generic_free_by_type,
699 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800700 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800702 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100703 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704};
705
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800706static int find_gmch(u16 device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800708 struct pci_dev *gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800710 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
711 if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
712 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
Dave Airlief011ae72008-01-25 11:23:04 +1000713 device, gmch_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 }
715
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800716 if (!gmch_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 return 0;
718
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800719 intel_private.pcidev = gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 return 1;
721}
722
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800723/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
724 * driver and gmch_driver must be non-null, and find_gmch will determine
725 * which one should be used if a gmch_chip_id is present.
726 */
727static const struct intel_driver_description {
728 unsigned int chip_id;
729 unsigned int gmch_chip_id;
730 char *name;
731 const struct agp_bridge_driver *driver;
732 const struct agp_bridge_driver *gmch_driver;
733} intel_agp_chipsets[] = {
Daniel Vetter059efc62010-04-14 00:29:54 +0200734 { PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL },
735 { PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL },
736 { PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL },
737 { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800738 NULL, &intel_810_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200739 { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800740 NULL, &intel_810_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200741 { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800742 NULL, &intel_810_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200743 { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815",
Wang Zhenyu88889852007-06-14 10:01:04 +0800744 &intel_815_driver, &intel_810_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200745 { PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL },
746 { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL },
747 { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800748 &intel_830mp_driver, &intel_830_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200749 { PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL },
750 { PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL },
751 { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800752 &intel_845_driver, &intel_830_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200753 { PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL },
754 { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, "854",
Stefan Husemann347486b2009-04-13 14:40:10 -0700755 &intel_845_driver, &intel_830_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200756 { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, "855PM", &intel_845_driver, NULL },
757 { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800758 &intel_845_driver, &intel_830_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200759 { PCI_DEVICE_ID_INTEL_82860_HB, 0, "i860", &intel_860_driver, NULL },
760 { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, "865",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800761 &intel_845_driver, &intel_830_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200762 { PCI_DEVICE_ID_INTEL_82875_HB, 0, "i875", &intel_845_driver, NULL },
763 { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
Carlos Martíne914a362008-01-24 10:34:09 +1000764 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200765 { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800766 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200767 { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800768 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200769 { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800770 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200771 { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800772 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200773 { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800774 NULL, &intel_915_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200775 { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800776 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200777 { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800778 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200779 { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800780 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200781 { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800782 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200783 { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800784 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200785 { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800786 NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200787 { PCI_DEVICE_ID_INTEL_7505_0, 0, "E7505", &intel_7505_driver, NULL },
788 { PCI_DEVICE_ID_INTEL_7205_0, 0, "E7205", &intel_7505_driver, NULL },
789 { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, "G33",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800790 NULL, &intel_g33_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200791 { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800792 NULL, &intel_g33_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200793 { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800794 NULL, &intel_g33_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200795 { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +0800796 NULL, &intel_g33_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200797 { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +0800798 NULL, &intel_g33_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200799 { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG,
Adam Jackson107f5172009-12-03 17:14:41 -0500800 "GM45", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200801 { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG,
Adam Jackson107f5172009-12-03 17:14:41 -0500802 "Eaglelake", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200803 { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG,
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000804 "Q45/Q43", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200805 { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG,
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000806 "G45/G43", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200807 { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG,
Fabian Henze38d8a952009-09-08 00:59:58 +0800808 "B43", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200809 { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG,
Zhenyu Wanga50ccc62008-11-17 14:39:00 +0800810 "G41", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200811 { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800812 "HD Graphics", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200813 { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800814 "HD Graphics", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200815 { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800816 "HD Graphics", NULL, &intel_i965_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200817 { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800818 "HD Graphics", NULL, &intel_i965_driver },
Zhenyu Wang85540482010-09-07 13:45:32 +0800819 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
Zhenyu Wang3869d4a2010-07-09 10:40:58 -0700820 "Sandybridge", NULL, &intel_gen6_driver },
Zhenyu Wang85540482010-09-07 13:45:32 +0800821 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
Zhenyu Wang3869d4a2010-07-09 10:40:58 -0700822 "Sandybridge", NULL, &intel_gen6_driver },
Zhenyu Wang85540482010-09-07 13:45:32 +0800823 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
824 "Sandybridge", NULL, &intel_gen6_driver },
825 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
826 "Sandybridge", NULL, &intel_gen6_driver },
827 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
828 "Sandybridge", NULL, &intel_gen6_driver },
829 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
830 "Sandybridge", NULL, &intel_gen6_driver },
831 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
Zhenyu Wang4fefe432010-08-19 09:46:16 +0800832 "Sandybridge", NULL, &intel_gen6_driver },
Daniel Vetter059efc62010-04-14 00:29:54 +0200833 { 0, 0, NULL, NULL, NULL }
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800834};
835
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200836static int __devinit intel_gmch_probe(struct pci_dev *pdev,
837 struct agp_bridge_data *bridge)
838{
Zhenyu Wang877fdac2010-08-19 09:46:13 +0800839 int i, mask;
840
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200841 bridge->driver = NULL;
842
843 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
844 if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
845 find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
846 bridge->driver =
847 intel_agp_chipsets[i].gmch_driver;
848 break;
849 }
850 }
851
852 if (!bridge->driver)
853 return 0;
854
855 bridge->dev_private_data = &intel_private;
856 bridge->dev = pdev;
857
858 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
859
Zhenyu Wang877fdac2010-08-19 09:46:13 +0800860 if (bridge->driver->mask_memory == intel_gen6_mask_memory)
861 mask = 40;
862 else if (bridge->driver->mask_memory == intel_i965_mask_memory)
863 mask = 36;
864 else
865 mask = 32;
866
867 if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
868 dev_err(&intel_private.pcidev->dev,
869 "set gfx device dma mask %d-bit failed!\n", mask);
870 else
871 pci_set_consistent_dma_mask(intel_private.pcidev,
872 DMA_BIT_MASK(mask));
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200873
874 return 1;
875}
876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877static int __devinit agp_intel_probe(struct pci_dev *pdev,
878 const struct pci_device_id *ent)
879{
880 struct agp_bridge_data *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 u8 cap_ptr = 0;
882 struct resource *r;
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +0800883 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
886
887 bridge = agp_alloc_bridge();
888 if (!bridge)
889 return -ENOMEM;
890
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200891 bridge->capndx = cap_ptr;
892
893 if (intel_gmch_probe(pdev, bridge))
894 goto found_gmch;
895
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800896 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
897 /* In case that multiple models of gfx chip may
898 stand on same host bridge type, this can be
899 sure we detect the right IGD. */
Wang Zhenyu88889852007-06-14 10:01:04 +0800900 if (pdev->device == intel_agp_chipsets[i].chip_id) {
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200901 bridge->driver = intel_agp_chipsets[i].driver;
902 break;
Wang Zhenyu88889852007-06-14 10:01:04 +0800903 }
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800904 }
905
906 if (intel_agp_chipsets[i].name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700908 dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
909 pdev->vendor, pdev->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 agp_put_bridge(bridge);
911 return -ENODEV;
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800912 }
913
Dave Airlie10fd8832010-04-20 16:34:20 +1000914 if (!bridge->driver) {
915 if (cap_ptr)
916 dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
917 intel_agp_chipsets[i].gmch_chip_id);
918 agp_put_bridge(bridge);
919 return -ENODEV;
920 }
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 bridge->dev = pdev;
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200923 bridge->dev_private_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700925 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
927 /*
Kulikov Vasiliy96576a92010-08-03 19:42:34 +0400928 * If the device has not been properly setup, the following will catch
929 * the problem and should stop the system from crashing.
930 * 20030610 - hamish@zot.org
931 */
932 if (pci_enable_device(pdev)) {
933 dev_err(&pdev->dev, "can't enable PCI device\n");
934 agp_put_bridge(bridge);
935 return -ENODEV;
936 }
937
938 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 * The following fixes the case where the BIOS has "forgotten" to
940 * provide an address range for the GART.
941 * 20030610 - hamish@zot.org
942 */
943 r = &pdev->resource[0];
944 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -0500945 if (pci_assign_resource(pdev, 0)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700946 dev_err(&pdev->dev, "can't assign resource 0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 agp_put_bridge(bridge);
948 return -ENODEV;
949 }
950 }
951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 /* Fill in the mode register */
953 if (cap_ptr) {
954 pci_read_config_dword(pdev,
955 bridge->capndx+PCI_AGP_STATUS,
956 &bridge->mode);
957 }
958
Daniel Vetter22dd82a2010-04-14 00:29:55 +0200959found_gmch:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 pci_set_drvdata(pdev, bridge);
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +0800961 err = agp_add_bridge(bridge);
962 if (!err)
963 intel_agp_enabled = 1;
964 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
967static void __devexit agp_intel_remove(struct pci_dev *pdev)
968{
969 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
970
971 agp_remove_bridge(bridge);
972
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800973 if (intel_private.pcidev)
974 pci_dev_put(intel_private.pcidev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976 agp_put_bridge(bridge);
977}
978
Alexey Dobriyan85be7d62006-08-12 02:02:02 +0400979#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980static int agp_intel_resume(struct pci_dev *pdev)
981{
982 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
Keith Packarda8c84df2008-07-31 15:48:07 +1000983 int ret_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Daniel Vettere5a04d52010-04-14 00:29:53 +0200985 bridge->driver->configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Keith Packarda8c84df2008-07-31 15:48:07 +1000987 ret_val = agp_rebind_memory();
988 if (ret_val != 0)
989 return ret_val;
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 return 0;
992}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +0400993#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995static struct pci_device_id agp_intel_pci_table[] = {
996#define ID(x) \
997 { \
998 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
999 .class_mask = ~0, \
1000 .vendor = PCI_VENDOR_ID_INTEL, \
1001 .device = x, \
1002 .subvendor = PCI_ANY_ID, \
1003 .subdevice = PCI_ANY_ID, \
1004 }
1005 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
1006 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
1007 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
1008 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
1009 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
1010 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
1011 ID(PCI_DEVICE_ID_INTEL_82815_MC),
1012 ID(PCI_DEVICE_ID_INTEL_82820_HB),
1013 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
1014 ID(PCI_DEVICE_ID_INTEL_82830_HB),
1015 ID(PCI_DEVICE_ID_INTEL_82840_HB),
1016 ID(PCI_DEVICE_ID_INTEL_82845_HB),
1017 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
1018 ID(PCI_DEVICE_ID_INTEL_82850_HB),
Stefan Husemann347486b2009-04-13 14:40:10 -07001019 ID(PCI_DEVICE_ID_INTEL_82854_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
1021 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
1022 ID(PCI_DEVICE_ID_INTEL_82860_HB),
1023 ID(PCI_DEVICE_ID_INTEL_82865_HB),
1024 ID(PCI_DEVICE_ID_INTEL_82875_HB),
1025 ID(PCI_DEVICE_ID_INTEL_7505_0),
1026 ID(PCI_DEVICE_ID_INTEL_7205_0),
Carlos Martíne914a362008-01-24 10:34:09 +10001027 ID(PCI_DEVICE_ID_INTEL_E7221_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
1029 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001030 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001031 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08001032 ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05001033 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
1034 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04001035 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
Zhenyu Wang9119f852008-01-23 15:49:26 +10001036 ID(PCI_DEVICE_ID_INTEL_82G35_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04001037 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
1038 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +08001039 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08001040 ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
Wang Zhenyu874808c62007-06-06 11:16:25 +08001041 ID(PCI_DEVICE_ID_INTEL_G33_HB),
1042 ID(PCI_DEVICE_ID_INTEL_Q35_HB),
1043 ID(PCI_DEVICE_ID_INTEL_Q33_HB),
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07001044 ID(PCI_DEVICE_ID_INTEL_GM45_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05001045 ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001046 ID(PCI_DEVICE_ID_INTEL_Q45_HB),
1047 ID(PCI_DEVICE_ID_INTEL_G45_HB),
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08001048 ID(PCI_DEVICE_ID_INTEL_G41_HB),
Fabian Henze38d8a952009-09-08 00:59:58 +08001049 ID(PCI_DEVICE_ID_INTEL_B43_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05001050 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
1051 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
1052 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
Dave Airlie3ff99162009-12-08 14:03:47 +10001053 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
Eric Anholt1089e302009-10-22 16:10:52 -07001054 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
Eric Anholt954bce52010-01-07 16:21:46 -08001055 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
Zhenyu Wang85540482010-09-07 13:45:32 +08001056 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 { }
1058};
1059
1060MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
1061
1062static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 .name = "agpgart-intel",
1064 .id_table = agp_intel_pci_table,
1065 .probe = agp_intel_probe,
1066 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001067#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001069#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070};
1071
1072static int __init agp_intel_init(void)
1073{
1074 if (agp_off)
1075 return -EINVAL;
1076 return pci_register_driver(&agp_intel_pci_driver);
1077}
1078
1079static void __exit agp_intel_cleanup(void)
1080{
1081 pci_unregister_driver(&agp_intel_pci_driver);
1082}
1083
1084module_init(agp_intel_init);
1085module_exit(agp_intel_cleanup);
1086
Dave Jonesf4432c52008-10-20 13:31:45 -04001087MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088MODULE_LICENSE("GPL and additional rights");