diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-11 18:39:05 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-11 18:39:05 (GMT) |
commit | 3334500b460a5eede2e3466ca97a90fe3b91ceb5 (patch) | |
tree | 970829ec5116abcaf237be5214b89638404554be /drivers/char/agp | |
parent | 72f60acb01fc7ef135d3181ba9235c9ef0ab68ea (diff) | |
parent | 874808c6dd429f7431b906a32c7f78a68e7636af (diff) | |
download | linux-3334500b460a5eede2e3466ca97a90fe3b91ceb5.tar.xz |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
* master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart:
[AGPGART] intel_agp: Add support for G33, Q33 and Q35 chipsets
[AGPGART] intel_agp: add support for 945GME
[AGPGART] intel_agp: add support for 965GME/GLE
[AGPGART] intel_agp: use table for device probe
[AGPGART] intel_agp: cleanup intel private data
Diffstat (limited to 'drivers/char/agp')
-rw-r--r-- | drivers/char/agp/agp.h | 6 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.c | 576 |
2 files changed, 275 insertions, 307 deletions
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index fdbca25..35ab1a9 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -176,7 +176,7 @@ struct agp_bridge_data { #define I830_GMCH_MEM_MASK 0x1 #define I830_GMCH_MEM_64M 0x1 #define I830_GMCH_MEM_128M 0 -#define I830_GMCH_GMS_MASK 0x70 +#define I830_GMCH_GMS_MASK 0xF0 #define I830_GMCH_GMS_DISABLED 0x00 #define I830_GMCH_GMS_LOCAL 0x10 #define I830_GMCH_GMS_STOLEN_512 0x20 @@ -231,6 +231,10 @@ struct agp_bridge_data { #define I965_PGETBL_SIZE_512KB (0 << 1) #define I965_PGETBL_SIZE_256KB (1 << 1) #define I965_PGETBL_SIZE_128KB (2 << 1) +#define G33_PGETBL_SIZE_MASK (3 << 8) +#define G33_PGETBL_SIZE_1M (1 << 8) +#define G33_PGETBL_SIZE_2M (2 << 8) + #define I810_DRAM_CTL 0x3000 #define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001 diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 9c69f2e..d383168 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -20,6 +20,14 @@ #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 +#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 +#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE +#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 +#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 +#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 +#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 +#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 +#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 #define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ @@ -27,6 +35,9 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB) +#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB) extern int agp_memory_reserved; @@ -53,6 +64,8 @@ extern int agp_memory_reserved; #define I915_PTEADDR 0x1C #define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) +#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) +#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) /* Intel 965G registers */ #define I965_MSAC 0x62 @@ -86,11 +99,18 @@ static struct gatt_mask intel_i810_masks[] = .type = INTEL_AGP_CACHED_MEMORY} }; -static struct _intel_i810_private { - struct pci_dev *i810_dev; /* device one */ - volatile u8 __iomem *registers; +static struct _intel_private { + struct pci_dev *pcidev; /* device one */ + u8 __iomem *registers; + u32 __iomem *gtt; /* I915G */ int num_dcache_entries; -} intel_i810_private; + /* gtt_entries is the number of gtt entries that are already mapped + * to stolen memory. Stolen memory is larger than the memory mapped + * through gtt_entries, as it includes some reserved space for the BIOS + * popup and for the GTT. + */ + int gtt_entries; /* i830+ */ +} intel_private; static int intel_i810_fetch_size(void) { @@ -127,32 +147,32 @@ static int intel_i810_configure(void) current_size = A_SIZE_FIX(agp_bridge->current_size); - if (!intel_i810_private.registers) { - pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp); + if (!intel_private.registers) { + pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); temp &= 0xfff80000; - intel_i810_private.registers = ioremap(temp, 128 * 4096); - if (!intel_i810_private.registers) { + intel_private.registers = ioremap(temp, 128 * 4096); + if (!intel_private.registers) { printk(KERN_ERR PFX "Unable to remap memory.\n"); return -ENOMEM; } } - if ((readl(intel_i810_private.registers+I810_DRAM_CTL) + if ((readl(intel_private.registers+I810_DRAM_CTL) & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { /* This will need to be dynamically assigned */ printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); - intel_i810_private.num_dcache_entries = 1024; + intel_private.num_dcache_entries = 1024; } - pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp); + pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL); - readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ + writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); + readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ if (agp_bridge->driver->needs_scratch_page) { for (i = 0; i < current_size->num_entries; i++) { - writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); - readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */ + writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); + readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */ } } global_cache_flush(); @@ -161,9 +181,9 @@ static int intel_i810_configure(void) static void intel_i810_cleanup(void) { - writel(0, intel_i810_private.registers+I810_PGETBL_CTL); - readl(intel_i810_private.registers); /* PCI Posting. */ - iounmap(intel_i810_private.registers); + writel(0, intel_private.registers+I810_PGETBL_CTL); + readl(intel_private.registers); /* PCI Posting. */ + iounmap(intel_private.registers); } static void intel_i810_tlbflush(struct agp_memory *mem) @@ -261,9 +281,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, global_cache_flush(); for (i = pg_start; i < (pg_start + mem->page_count); i++) { writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, - intel_i810_private.registers+I810_PTE_BASE+(i*4)); + intel_private.registers+I810_PTE_BASE+(i*4)); } - readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); + readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); break; case AGP_PHYS_MEMORY: case AGP_NORMAL_MEMORY: @@ -273,9 +293,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mask_type), - intel_i810_private.registers+I810_PTE_BASE+(j*4)); + intel_private.registers+I810_PTE_BASE+(j*4)); } - readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); + readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); break; default: goto out_err; @@ -298,9 +318,9 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, return 0; for (i = pg_start; i < (mem->page_count + pg_start); i++) { - writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); + writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); } - readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); + readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); agp_bridge->driver->tlb_flush(mem); return 0; @@ -354,7 +374,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) struct agp_memory *new; if (type == AGP_DCACHE_MEMORY) { - if (pg_count != intel_i810_private.num_dcache_entries) + if (pg_count != intel_private.num_dcache_entries) return NULL; new = agp_create_memory(1); @@ -404,18 +424,6 @@ static struct aper_size_info_fixed intel_i830_sizes[] = {512, 131072, 7}, }; -static struct _intel_i830_private { - struct pci_dev *i830_dev; /* device one */ - volatile u8 __iomem *registers; - volatile u32 __iomem *gtt; /* I915G */ - /* gtt_entries is the number of gtt entries that are already mapped - * to stolen memory. Stolen memory is larger than the memory mapped - * through gtt_entries, as it includes some reserved space for the BIOS - * popup and for the GTT. - */ - int gtt_entries; -} intel_i830_private; - static void intel_i830_init_gtt_entries(void) { u16 gmch_ctrl; @@ -429,7 +437,7 @@ static void intel_i830_init_gtt_entries(void) if (IS_I965) { u32 pgetbl_ctl; - pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL); + pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); /* The 965 has a field telling us the size of the GTT, * which may be larger than what is necessary to map the @@ -451,6 +459,22 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; /* add in BIOS popup space */ + } else if (IS_G33) { + /* G33's GTT size defined in gmch_ctrl */ + switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { + case G33_PGETBL_SIZE_1M: + size = 1024; + break; + case G33_PGETBL_SIZE_2M: + size = 2048; + break; + default: + printk(KERN_INFO PFX "Unknown page table size 0x%x, " + "assuming 512KB\n", + (gmch_ctrl & G33_PGETBL_SIZE_MASK)); + size = 512; + } + size += 4; } else { /* On previous hardware, the GTT size was just what was * required to map the aperture. @@ -471,7 +495,7 @@ static void intel_i830_init_gtt_entries(void) gtt_entries = MB(8) - KB(size); break; case I830_GMCH_GMS_LOCAL: - rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE); + rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); gtt_entries = (I830_RDRAM_ND(rdct) + 1) * MB(ddt[I830_RDRAM_DDT(rdct)]); local = 1; @@ -502,7 +526,8 @@ static void intel_i830_init_gtt_entries(void) if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 ) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || + IS_I965 || IS_G33) gtt_entries = MB(48) - KB(size); else gtt_entries = 0; @@ -512,10 +537,24 @@ static void intel_i830_init_gtt_entries(void) if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || + IS_I965 || IS_G33) gtt_entries = MB(64) - KB(size); else gtt_entries = 0; + break; + case G33_GMCH_GMS_STOLEN_128M: + if (IS_G33) + gtt_entries = MB(128) - KB(size); + else + gtt_entries = 0; + break; + case G33_GMCH_GMS_STOLEN_256M: + if (IS_G33) + gtt_entries = MB(256) - KB(size); + else + gtt_entries = 0; + break; default: gtt_entries = 0; break; @@ -529,7 +568,7 @@ static void intel_i830_init_gtt_entries(void) "No pre-allocated video memory detected.\n"); gtt_entries /= KB(4); - intel_i830_private.gtt_entries = gtt_entries; + intel_private.gtt_entries = gtt_entries; } /* The intel i830 automatically initializes the agp aperture during POST. @@ -547,14 +586,14 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) num_entries = size->num_entries; agp_bridge->gatt_table_real = NULL; - pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); + pci_read_config_dword(intel_private.pcidev,I810_MMADDR,&temp); temp &= 0xfff80000; - intel_i830_private.registers = ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) + intel_private.registers = ioremap(temp,128 * 4096); + if (!intel_private.registers) return -ENOMEM; - temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; + temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; global_cache_flush(); /* FIXME: ?? */ /* we have to call this as early as possible after the MMIO base address is known */ @@ -614,20 +653,20 @@ static int intel_i830_configure(void) current_size = A_SIZE_FIX(agp_bridge->current_size); - pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp); + pci_read_config_dword(intel_private.pcidev,I810_GMADDR,&temp); agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); gmch_ctrl |= I830_GMCH_ENABLED; pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); - writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL); - readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ + writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); + readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ if (agp_bridge->driver->needs_scratch_page) { - for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) { - writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); - readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ + for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { + writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); + readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ } } @@ -637,7 +676,7 @@ static int intel_i830_configure(void) static void intel_i830_cleanup(void) { - iounmap(intel_i830_private.registers); + iounmap(intel_private.registers); } static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type) @@ -653,9 +692,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int temp = agp_bridge->current_size; num_entries = A_SIZE_FIX(temp)->num_entries; - if (pg_start < intel_i830_private.gtt_entries) { - printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", - pg_start,intel_i830_private.gtt_entries); + if (pg_start < intel_private.gtt_entries) { + printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", + pg_start,intel_private.gtt_entries); printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); goto out_err; @@ -683,9 +722,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mask_type), - intel_i830_private.registers+I810_PTE_BASE+(j*4)); + intel_private.registers+I810_PTE_BASE+(j*4)); } - readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); + readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); agp_bridge->driver->tlb_flush(mem); out: @@ -703,15 +742,15 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, if (mem->page_count == 0) return 0; - if (pg_start < intel_i830_private.gtt_entries) { + if (pg_start < intel_private.gtt_entries) { printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); return -EINVAL; } for (i = pg_start; i < (mem->page_count + pg_start); i++) { - writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); + writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); } - readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4)); + readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); agp_bridge->driver->tlb_flush(mem); return 0; @@ -734,7 +773,7 @@ static int intel_i915_configure(void) current_size = A_SIZE_FIX(agp_bridge->current_size); - pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp); + pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp); agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); @@ -742,13 +781,13 @@ static int intel_i915_configure(void) gmch_ctrl |= I830_GMCH_ENABLED; pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); - writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL); - readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ + writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); + readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ if (agp_bridge->driver->needs_scratch_page) { - for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) { - writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); - readl(intel_i830_private.gtt+i); /* PCI Posting. */ + for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { + writel(agp_bridge->scratch_page, intel_private.gtt+i); + readl(intel_private.gtt+i); /* PCI Posting. */ } } @@ -758,8 +797,8 @@ static int intel_i915_configure(void) static void intel_i915_cleanup(void) { - iounmap(intel_i830_private.gtt); - iounmap(intel_i830_private.registers); + iounmap(intel_private.gtt); + iounmap(intel_private.registers); } static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, @@ -776,9 +815,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, temp = agp_bridge->current_size; num_entries = A_SIZE_FIX(temp)->num_entries; - if (pg_start < intel_i830_private.gtt_entries) { - printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", - pg_start,intel_i830_private.gtt_entries); + if (pg_start < intel_private.gtt_entries) { + printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", + pg_start,intel_private.gtt_entries); printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); goto out_err; @@ -805,10 +844,10 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, - mem->memory[i], mask_type), intel_i830_private.gtt+j); + mem->memory[i], mask_type), intel_private.gtt+j); } - readl(intel_i830_private.gtt+j-1); + readl(intel_private.gtt+j-1); agp_bridge->driver->tlb_flush(mem); out: @@ -826,15 +865,15 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, if (mem->page_count == 0) return 0; - if (pg_start < intel_i830_private.gtt_entries) { + if (pg_start < intel_private.gtt_entries) { printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); return -EINVAL; } for (i = pg_start; i < (mem->page_count + pg_start); i++) { - writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); + writel(agp_bridge->scratch_page, intel_private.gtt+i); } - readl(intel_i830_private.gtt+i-1); + readl(intel_private.gtt+i-1); agp_bridge->driver->tlb_flush(mem); return 0; @@ -850,7 +889,7 @@ static int intel_i9xx_fetch_size(void) int aper_size; /* size in megabytes */ int i; - aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1); + aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1); for (i = 0; i < num_sizes; i++) { if (aper_size == intel_i830_sizes[i].size) { @@ -878,20 +917,20 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) num_entries = size->num_entries; agp_bridge->gatt_table_real = NULL; - pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp); - pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2); + pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); + pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2); - intel_i830_private.gtt = ioremap(temp2, 256 * 1024); - if (!intel_i830_private.gtt) + intel_private.gtt = ioremap(temp2, 256 * 1024); + if (!intel_private.gtt) return -ENOMEM; temp &= 0xfff80000; - intel_i830_private.registers = ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) + intel_private.registers = ioremap(temp,128 * 4096); + if (!intel_private.registers) return -ENOMEM; - temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; + temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; global_cache_flush(); /* FIXME: ? */ /* we have to call this as early as possible after the MMIO base address is known */ @@ -938,20 +977,20 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) num_entries = size->num_entries; agp_bridge->gatt_table_real = NULL; - pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp); + pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); temp &= 0xfff00000; - intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024); + intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024); - if (!intel_i830_private.gtt) + if (!intel_private.gtt) return -ENOMEM; - intel_i830_private.registers = ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) + intel_private.registers = ioremap(temp,128 * 4096); + if (!intel_private.registers) return -ENOMEM; - temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; + temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; global_cache_flush(); /* FIXME: ? */ /* we have to call this as early as possible after the MMIO base address is known */ @@ -1722,41 +1761,126 @@ static const struct agp_bridge_driver intel_7505_driver = { .agp_type_to_mask_type = agp_generic_type_to_mask_type, }; -static int find_i810(u16 device) -{ - struct pci_dev *i810_dev; - - i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); - if (!i810_dev) - return 0; - intel_i810_private.i810_dev = i810_dev; - return 1; -} +static const struct agp_bridge_driver intel_g33_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_i830_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 4, + .needs_scratch_page = TRUE, + .configure = intel_i915_configure, + .fetch_size = intel_i9xx_fetch_size, + .cleanup = intel_i915_cleanup, + .tlb_flush = intel_i810_tlbflush, + .mask_memory = intel_i965_mask_memory, + .masks = intel_i810_masks, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = intel_i915_create_gatt_table, + .free_gatt_table = intel_i830_free_gatt_table, + .insert_memory = intel_i915_insert_entries, + .remove_memory = intel_i915_remove_entries, + .alloc_by_type = intel_i830_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .agp_type_to_mask_type = intel_i830_type_to_mask_type, +}; -static int find_i830(u16 device) +static int find_gmch(u16 device) { - struct pci_dev *i830_dev; + struct pci_dev *gmch_device; - i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); - if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) { - i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, - device, i830_dev); + gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); + if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { + gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, + device, gmch_device); } - if (!i830_dev) + if (!gmch_device) return 0; - intel_i830_private.i830_dev = i830_dev; + intel_private.pcidev = gmch_device; return 1; } +/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of + * driver and gmch_driver must be non-null, and find_gmch will determine + * which one should be used if a gmch_chip_id is present. + */ +static const struct intel_driver_description { + unsigned int chip_id; + unsigned int gmch_chip_id; + char *name; + const struct agp_bridge_driver *driver; + const struct agp_bridge_driver *gmch_driver; +} intel_agp_chipsets[] = { + { PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810", + NULL, &intel_810_driver }, + { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810", + NULL, &intel_810_driver }, + { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810", + NULL, &intel_810_driver }, + { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815", + &intel_810_driver, &intel_815_driver }, + { PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M", + &intel_830mp_driver, &intel_830_driver }, + { PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M", + &intel_845_driver, &intel_830_driver }, + { PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, "855PM", &intel_845_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", + &intel_845_driver, &intel_830_driver }, + { PCI_DEVICE_ID_INTEL_82860_HB, 0, "i860", &intel_860_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, "865", + &intel_845_driver, &intel_830_driver }, + { PCI_DEVICE_ID_INTEL_82875_HB, 0, "i875", &intel_845_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, "915G", + &intel_845_driver, &intel_915_driver }, + { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", + &intel_845_driver, &intel_915_driver }, + { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, "945G", + &intel_845_driver, &intel_915_driver }, + { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", + &intel_845_driver, &intel_915_driver }, + { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", + &intel_845_driver, &intel_915_driver }, + { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_82965G_1_HB, PCI_DEVICE_ID_INTEL_82965G_1_IG, "965G", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, "965G", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", + &intel_845_driver, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_7505_0, 0, "E7505", &intel_7505_driver, NULL }, + { PCI_DEVICE_ID_INTEL_7205_0, 0, "E7205", &intel_7505_driver, NULL }, + { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, "G33", + &intel_845_driver, &intel_g33_driver }, + { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", + &intel_845_driver, &intel_g33_driver }, + { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", + &intel_845_driver, &intel_g33_driver }, + { 0, 0, NULL, NULL, NULL } +}; + static int __devinit agp_intel_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; - char *name = "(unknown)"; u8 cap_ptr = 0; struct resource *r; + int i; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); @@ -1764,195 +1888,42 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, if (!bridge) return -ENOMEM; - switch (pdev->device) { - case PCI_DEVICE_ID_INTEL_82443LX_0: - bridge->driver = &intel_generic_driver; - name = "440LX"; - break; - case PCI_DEVICE_ID_INTEL_82443BX_0: - bridge->driver = &intel_generic_driver; - name = "440BX"; - break; - case PCI_DEVICE_ID_INTEL_82443GX_0: - bridge->driver = &intel_generic_driver; - name = "440GX"; - break; - case PCI_DEVICE_ID_INTEL_82810_MC1: - name = "i810"; - if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1)) - goto fail; - bridge->driver = &intel_810_driver; - break; - case PCI_DEVICE_ID_INTEL_82810_MC3: - name = "i810 DC100"; - if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3)) - goto fail; - bridge->driver = &intel_810_driver; - break; - case PCI_DEVICE_ID_INTEL_82810E_MC: - name = "i810 E"; - if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG)) - goto fail; - bridge->driver = &intel_810_driver; - break; - case PCI_DEVICE_ID_INTEL_82815_MC: - /* - * The i815 can operate either as an i810 style - * integrated device, or as an AGP4X motherboard. - */ - if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC)) - bridge->driver = &intel_810_driver; - else - bridge->driver = &intel_815_driver; - name = "i815"; - break; - case PCI_DEVICE_ID_INTEL_82820_HB: - case PCI_DEVICE_ID_INTEL_82820_UP_HB: - bridge->driver = &intel_820_driver; - name = "i820"; - break; - case PCI_DEVICE_ID_INTEL_82830_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) - bridge->driver = &intel_830_driver; - else - bridge->driver = &intel_830mp_driver; - name = "830M"; - break; - case PCI_DEVICE_ID_INTEL_82840_HB: - bridge->driver = &intel_840_driver; - name = "i840"; - break; - case PCI_DEVICE_ID_INTEL_82845_HB: - bridge->driver = &intel_845_driver; - name = "i845"; - break; - case PCI_DEVICE_ID_INTEL_82845G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) - bridge->driver = &intel_830_driver; - else - bridge->driver = &intel_845_driver; - name = "845G"; - break; - case PCI_DEVICE_ID_INTEL_82850_HB: - bridge->driver = &intel_850_driver; - name = "i850"; - break; - case PCI_DEVICE_ID_INTEL_82855PM_HB: - bridge->driver = &intel_845_driver; - name = "855PM"; - break; - case PCI_DEVICE_ID_INTEL_82855GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) { - bridge->driver = &intel_830_driver; - name = "855"; - } else { - bridge->driver = &intel_845_driver; - name = "855GM"; - } - break; - case PCI_DEVICE_ID_INTEL_82860_HB: - bridge->driver = &intel_860_driver; - name = "i860"; - break; - case PCI_DEVICE_ID_INTEL_82865_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) - bridge->driver = &intel_830_driver; - else - bridge->driver = &intel_845_driver; - name = "865"; - break; - case PCI_DEVICE_ID_INTEL_82875_HB: - bridge->driver = &intel_845_driver; - name = "i875"; - break; - case PCI_DEVICE_ID_INTEL_82915G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) - bridge->driver = &intel_915_driver; - else - bridge->driver = &intel_845_driver; - name = "915G"; - break; - case PCI_DEVICE_ID_INTEL_82915GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) - bridge->driver = &intel_915_driver; - else - bridge->driver = &intel_845_driver; - name = "915GM"; - break; - case PCI_DEVICE_ID_INTEL_82945G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) - bridge->driver = &intel_915_driver; - else - bridge->driver = &intel_845_driver; - name = "945G"; - break; - case PCI_DEVICE_ID_INTEL_82945GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) - bridge->driver = &intel_915_driver; - else - bridge->driver = &intel_845_driver; - name = "945GM"; - break; - case PCI_DEVICE_ID_INTEL_82946GZ_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "946GZ"; - break; - case PCI_DEVICE_ID_INTEL_82965G_1_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965G"; - break; - case PCI_DEVICE_ID_INTEL_82965Q_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965Q"; - break; - case PCI_DEVICE_ID_INTEL_82965G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965G"; - break; - case PCI_DEVICE_ID_INTEL_82965GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965GM"; - break; - case PCI_DEVICE_ID_INTEL_7505_0: - bridge->driver = &intel_7505_driver; - name = "E7505"; - break; - case PCI_DEVICE_ID_INTEL_7205_0: - bridge->driver = &intel_7505_driver; - name = "E7205"; - break; - default: + for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { + /* In case that multiple models of gfx chip may + stand on same host bridge type, this can be + sure we detect the right IGD. */ + if ((pdev->device == intel_agp_chipsets[i].chip_id) && + ((intel_agp_chipsets[i].gmch_chip_id == 0) || + find_gmch(intel_agp_chipsets[i].gmch_chip_id))) + break; + } + + if (intel_agp_chipsets[i].name == NULL) { if (cap_ptr) - printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n", - pdev->device); + printk(KERN_WARNING PFX "Unsupported Intel chipset" + "(device id: %04x)\n", pdev->device); agp_put_bridge(bridge); return -ENODEV; - }; + } + + if (intel_agp_chipsets[i].gmch_chip_id != 0) + bridge->driver = intel_agp_chipsets[i].gmch_driver; + else + bridge->driver = intel_agp_chipsets[i].driver; + + if (bridge->driver == NULL) { + printk(KERN_WARNING PFX "Failed to find bridge device " + "(chip_id: %04x)\n", intel_agp_chipsets[i].gmch_chip_id); + agp_put_bridge(bridge); + return -ENODEV; + } bridge->dev = pdev; bridge->capndx = cap_ptr; + bridge->dev_private_data = &intel_private; - if (bridge->driver == &intel_810_driver) - bridge->dev_private_data = &intel_i810_private; - else if (bridge->driver == &intel_830_driver) - bridge->dev_private_data = &intel_i830_private; - - printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); + printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", + intel_agp_chipsets[i].name); /* * The following fixes the case where the BIOS has "forgotten" to @@ -1988,12 +1959,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); - -fail: - printk(KERN_ERR PFX "Detected an Intel %s chipset, " - "but could not find the secondary device.\n", name); - agp_put_bridge(bridge); - return -ENODEV; } static void __devexit agp_intel_remove(struct pci_dev *pdev) @@ -2002,10 +1967,8 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) agp_remove_bridge(bridge); - if (intel_i810_private.i810_dev) - pci_dev_put(intel_i810_private.i810_dev); - if (intel_i830_private.i830_dev) - pci_dev_put(intel_i830_private.i830_dev); + if (intel_private.pcidev) + pci_dev_put(intel_private.pcidev); agp_put_bridge(bridge); } @@ -2021,10 +1984,8 @@ static int agp_intel_resume(struct pci_dev *pdev) * as host bridge (00:00) resumes before graphics device (02:00), * then our access to its pci space can work right. */ - if (intel_i810_private.i810_dev) - pci_restore_state(intel_i810_private.i810_dev); - if (intel_i830_private.i830_dev) - pci_restore_state(intel_i830_private.i830_dev); + if (intel_private.pcidev) + pci_restore_state(intel_private.pcidev); if (bridge->driver == &intel_generic_driver) intel_configure(); @@ -2087,6 +2048,9 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82965Q_HB), ID(PCI_DEVICE_ID_INTEL_82965G_HB), ID(PCI_DEVICE_ID_INTEL_82965GM_HB), + ID(PCI_DEVICE_ID_INTEL_G33_HB), + ID(PCI_DEVICE_ID_INTEL_Q35_HB), + ID(PCI_DEVICE_ID_INTEL_Q33_HB), { } }; |