blob: 10f72db7da02f10977c1c0b71f5e16eb05b2fcd1 [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>
7#include <linux/init.h>
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02008#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/pagemap.h>
10#include <linux/agp_backend.h>
Borislav Petkov48a719c2010-01-22 16:01:04 +010011#include <asm/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include "agp.h"
Daniel Vetterff7cdd62010-04-14 00:29:51 +020013#include "intel-agp.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
Daniel Vetterf51b7662010-04-14 00:29:52 +020015#include "intel-gtt.c"
16
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +080017int intel_agp_enabled;
18EXPORT_SYMBOL(intel_agp_enabled);
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020static int intel_fetch_size(void)
21{
22 int i;
23 u16 temp;
24 struct aper_size_info_16 *values;
25
26 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
27 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
28
29 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
30 if (temp == values[i].size_value) {
31 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
32 agp_bridge->aperture_size_idx = i;
33 return values[i].size;
34 }
35 }
36
37 return 0;
38}
39
40static int __intel_8xx_fetch_size(u8 temp)
41{
42 int i;
43 struct aper_size_info_8 *values;
44
45 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
46
47 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
48 if (temp == values[i].size_value) {
49 agp_bridge->previous_size =
50 agp_bridge->current_size = (void *) (values + i);
51 agp_bridge->aperture_size_idx = i;
52 return values[i].size;
53 }
54 }
55 return 0;
56}
57
58static int intel_8xx_fetch_size(void)
59{
60 u8 temp;
61
62 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
63 return __intel_8xx_fetch_size(temp);
64}
65
66static int intel_815_fetch_size(void)
67{
68 u8 temp;
69
70 /* Intel 815 chipsets have a _weird_ APSIZE register with only
71 * one non-reserved bit, so mask the others out ... */
72 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
73 temp &= (1 << 3);
74
75 return __intel_8xx_fetch_size(temp);
76}
77
78static void intel_tlbflush(struct agp_memory *mem)
79{
80 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
81 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
82}
83
84
85static void intel_8xx_tlbflush(struct agp_memory *mem)
86{
87 u32 temp;
88 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
89 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
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}
93
94
95static void intel_cleanup(void)
96{
97 u16 temp;
98 struct aper_size_info_16 *previous_size;
99
100 previous_size = A_SIZE_16(agp_bridge->previous_size);
101 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
102 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
103 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
104}
105
106
107static void intel_8xx_cleanup(void)
108{
109 u16 temp;
110 struct aper_size_info_8 *previous_size;
111
112 previous_size = A_SIZE_8(agp_bridge->previous_size);
113 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
114 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
115 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
116}
117
118
119static int intel_configure(void)
120{
121 u32 temp;
122 u16 temp2;
123 struct aper_size_info_16 *current_size;
124
125 current_size = A_SIZE_16(agp_bridge->current_size);
126
127 /* aperture size */
128 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
129
130 /* address to map to */
131 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
132 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
133
134 /* attbase - aperture base */
135 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
136
137 /* agpctrl */
138 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
139
140 /* paccfg/nbxcfg */
141 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
142 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
143 (temp2 & ~(1 << 10)) | (1 << 9));
144 /* clear any possible error conditions */
145 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
146 return 0;
147}
148
149static int intel_815_configure(void)
150{
151 u32 temp, addr;
152 u8 temp2;
153 struct aper_size_info_8 *current_size;
154
155 /* attbase - aperture base */
156 /* the Intel 815 chipset spec. says that bits 29-31 in the
157 * ATTBASE register are reserved -> try not to write them */
158 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700159 dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 return -EINVAL;
161 }
162
163 current_size = A_SIZE_8(agp_bridge->current_size);
164
165 /* aperture size */
166 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
167 current_size->size_value);
168
169 /* address to map to */
170 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
171 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
172
173 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
174 addr &= INTEL_815_ATTBASE_MASK;
175 addr |= agp_bridge->gatt_bus_addr;
176 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
177
178 /* agpctrl */
179 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
180
181 /* apcont */
182 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
183 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
184
185 /* clear any possible error conditions */
186 /* Oddness : this chipset seems to have no ERRSTS register ! */
187 return 0;
188}
189
190static void intel_820_tlbflush(struct agp_memory *mem)
191{
192 return;
193}
194
195static void intel_820_cleanup(void)
196{
197 u8 temp;
198 struct aper_size_info_8 *previous_size;
199
200 previous_size = A_SIZE_8(agp_bridge->previous_size);
201 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
202 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
203 temp & ~(1 << 1));
204 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
205 previous_size->size_value);
206}
207
208
209static int intel_820_configure(void)
210{
211 u32 temp;
212 u8 temp2;
213 struct aper_size_info_8 *current_size;
214
215 current_size = A_SIZE_8(agp_bridge->current_size);
216
217 /* aperture size */
218 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
219
220 /* address to map to */
221 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
222 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
223
224 /* attbase - aperture base */
225 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
226
227 /* agpctrl */
228 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
229
230 /* global enable aperture access */
231 /* This flag is not accessed through MCHCFG register as in */
232 /* i850 chipset. */
233 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
234 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
235 /* clear any possible AGP-related error conditions */
236 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
237 return 0;
238}
239
240static int intel_840_configure(void)
241{
242 u32 temp;
243 u16 temp2;
244 struct aper_size_info_8 *current_size;
245
246 current_size = A_SIZE_8(agp_bridge->current_size);
247
248 /* aperture size */
249 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
250
251 /* address to map to */
252 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
253 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
254
255 /* attbase - aperture base */
256 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
257
258 /* agpctrl */
259 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
260
261 /* mcgcfg */
262 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
263 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
264 /* clear any possible error conditions */
265 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
266 return 0;
267}
268
269static int intel_845_configure(void)
270{
271 u32 temp;
272 u8 temp2;
273 struct aper_size_info_8 *current_size;
274
275 current_size = A_SIZE_8(agp_bridge->current_size);
276
277 /* aperture size */
278 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
279
Matthew Garrettb0825482005-07-29 14:03:39 -0700280 if (agp_bridge->apbase_config != 0) {
281 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
282 agp_bridge->apbase_config);
283 } else {
284 /* address to map to */
285 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
286 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
287 agp_bridge->apbase_config = temp;
288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 /* attbase - aperture base */
291 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
292
293 /* agpctrl */
294 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
295
296 /* agpm */
297 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
298 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
299 /* clear any possible error conditions */
300 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
301 return 0;
302}
303
304static int intel_850_configure(void)
305{
306 u32 temp;
307 u16 temp2;
308 struct aper_size_info_8 *current_size;
309
310 current_size = A_SIZE_8(agp_bridge->current_size);
311
312 /* aperture size */
313 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
314
315 /* address to map to */
316 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
317 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
318
319 /* attbase - aperture base */
320 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
321
322 /* agpctrl */
323 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
324
325 /* mcgcfg */
326 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
327 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
328 /* clear any possible AGP-related error conditions */
329 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
330 return 0;
331}
332
333static int intel_860_configure(void)
334{
335 u32 temp;
336 u16 temp2;
337 struct aper_size_info_8 *current_size;
338
339 current_size = A_SIZE_8(agp_bridge->current_size);
340
341 /* aperture size */
342 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
343
344 /* address to map to */
345 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
346 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
347
348 /* attbase - aperture base */
349 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
350
351 /* agpctrl */
352 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
353
354 /* mcgcfg */
355 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
356 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
357 /* clear any possible AGP-related error conditions */
358 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
359 return 0;
360}
361
362static int intel_830mp_configure(void)
363{
364 u32 temp;
365 u16 temp2;
366 struct aper_size_info_8 *current_size;
367
368 current_size = A_SIZE_8(agp_bridge->current_size);
369
370 /* aperture size */
371 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
372
373 /* address to map to */
374 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
375 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
376
377 /* attbase - aperture base */
378 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
379
380 /* agpctrl */
381 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
382
383 /* gmch */
384 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
385 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
386 /* clear any possible AGP-related error conditions */
387 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
388 return 0;
389}
390
391static int intel_7505_configure(void)
392{
393 u32 temp;
394 u16 temp2;
395 struct aper_size_info_8 *current_size;
396
397 current_size = A_SIZE_8(agp_bridge->current_size);
398
399 /* aperture size */
400 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
401
402 /* address to map to */
403 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
404 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
405
406 /* attbase - aperture base */
407 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
408
409 /* agpctrl */
410 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
411
412 /* mchcfg */
413 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
414 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
415
416 return 0;
417}
418
419/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -0500420static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
422 {.mask = 0x00000017, .type = 0}
423};
424
Dave Jonese5524f32007-02-22 18:41:28 -0500425static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 {64, 16384, 4, 0},
428 {32, 8192, 3, 8},
429};
430
Dave Jonese5524f32007-02-22 18:41:28 -0500431static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 {256, 65536, 6, 0},
434 {128, 32768, 5, 32},
435 {64, 16384, 4, 48},
436 {32, 8192, 3, 56},
437 {16, 4096, 2, 60},
438 {8, 2048, 1, 62},
439 {4, 1024, 0, 63}
440};
441
Dave Jonese5524f32007-02-22 18:41:28 -0500442static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
444 {256, 65536, 6, 0},
445 {128, 32768, 5, 32},
446 {64, 16384, 4, 48},
447 {32, 8192, 3, 56},
448 {16, 4096, 2, 60},
449 {8, 2048, 1, 62},
450 {4, 1024, 0, 63}
451};
452
Dave Jonese5524f32007-02-22 18:41:28 -0500453static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 {256, 65536, 6, 0},
456 {128, 32768, 5, 32},
457 {64, 16384, 4, 48},
458 {32, 8192, 3, 56}
459};
460
Dave Jonese5524f32007-02-22 18:41:28 -0500461static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 .owner = THIS_MODULE,
463 .aperture_sizes = intel_generic_sizes,
464 .size_type = U16_APER_SIZE,
465 .num_aperture_sizes = 7,
466 .configure = intel_configure,
467 .fetch_size = intel_fetch_size,
468 .cleanup = intel_cleanup,
469 .tlb_flush = intel_tlbflush,
470 .mask_memory = agp_generic_mask_memory,
471 .masks = intel_generic_masks,
472 .agp_enable = agp_generic_enable,
473 .cache_flush = global_cache_flush,
474 .create_gatt_table = agp_generic_create_gatt_table,
475 .free_gatt_table = agp_generic_free_gatt_table,
476 .insert_memory = agp_generic_insert_memory,
477 .remove_memory = agp_generic_remove_memory,
478 .alloc_by_type = agp_generic_alloc_by_type,
479 .free_by_type = agp_generic_free_by_type,
480 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800481 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800483 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100484 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485};
486
Dave Jonese5524f32007-02-22 18:41:28 -0500487static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 .owner = THIS_MODULE,
489 .aperture_sizes = intel_815_sizes,
490 .size_type = U8_APER_SIZE,
491 .num_aperture_sizes = 2,
492 .configure = intel_815_configure,
493 .fetch_size = intel_815_fetch_size,
494 .cleanup = intel_8xx_cleanup,
495 .tlb_flush = intel_8xx_tlbflush,
496 .mask_memory = agp_generic_mask_memory,
497 .masks = intel_generic_masks,
498 .agp_enable = agp_generic_enable,
499 .cache_flush = global_cache_flush,
500 .create_gatt_table = agp_generic_create_gatt_table,
501 .free_gatt_table = agp_generic_free_gatt_table,
502 .insert_memory = agp_generic_insert_memory,
503 .remove_memory = agp_generic_remove_memory,
504 .alloc_by_type = agp_generic_alloc_by_type,
505 .free_by_type = agp_generic_free_by_type,
506 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800507 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800509 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +1000510 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511};
512
Dave Jonese5524f32007-02-22 18:41:28 -0500513static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 .owner = THIS_MODULE,
515 .aperture_sizes = intel_8xx_sizes,
516 .size_type = U8_APER_SIZE,
517 .num_aperture_sizes = 7,
518 .configure = intel_820_configure,
519 .fetch_size = intel_8xx_fetch_size,
520 .cleanup = intel_820_cleanup,
521 .tlb_flush = intel_820_tlbflush,
522 .mask_memory = agp_generic_mask_memory,
523 .masks = intel_generic_masks,
524 .agp_enable = agp_generic_enable,
525 .cache_flush = global_cache_flush,
526 .create_gatt_table = agp_generic_create_gatt_table,
527 .free_gatt_table = agp_generic_free_gatt_table,
528 .insert_memory = agp_generic_insert_memory,
529 .remove_memory = agp_generic_remove_memory,
530 .alloc_by_type = agp_generic_alloc_by_type,
531 .free_by_type = agp_generic_free_by_type,
532 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800533 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800535 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100536 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537};
538
Dave Jonese5524f32007-02-22 18:41:28 -0500539static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 .owner = THIS_MODULE,
541 .aperture_sizes = intel_830mp_sizes,
542 .size_type = U8_APER_SIZE,
543 .num_aperture_sizes = 4,
544 .configure = intel_830mp_configure,
545 .fetch_size = intel_8xx_fetch_size,
546 .cleanup = intel_8xx_cleanup,
547 .tlb_flush = intel_8xx_tlbflush,
548 .mask_memory = agp_generic_mask_memory,
549 .masks = intel_generic_masks,
550 .agp_enable = agp_generic_enable,
551 .cache_flush = global_cache_flush,
552 .create_gatt_table = agp_generic_create_gatt_table,
553 .free_gatt_table = agp_generic_free_gatt_table,
554 .insert_memory = agp_generic_insert_memory,
555 .remove_memory = agp_generic_remove_memory,
556 .alloc_by_type = agp_generic_alloc_by_type,
557 .free_by_type = agp_generic_free_by_type,
558 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800559 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800561 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100562 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563};
564
Dave Jonese5524f32007-02-22 18:41:28 -0500565static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 .owner = THIS_MODULE,
567 .aperture_sizes = intel_8xx_sizes,
568 .size_type = U8_APER_SIZE,
569 .num_aperture_sizes = 7,
570 .configure = intel_840_configure,
571 .fetch_size = intel_8xx_fetch_size,
572 .cleanup = intel_8xx_cleanup,
573 .tlb_flush = intel_8xx_tlbflush,
574 .mask_memory = agp_generic_mask_memory,
575 .masks = intel_generic_masks,
576 .agp_enable = agp_generic_enable,
577 .cache_flush = global_cache_flush,
578 .create_gatt_table = agp_generic_create_gatt_table,
579 .free_gatt_table = agp_generic_free_gatt_table,
580 .insert_memory = agp_generic_insert_memory,
581 .remove_memory = agp_generic_remove_memory,
582 .alloc_by_type = agp_generic_alloc_by_type,
583 .free_by_type = agp_generic_free_by_type,
584 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800585 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800587 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100588 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589};
590
Dave Jonese5524f32007-02-22 18:41:28 -0500591static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 .owner = THIS_MODULE,
593 .aperture_sizes = intel_8xx_sizes,
594 .size_type = U8_APER_SIZE,
595 .num_aperture_sizes = 7,
596 .configure = intel_845_configure,
597 .fetch_size = intel_8xx_fetch_size,
598 .cleanup = intel_8xx_cleanup,
599 .tlb_flush = intel_8xx_tlbflush,
600 .mask_memory = agp_generic_mask_memory,
601 .masks = intel_generic_masks,
602 .agp_enable = agp_generic_enable,
603 .cache_flush = global_cache_flush,
604 .create_gatt_table = agp_generic_create_gatt_table,
605 .free_gatt_table = agp_generic_free_gatt_table,
606 .insert_memory = agp_generic_insert_memory,
607 .remove_memory = agp_generic_remove_memory,
608 .alloc_by_type = agp_generic_alloc_by_type,
609 .free_by_type = agp_generic_free_by_type,
610 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800611 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800613 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100614 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615};
616
Dave Jonese5524f32007-02-22 18:41:28 -0500617static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 .owner = THIS_MODULE,
619 .aperture_sizes = intel_8xx_sizes,
620 .size_type = U8_APER_SIZE,
621 .num_aperture_sizes = 7,
622 .configure = intel_850_configure,
623 .fetch_size = intel_8xx_fetch_size,
624 .cleanup = intel_8xx_cleanup,
625 .tlb_flush = intel_8xx_tlbflush,
626 .mask_memory = agp_generic_mask_memory,
627 .masks = intel_generic_masks,
628 .agp_enable = agp_generic_enable,
629 .cache_flush = global_cache_flush,
630 .create_gatt_table = agp_generic_create_gatt_table,
631 .free_gatt_table = agp_generic_free_gatt_table,
632 .insert_memory = agp_generic_insert_memory,
633 .remove_memory = agp_generic_remove_memory,
634 .alloc_by_type = agp_generic_alloc_by_type,
635 .free_by_type = agp_generic_free_by_type,
636 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800637 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800639 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100640 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641};
642
Dave Jonese5524f32007-02-22 18:41:28 -0500643static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 .owner = THIS_MODULE,
645 .aperture_sizes = intel_8xx_sizes,
646 .size_type = U8_APER_SIZE,
647 .num_aperture_sizes = 7,
648 .configure = intel_860_configure,
649 .fetch_size = intel_8xx_fetch_size,
650 .cleanup = intel_8xx_cleanup,
651 .tlb_flush = intel_8xx_tlbflush,
652 .mask_memory = agp_generic_mask_memory,
653 .masks = intel_generic_masks,
654 .agp_enable = agp_generic_enable,
655 .cache_flush = global_cache_flush,
656 .create_gatt_table = agp_generic_create_gatt_table,
657 .free_gatt_table = agp_generic_free_gatt_table,
658 .insert_memory = agp_generic_insert_memory,
659 .remove_memory = agp_generic_remove_memory,
660 .alloc_by_type = agp_generic_alloc_by_type,
661 .free_by_type = agp_generic_free_by_type,
662 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800663 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800665 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100666 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667};
668
Dave Jonese5524f32007-02-22 18:41:28 -0500669static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 .owner = THIS_MODULE,
671 .aperture_sizes = intel_8xx_sizes,
672 .size_type = U8_APER_SIZE,
673 .num_aperture_sizes = 7,
674 .configure = intel_7505_configure,
675 .fetch_size = intel_8xx_fetch_size,
676 .cleanup = intel_8xx_cleanup,
677 .tlb_flush = intel_8xx_tlbflush,
678 .mask_memory = agp_generic_mask_memory,
679 .masks = intel_generic_masks,
680 .agp_enable = agp_generic_enable,
681 .cache_flush = global_cache_flush,
682 .create_gatt_table = agp_generic_create_gatt_table,
683 .free_gatt_table = agp_generic_free_gatt_table,
684 .insert_memory = agp_generic_insert_memory,
685 .remove_memory = agp_generic_remove_memory,
686 .alloc_by_type = agp_generic_alloc_by_type,
687 .free_by_type = agp_generic_free_by_type,
688 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +0800689 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +0800691 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100692 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693};
694
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800695static int find_gmch(u16 device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800697 struct pci_dev *gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800699 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
700 if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
701 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
Dave Airlief011ae72008-01-25 11:23:04 +1000702 device, gmch_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800705 if (!gmch_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 return 0;
707
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800708 intel_private.pcidev = gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 return 1;
710}
711
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800712/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
713 * driver and gmch_driver must be non-null, and find_gmch will determine
714 * which one should be used if a gmch_chip_id is present.
715 */
716static const struct intel_driver_description {
717 unsigned int chip_id;
718 unsigned int gmch_chip_id;
Wang Zhenyu88889852007-06-14 10:01:04 +0800719 unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800720 char *name;
721 const struct agp_bridge_driver *driver;
722 const struct agp_bridge_driver *gmch_driver;
723} intel_agp_chipsets[] = {
Wang Zhenyu88889852007-06-14 10:01:04 +0800724 { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
725 { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
726 { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
727 { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800728 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800729 { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800730 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800731 { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800732 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800733 { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
734 &intel_815_driver, &intel_810_driver },
735 { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
736 { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
737 { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800738 &intel_830mp_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800739 { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
740 { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
741 { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800742 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800743 { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
Stefan Husemann347486b2009-04-13 14:40:10 -0700744 { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854",
745 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800746 { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
747 { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800748 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800749 { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
750 { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800751 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800752 { PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
Carlos Martíne914a362008-01-24 10:34:09 +1000753 { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, 0, "E7221 (i915)",
754 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800755 { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800756 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800757 { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800758 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800759 { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800760 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +0800761 { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800762 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +0800763 { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800764 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800765 { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800766 NULL, &intel_i965_driver },
Zhenyu Wang9119f852008-01-23 15:49:26 +1000767 { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800768 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800769 { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800770 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800771 { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800772 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +0800773 { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800774 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +0800775 { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800776 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800777 { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
778 { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
779 { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800780 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800781 { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800782 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800783 { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
Wang Zhenyu47d46372007-06-21 13:43:18 +0800784 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800785 { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +0800786 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800787 { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +0800788 NULL, &intel_g33_driver },
Zhenyu Wang99d32bd2008-07-30 12:26:50 -0700789 { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
Adam Jackson107f5172009-12-03 17:14:41 -0500790 "GM45", NULL, &intel_i965_driver },
791 { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0,
792 "Eaglelake", NULL, &intel_i965_driver },
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000793 { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0,
794 "Q45/Q43", NULL, &intel_i965_driver },
795 { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
796 "G45/G43", NULL, &intel_i965_driver },
Fabian Henze38d8a952009-09-08 00:59:58 +0800797 { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
798 "B43", NULL, &intel_i965_driver },
Zhenyu Wanga50ccc62008-11-17 14:39:00 +0800799 { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
800 "G41", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -0500801 { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800802 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -0500803 { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800804 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -0500805 { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800806 "HD Graphics", NULL, &intel_i965_driver },
Dave Airlie3ff99162009-12-08 14:03:47 +1000807 { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +0800808 "HD Graphics", NULL, &intel_i965_driver },
Eric Anholt1089e302009-10-22 16:10:52 -0700809 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
810 "Sandybridge", NULL, &intel_i965_driver },
Eric Anholt954bce52010-01-07 16:21:46 -0800811 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
812 "Sandybridge", NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +0800813 { 0, 0, 0, NULL, NULL, NULL }
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800814};
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816static int __devinit agp_intel_probe(struct pci_dev *pdev,
817 const struct pci_device_id *ent)
818{
819 struct agp_bridge_data *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 u8 cap_ptr = 0;
821 struct resource *r;
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +0800822 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
825
826 bridge = agp_alloc_bridge();
827 if (!bridge)
828 return -ENOMEM;
829
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800830 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
831 /* In case that multiple models of gfx chip may
832 stand on same host bridge type, this can be
833 sure we detect the right IGD. */
Wang Zhenyu88889852007-06-14 10:01:04 +0800834 if (pdev->device == intel_agp_chipsets[i].chip_id) {
835 if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
836 find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
837 bridge->driver =
838 intel_agp_chipsets[i].gmch_driver;
839 break;
840 } else if (intel_agp_chipsets[i].multi_gmch_chip) {
841 continue;
842 } else {
843 bridge->driver = intel_agp_chipsets[i].driver;
844 break;
845 }
846 }
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800847 }
848
849 if (intel_agp_chipsets[i].name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700851 dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
852 pdev->vendor, pdev->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 agp_put_bridge(bridge);
854 return -ENODEV;
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800855 }
856
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800857 if (bridge->driver == NULL) {
Wang Zhenyu47d46372007-06-21 13:43:18 +0800858 /* bridge has no AGP and no IGD detected */
859 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700860 dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
861 intel_agp_chipsets[i].gmch_chip_id);
Wang Zhenyu9614ece2007-05-30 09:45:58 +0800862 agp_put_bridge(bridge);
863 return -ENODEV;
Dave Airlief011ae72008-01-25 11:23:04 +1000864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
866 bridge->dev = pdev;
867 bridge->capndx = cap_ptr;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800868 bridge->dev_private_data = &intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700870 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 /*
873 * The following fixes the case where the BIOS has "forgotten" to
874 * provide an address range for the GART.
875 * 20030610 - hamish@zot.org
876 */
877 r = &pdev->resource[0];
878 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -0500879 if (pci_assign_resource(pdev, 0)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700880 dev_err(&pdev->dev, "can't assign resource 0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 agp_put_bridge(bridge);
882 return -ENODEV;
883 }
884 }
885
886 /*
887 * If the device has not been properly setup, the following will catch
888 * the problem and should stop the system from crashing.
889 * 20030610 - hamish@zot.org
890 */
891 if (pci_enable_device(pdev)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700892 dev_err(&pdev->dev, "can't enable PCI device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 agp_put_bridge(bridge);
894 return -ENODEV;
895 }
896
897 /* Fill in the mode register */
898 if (cap_ptr) {
899 pci_read_config_dword(pdev,
900 bridge->capndx+PCI_AGP_STATUS,
901 &bridge->mode);
902 }
903
Zhenyu Wang9b974cc2010-01-05 11:25:06 +0800904 if (bridge->driver->mask_memory == intel_i965_mask_memory) {
David Woodhouseec402ba2009-11-18 10:22:46 +0000905 if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36)))
906 dev_err(&intel_private.pcidev->dev,
907 "set gfx device dma mask 36bit failed!\n");
Zhenyu Wang9b974cc2010-01-05 11:25:06 +0800908 else
909 pci_set_consistent_dma_mask(intel_private.pcidev,
910 DMA_BIT_MASK(36));
911 }
David Woodhouseec402ba2009-11-18 10:22:46 +0000912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 pci_set_drvdata(pdev, bridge);
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +0800914 err = agp_add_bridge(bridge);
915 if (!err)
916 intel_agp_enabled = 1;
917 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918}
919
920static void __devexit agp_intel_remove(struct pci_dev *pdev)
921{
922 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
923
924 agp_remove_bridge(bridge);
925
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800926 if (intel_private.pcidev)
927 pci_dev_put(intel_private.pcidev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
929 agp_put_bridge(bridge);
930}
931
Alexey Dobriyan85be7d62006-08-12 02:02:02 +0400932#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933static int agp_intel_resume(struct pci_dev *pdev)
934{
935 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
Keith Packarda8c84df2008-07-31 15:48:07 +1000936 int ret_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Daniel Vettere5a04d52010-04-14 00:29:53 +0200938 bridge->driver->configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Keith Packarda8c84df2008-07-31 15:48:07 +1000940 ret_val = agp_rebind_memory();
941 if (ret_val != 0)
942 return ret_val;
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 return 0;
945}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +0400946#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948static struct pci_device_id agp_intel_pci_table[] = {
949#define ID(x) \
950 { \
951 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
952 .class_mask = ~0, \
953 .vendor = PCI_VENDOR_ID_INTEL, \
954 .device = x, \
955 .subvendor = PCI_ANY_ID, \
956 .subdevice = PCI_ANY_ID, \
957 }
958 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
959 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
960 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
961 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
962 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
963 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
964 ID(PCI_DEVICE_ID_INTEL_82815_MC),
965 ID(PCI_DEVICE_ID_INTEL_82820_HB),
966 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
967 ID(PCI_DEVICE_ID_INTEL_82830_HB),
968 ID(PCI_DEVICE_ID_INTEL_82840_HB),
969 ID(PCI_DEVICE_ID_INTEL_82845_HB),
970 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
971 ID(PCI_DEVICE_ID_INTEL_82850_HB),
Stefan Husemann347486b2009-04-13 14:40:10 -0700972 ID(PCI_DEVICE_ID_INTEL_82854_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
974 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
975 ID(PCI_DEVICE_ID_INTEL_82860_HB),
976 ID(PCI_DEVICE_ID_INTEL_82865_HB),
977 ID(PCI_DEVICE_ID_INTEL_82875_HB),
978 ID(PCI_DEVICE_ID_INTEL_7505_0),
979 ID(PCI_DEVICE_ID_INTEL_7205_0),
Carlos Martíne914a362008-01-24 10:34:09 +1000980 ID(PCI_DEVICE_ID_INTEL_E7221_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
982 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +0100983 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +0000984 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +0800985 ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
Adam Jackson107f5172009-12-03 17:14:41 -0500986 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
987 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -0400988 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
Zhenyu Wang9119f852008-01-23 15:49:26 +1000989 ID(PCI_DEVICE_ID_INTEL_82G35_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -0400990 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
991 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +0800992 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +0800993 ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
Wang Zhenyu874808c62007-06-06 11:16:25 +0800994 ID(PCI_DEVICE_ID_INTEL_G33_HB),
995 ID(PCI_DEVICE_ID_INTEL_Q35_HB),
996 ID(PCI_DEVICE_ID_INTEL_Q33_HB),
Zhenyu Wang99d32bd2008-07-30 12:26:50 -0700997 ID(PCI_DEVICE_ID_INTEL_GM45_HB),
Adam Jackson107f5172009-12-03 17:14:41 -0500998 ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000999 ID(PCI_DEVICE_ID_INTEL_Q45_HB),
1000 ID(PCI_DEVICE_ID_INTEL_G45_HB),
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08001001 ID(PCI_DEVICE_ID_INTEL_G41_HB),
Fabian Henze38d8a952009-09-08 00:59:58 +08001002 ID(PCI_DEVICE_ID_INTEL_B43_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05001003 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
1004 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
1005 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
Dave Airlie3ff99162009-12-08 14:03:47 +10001006 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
Eric Anholt1089e302009-10-22 16:10:52 -07001007 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
Eric Anholt954bce52010-01-07 16:21:46 -08001008 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 { }
1010};
1011
1012MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
1013
1014static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 .name = "agpgart-intel",
1016 .id_table = agp_intel_pci_table,
1017 .probe = agp_intel_probe,
1018 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001019#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001021#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022};
1023
1024static int __init agp_intel_init(void)
1025{
1026 if (agp_off)
1027 return -EINVAL;
1028 return pci_register_driver(&agp_intel_pci_driver);
1029}
1030
1031static void __exit agp_intel_cleanup(void)
1032{
1033 pci_unregister_driver(&agp_intel_pci_driver);
1034}
1035
1036module_init(agp_intel_init);
1037module_exit(agp_intel_cleanup);
1038
Dave Jonesf4432c52008-10-20 13:31:45 -04001039MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040MODULE_LICENSE("GPL and additional rights");