1f51b7662SDaniel Vetter /* 2f51b7662SDaniel Vetter * Intel GTT (Graphics Translation Table) routines 3f51b7662SDaniel Vetter * 4f51b7662SDaniel Vetter * Caveat: This driver implements the linux agp interface, but this is far from 5f51b7662SDaniel Vetter * a agp driver! GTT support ended up here for purely historical reasons: The 6f51b7662SDaniel Vetter * old userspace intel graphics drivers needed an interface to map memory into 7f51b7662SDaniel Vetter * the GTT. And the drm provides a default interface for graphic devices sitting 8f51b7662SDaniel Vetter * on an agp port. So it made sense to fake the GTT support as an agp port to 9f51b7662SDaniel Vetter * avoid having to create a new api. 10f51b7662SDaniel Vetter * 11f51b7662SDaniel Vetter * With gem this does not make much sense anymore, just needlessly complicates 12f51b7662SDaniel Vetter * the code. But as long as the old graphics stack is still support, it's stuck 13f51b7662SDaniel Vetter * here. 14f51b7662SDaniel Vetter * 15f51b7662SDaniel Vetter * /fairy-tale-mode off 16f51b7662SDaniel Vetter */ 17f51b7662SDaniel Vetter 18e2404e7cSDaniel Vetter #include <linux/module.h> 19e2404e7cSDaniel Vetter #include <linux/pci.h> 20e2404e7cSDaniel Vetter #include <linux/init.h> 21e2404e7cSDaniel Vetter #include <linux/kernel.h> 22e2404e7cSDaniel Vetter #include <linux/pagemap.h> 23e2404e7cSDaniel Vetter #include <linux/agp_backend.h> 24e2404e7cSDaniel Vetter #include <asm/smp.h> 25e2404e7cSDaniel Vetter #include "agp.h" 26e2404e7cSDaniel Vetter #include "intel-agp.h" 27e2404e7cSDaniel Vetter #include <linux/intel-gtt.h> 280ade6386SDaniel Vetter #include <drm/intel-gtt.h> 29e2404e7cSDaniel Vetter 30f51b7662SDaniel Vetter /* 31f51b7662SDaniel Vetter * If we have Intel graphics, we're not going to have anything other than 32f51b7662SDaniel Vetter * an Intel IOMMU. So make the correct use of the PCI DMA API contingent 33f51b7662SDaniel Vetter * on the Intel IOMMU support (CONFIG_DMAR). 34f51b7662SDaniel Vetter * Only newer chipsets need to bother with this, of course. 35f51b7662SDaniel Vetter */ 36f51b7662SDaniel Vetter #ifdef CONFIG_DMAR 37f51b7662SDaniel Vetter #define USE_PCI_DMA_API 1 38f51b7662SDaniel Vetter #endif 39f51b7662SDaniel Vetter 40d1d6ca73SJesse Barnes /* Max amount of stolen space, anything above will be returned to Linux */ 41d1d6ca73SJesse Barnes int intel_max_stolen = 32 * 1024 * 1024; 42d1d6ca73SJesse Barnes EXPORT_SYMBOL(intel_max_stolen); 43d1d6ca73SJesse Barnes 44f51b7662SDaniel Vetter static const struct aper_size_info_fixed intel_i810_sizes[] = 45f51b7662SDaniel Vetter { 46f51b7662SDaniel Vetter {64, 16384, 4}, 47f51b7662SDaniel Vetter /* The 32M mode still requires a 64k gatt */ 48f51b7662SDaniel Vetter {32, 8192, 4} 49f51b7662SDaniel Vetter }; 50f51b7662SDaniel Vetter 51f51b7662SDaniel Vetter #define AGP_DCACHE_MEMORY 1 52f51b7662SDaniel Vetter #define AGP_PHYS_MEMORY 2 53f51b7662SDaniel Vetter #define INTEL_AGP_CACHED_MEMORY 3 54f51b7662SDaniel Vetter 55f51b7662SDaniel Vetter static struct gatt_mask intel_i810_masks[] = 56f51b7662SDaniel Vetter { 57f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 58f51b7662SDaniel Vetter {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, 59f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 60f51b7662SDaniel Vetter {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, 61f51b7662SDaniel Vetter .type = INTEL_AGP_CACHED_MEMORY} 62f51b7662SDaniel Vetter }; 63f51b7662SDaniel Vetter 64f8f235e5SZhenyu Wang #define INTEL_AGP_UNCACHED_MEMORY 0 65f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC 1 66f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 67f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 68f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 69f8f235e5SZhenyu Wang 70f8f235e5SZhenyu Wang static struct gatt_mask intel_gen6_masks[] = 71f8f235e5SZhenyu Wang { 72f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, 73f8f235e5SZhenyu Wang .type = INTEL_AGP_UNCACHED_MEMORY }, 74f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC, 75f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC }, 76f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, 77f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, 78f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, 79f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, 80f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, 81f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, 82f8f235e5SZhenyu Wang }; 83f8f235e5SZhenyu Wang 841a997ff2SDaniel Vetter struct intel_gtt_driver { 851a997ff2SDaniel Vetter unsigned int gen : 8; 861a997ff2SDaniel Vetter unsigned int is_g33 : 1; 871a997ff2SDaniel Vetter unsigned int is_pineview : 1; 881a997ff2SDaniel Vetter unsigned int is_ironlake : 1; 891a997ff2SDaniel Vetter }; 901a997ff2SDaniel Vetter 91f51b7662SDaniel Vetter static struct _intel_private { 920ade6386SDaniel Vetter struct intel_gtt base; 931a997ff2SDaniel Vetter const struct intel_gtt_driver *driver; 94f51b7662SDaniel Vetter struct pci_dev *pcidev; /* device one */ 95d7cca2f7SDaniel Vetter struct pci_dev *bridge_dev; 96f51b7662SDaniel Vetter u8 __iomem *registers; 97f51b7662SDaniel Vetter u32 __iomem *gtt; /* I915G */ 98f51b7662SDaniel Vetter int num_dcache_entries; 99f51b7662SDaniel Vetter union { 100f51b7662SDaniel Vetter void __iomem *i9xx_flush_page; 101f51b7662SDaniel Vetter void *i8xx_flush_page; 102f51b7662SDaniel Vetter }; 103f51b7662SDaniel Vetter struct page *i8xx_page; 104f51b7662SDaniel Vetter struct resource ifp_resource; 105f51b7662SDaniel Vetter int resource_valid; 106f51b7662SDaniel Vetter } intel_private; 107f51b7662SDaniel Vetter 1081a997ff2SDaniel Vetter #define INTEL_GTT_GEN intel_private.driver->gen 1091a997ff2SDaniel Vetter #define IS_G33 intel_private.driver->is_g33 1101a997ff2SDaniel Vetter #define IS_PINEVIEW intel_private.driver->is_pineview 1111a997ff2SDaniel Vetter #define IS_IRONLAKE intel_private.driver->is_ironlake 1121a997ff2SDaniel Vetter 113f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 114f51b7662SDaniel Vetter static int intel_agp_map_page(struct page *page, dma_addr_t *ret) 115f51b7662SDaniel Vetter { 116f51b7662SDaniel Vetter *ret = pci_map_page(intel_private.pcidev, page, 0, 117f51b7662SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 118f51b7662SDaniel Vetter if (pci_dma_mapping_error(intel_private.pcidev, *ret)) 119f51b7662SDaniel Vetter return -EINVAL; 120f51b7662SDaniel Vetter return 0; 121f51b7662SDaniel Vetter } 122f51b7662SDaniel Vetter 123f51b7662SDaniel Vetter static void intel_agp_unmap_page(struct page *page, dma_addr_t dma) 124f51b7662SDaniel Vetter { 125f51b7662SDaniel Vetter pci_unmap_page(intel_private.pcidev, dma, 126f51b7662SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 127f51b7662SDaniel Vetter } 128f51b7662SDaniel Vetter 129f51b7662SDaniel Vetter static void intel_agp_free_sglist(struct agp_memory *mem) 130f51b7662SDaniel Vetter { 131f51b7662SDaniel Vetter struct sg_table st; 132f51b7662SDaniel Vetter 133f51b7662SDaniel Vetter st.sgl = mem->sg_list; 134f51b7662SDaniel Vetter st.orig_nents = st.nents = mem->page_count; 135f51b7662SDaniel Vetter 136f51b7662SDaniel Vetter sg_free_table(&st); 137f51b7662SDaniel Vetter 138f51b7662SDaniel Vetter mem->sg_list = NULL; 139f51b7662SDaniel Vetter mem->num_sg = 0; 140f51b7662SDaniel Vetter } 141f51b7662SDaniel Vetter 142f51b7662SDaniel Vetter static int intel_agp_map_memory(struct agp_memory *mem) 143f51b7662SDaniel Vetter { 144f51b7662SDaniel Vetter struct sg_table st; 145f51b7662SDaniel Vetter struct scatterlist *sg; 146f51b7662SDaniel Vetter int i; 147f51b7662SDaniel Vetter 148f51b7662SDaniel Vetter DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); 149f51b7662SDaniel Vetter 150f51b7662SDaniel Vetter if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) 151831cd445SChris Wilson goto err; 152f51b7662SDaniel Vetter 153f51b7662SDaniel Vetter mem->sg_list = sg = st.sgl; 154f51b7662SDaniel Vetter 155f51b7662SDaniel Vetter for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) 156f51b7662SDaniel Vetter sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); 157f51b7662SDaniel Vetter 158f51b7662SDaniel Vetter mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, 159f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 160831cd445SChris Wilson if (unlikely(!mem->num_sg)) 161831cd445SChris Wilson goto err; 162831cd445SChris Wilson 163f51b7662SDaniel Vetter return 0; 164831cd445SChris Wilson 165831cd445SChris Wilson err: 166831cd445SChris Wilson sg_free_table(&st); 167831cd445SChris Wilson return -ENOMEM; 168f51b7662SDaniel Vetter } 169f51b7662SDaniel Vetter 170f51b7662SDaniel Vetter static void intel_agp_unmap_memory(struct agp_memory *mem) 171f51b7662SDaniel Vetter { 172f51b7662SDaniel Vetter DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); 173f51b7662SDaniel Vetter 174f51b7662SDaniel Vetter pci_unmap_sg(intel_private.pcidev, mem->sg_list, 175f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 176f51b7662SDaniel Vetter intel_agp_free_sglist(mem); 177f51b7662SDaniel Vetter } 178f51b7662SDaniel Vetter 179f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 180f51b7662SDaniel Vetter off_t pg_start, int mask_type) 181f51b7662SDaniel Vetter { 182f51b7662SDaniel Vetter struct scatterlist *sg; 183f51b7662SDaniel Vetter int i, j; 184f51b7662SDaniel Vetter 185f51b7662SDaniel Vetter j = pg_start; 186f51b7662SDaniel Vetter 187f51b7662SDaniel Vetter WARN_ON(!mem->num_sg); 188f51b7662SDaniel Vetter 189f51b7662SDaniel Vetter if (mem->num_sg == mem->page_count) { 190f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->page_count, i) { 191f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 192f51b7662SDaniel Vetter sg_dma_address(sg), mask_type), 193f51b7662SDaniel Vetter intel_private.gtt+j); 194f51b7662SDaniel Vetter j++; 195f51b7662SDaniel Vetter } 196f51b7662SDaniel Vetter } else { 197f51b7662SDaniel Vetter /* sg may merge pages, but we have to separate 198f51b7662SDaniel Vetter * per-page addr for GTT */ 199f51b7662SDaniel Vetter unsigned int len, m; 200f51b7662SDaniel Vetter 201f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->num_sg, i) { 202f51b7662SDaniel Vetter len = sg_dma_len(sg) / PAGE_SIZE; 203f51b7662SDaniel Vetter for (m = 0; m < len; m++) { 204f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 205f51b7662SDaniel Vetter sg_dma_address(sg) + m * PAGE_SIZE, 206f51b7662SDaniel Vetter mask_type), 207f51b7662SDaniel Vetter intel_private.gtt+j); 208f51b7662SDaniel Vetter j++; 209f51b7662SDaniel Vetter } 210f51b7662SDaniel Vetter } 211f51b7662SDaniel Vetter } 212f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 213f51b7662SDaniel Vetter } 214f51b7662SDaniel Vetter 215f51b7662SDaniel Vetter #else 216f51b7662SDaniel Vetter 217f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 218f51b7662SDaniel Vetter off_t pg_start, int mask_type) 219f51b7662SDaniel Vetter { 220f51b7662SDaniel Vetter int i, j; 221f51b7662SDaniel Vetter 222f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 223f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 224f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 225f51b7662SDaniel Vetter intel_private.gtt+j); 226f51b7662SDaniel Vetter } 227f51b7662SDaniel Vetter 228f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 229f51b7662SDaniel Vetter } 230f51b7662SDaniel Vetter 231f51b7662SDaniel Vetter #endif 232f51b7662SDaniel Vetter 233f51b7662SDaniel Vetter static int intel_i810_fetch_size(void) 234f51b7662SDaniel Vetter { 235f51b7662SDaniel Vetter u32 smram_miscc; 236f51b7662SDaniel Vetter struct aper_size_info_fixed *values; 237f51b7662SDaniel Vetter 238d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, 239d7cca2f7SDaniel Vetter I810_SMRAM_MISCC, &smram_miscc); 240f51b7662SDaniel Vetter values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); 241f51b7662SDaniel Vetter 242f51b7662SDaniel Vetter if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { 243d7cca2f7SDaniel Vetter dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n"); 244f51b7662SDaniel Vetter return 0; 245f51b7662SDaniel Vetter } 246f51b7662SDaniel Vetter if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { 247f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values + 1); 248f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 1; 249f51b7662SDaniel Vetter return values[1].size; 250f51b7662SDaniel Vetter } else { 251f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values); 252f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 0; 253f51b7662SDaniel Vetter return values[0].size; 254f51b7662SDaniel Vetter } 255f51b7662SDaniel Vetter 256f51b7662SDaniel Vetter return 0; 257f51b7662SDaniel Vetter } 258f51b7662SDaniel Vetter 259f51b7662SDaniel Vetter static int intel_i810_configure(void) 260f51b7662SDaniel Vetter { 261f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 262f51b7662SDaniel Vetter u32 temp; 263f51b7662SDaniel Vetter int i; 264f51b7662SDaniel Vetter 265f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 266f51b7662SDaniel Vetter 267f51b7662SDaniel Vetter if (!intel_private.registers) { 268f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); 269f51b7662SDaniel Vetter temp &= 0xfff80000; 270f51b7662SDaniel Vetter 271f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 272f51b7662SDaniel Vetter if (!intel_private.registers) { 273f51b7662SDaniel Vetter dev_err(&intel_private.pcidev->dev, 274f51b7662SDaniel Vetter "can't remap memory\n"); 275f51b7662SDaniel Vetter return -ENOMEM; 276f51b7662SDaniel Vetter } 277f51b7662SDaniel Vetter } 278f51b7662SDaniel Vetter 279f51b7662SDaniel Vetter if ((readl(intel_private.registers+I810_DRAM_CTL) 280f51b7662SDaniel Vetter & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { 281f51b7662SDaniel Vetter /* This will need to be dynamically assigned */ 282f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 283f51b7662SDaniel Vetter "detected 4MB dedicated video ram\n"); 284f51b7662SDaniel Vetter intel_private.num_dcache_entries = 1024; 285f51b7662SDaniel Vetter } 286f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); 287f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 288f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 289f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 290f51b7662SDaniel Vetter 291f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 292f51b7662SDaniel Vetter for (i = 0; i < current_size->num_entries; i++) { 293f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 294f51b7662SDaniel Vetter } 295f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ 296f51b7662SDaniel Vetter } 297f51b7662SDaniel Vetter global_cache_flush(); 298f51b7662SDaniel Vetter return 0; 299f51b7662SDaniel Vetter } 300f51b7662SDaniel Vetter 301f51b7662SDaniel Vetter static void intel_i810_cleanup(void) 302f51b7662SDaniel Vetter { 303f51b7662SDaniel Vetter writel(0, intel_private.registers+I810_PGETBL_CTL); 304f51b7662SDaniel Vetter readl(intel_private.registers); /* PCI Posting. */ 305f51b7662SDaniel Vetter iounmap(intel_private.registers); 306f51b7662SDaniel Vetter } 307f51b7662SDaniel Vetter 308ffdd7510SDaniel Vetter static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) 309f51b7662SDaniel Vetter { 310f51b7662SDaniel Vetter return; 311f51b7662SDaniel Vetter } 312f51b7662SDaniel Vetter 313f51b7662SDaniel Vetter /* Exists to support ARGB cursors */ 314f51b7662SDaniel Vetter static struct page *i8xx_alloc_pages(void) 315f51b7662SDaniel Vetter { 316f51b7662SDaniel Vetter struct page *page; 317f51b7662SDaniel Vetter 318f51b7662SDaniel Vetter page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); 319f51b7662SDaniel Vetter if (page == NULL) 320f51b7662SDaniel Vetter return NULL; 321f51b7662SDaniel Vetter 322f51b7662SDaniel Vetter if (set_pages_uc(page, 4) < 0) { 323f51b7662SDaniel Vetter set_pages_wb(page, 4); 324f51b7662SDaniel Vetter __free_pages(page, 2); 325f51b7662SDaniel Vetter return NULL; 326f51b7662SDaniel Vetter } 327f51b7662SDaniel Vetter get_page(page); 328f51b7662SDaniel Vetter atomic_inc(&agp_bridge->current_memory_agp); 329f51b7662SDaniel Vetter return page; 330f51b7662SDaniel Vetter } 331f51b7662SDaniel Vetter 332f51b7662SDaniel Vetter static void i8xx_destroy_pages(struct page *page) 333f51b7662SDaniel Vetter { 334f51b7662SDaniel Vetter if (page == NULL) 335f51b7662SDaniel Vetter return; 336f51b7662SDaniel Vetter 337f51b7662SDaniel Vetter set_pages_wb(page, 4); 338f51b7662SDaniel Vetter put_page(page); 339f51b7662SDaniel Vetter __free_pages(page, 2); 340f51b7662SDaniel Vetter atomic_dec(&agp_bridge->current_memory_agp); 341f51b7662SDaniel Vetter } 342f51b7662SDaniel Vetter 343f51b7662SDaniel Vetter static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, 344f51b7662SDaniel Vetter int type) 345f51b7662SDaniel Vetter { 346f51b7662SDaniel Vetter if (type < AGP_USER_TYPES) 347f51b7662SDaniel Vetter return type; 348f51b7662SDaniel Vetter else if (type == AGP_USER_CACHED_MEMORY) 349f51b7662SDaniel Vetter return INTEL_AGP_CACHED_MEMORY; 350f51b7662SDaniel Vetter else 351f51b7662SDaniel Vetter return 0; 352f51b7662SDaniel Vetter } 353f51b7662SDaniel Vetter 354f8f235e5SZhenyu Wang static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, 355f8f235e5SZhenyu Wang int type) 356f8f235e5SZhenyu Wang { 357f8f235e5SZhenyu Wang unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; 358f8f235e5SZhenyu Wang unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; 359f8f235e5SZhenyu Wang 360f8f235e5SZhenyu Wang if (type_mask == AGP_USER_UNCACHED_MEMORY) 361f8f235e5SZhenyu Wang return INTEL_AGP_UNCACHED_MEMORY; 362f8f235e5SZhenyu Wang else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) 363f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : 364f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC_MLC; 365f8f235e5SZhenyu Wang else /* set 'normal'/'cached' to LLC by default */ 366f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : 367f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC; 368f8f235e5SZhenyu Wang } 369f8f235e5SZhenyu Wang 370f8f235e5SZhenyu Wang 371f51b7662SDaniel Vetter static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, 372f51b7662SDaniel Vetter int type) 373f51b7662SDaniel Vetter { 374f51b7662SDaniel Vetter int i, j, num_entries; 375f51b7662SDaniel Vetter void *temp; 376f51b7662SDaniel Vetter int ret = -EINVAL; 377f51b7662SDaniel Vetter int mask_type; 378f51b7662SDaniel Vetter 379f51b7662SDaniel Vetter if (mem->page_count == 0) 380f51b7662SDaniel Vetter goto out; 381f51b7662SDaniel Vetter 382f51b7662SDaniel Vetter temp = agp_bridge->current_size; 383f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 384f51b7662SDaniel Vetter 385f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 386f51b7662SDaniel Vetter goto out_err; 387f51b7662SDaniel Vetter 388f51b7662SDaniel Vetter 389f51b7662SDaniel Vetter for (j = pg_start; j < (pg_start + mem->page_count); j++) { 390f51b7662SDaniel Vetter if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { 391f51b7662SDaniel Vetter ret = -EBUSY; 392f51b7662SDaniel Vetter goto out_err; 393f51b7662SDaniel Vetter } 394f51b7662SDaniel Vetter } 395f51b7662SDaniel Vetter 396f51b7662SDaniel Vetter if (type != mem->type) 397f51b7662SDaniel Vetter goto out_err; 398f51b7662SDaniel Vetter 399f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 400f51b7662SDaniel Vetter 401f51b7662SDaniel Vetter switch (mask_type) { 402f51b7662SDaniel Vetter case AGP_DCACHE_MEMORY: 403f51b7662SDaniel Vetter if (!mem->is_flushed) 404f51b7662SDaniel Vetter global_cache_flush(); 405f51b7662SDaniel Vetter for (i = pg_start; i < (pg_start + mem->page_count); i++) { 406f51b7662SDaniel Vetter writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, 407f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(i*4)); 408f51b7662SDaniel Vetter } 409f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 410f51b7662SDaniel Vetter break; 411f51b7662SDaniel Vetter case AGP_PHYS_MEMORY: 412f51b7662SDaniel Vetter case AGP_NORMAL_MEMORY: 413f51b7662SDaniel Vetter if (!mem->is_flushed) 414f51b7662SDaniel Vetter global_cache_flush(); 415f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 416f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 417f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 418f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(j*4)); 419f51b7662SDaniel Vetter } 420f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 421f51b7662SDaniel Vetter break; 422f51b7662SDaniel Vetter default: 423f51b7662SDaniel Vetter goto out_err; 424f51b7662SDaniel Vetter } 425f51b7662SDaniel Vetter 426f51b7662SDaniel Vetter out: 427f51b7662SDaniel Vetter ret = 0; 428f51b7662SDaniel Vetter out_err: 429f51b7662SDaniel Vetter mem->is_flushed = true; 430f51b7662SDaniel Vetter return ret; 431f51b7662SDaniel Vetter } 432f51b7662SDaniel Vetter 433f51b7662SDaniel Vetter static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, 434f51b7662SDaniel Vetter int type) 435f51b7662SDaniel Vetter { 436f51b7662SDaniel Vetter int i; 437f51b7662SDaniel Vetter 438f51b7662SDaniel Vetter if (mem->page_count == 0) 439f51b7662SDaniel Vetter return 0; 440f51b7662SDaniel Vetter 441f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 442f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 443f51b7662SDaniel Vetter } 444f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 445f51b7662SDaniel Vetter 446f51b7662SDaniel Vetter return 0; 447f51b7662SDaniel Vetter } 448f51b7662SDaniel Vetter 449f51b7662SDaniel Vetter /* 450f51b7662SDaniel Vetter * The i810/i830 requires a physical address to program its mouse 451f51b7662SDaniel Vetter * pointer into hardware. 452f51b7662SDaniel Vetter * However the Xserver still writes to it through the agp aperture. 453f51b7662SDaniel Vetter */ 454f51b7662SDaniel Vetter static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) 455f51b7662SDaniel Vetter { 456f51b7662SDaniel Vetter struct agp_memory *new; 457f51b7662SDaniel Vetter struct page *page; 458f51b7662SDaniel Vetter 459f51b7662SDaniel Vetter switch (pg_count) { 460f51b7662SDaniel Vetter case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); 461f51b7662SDaniel Vetter break; 462f51b7662SDaniel Vetter case 4: 463f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 464f51b7662SDaniel Vetter page = i8xx_alloc_pages(); 465f51b7662SDaniel Vetter break; 466f51b7662SDaniel Vetter default: 467f51b7662SDaniel Vetter return NULL; 468f51b7662SDaniel Vetter } 469f51b7662SDaniel Vetter 470f51b7662SDaniel Vetter if (page == NULL) 471f51b7662SDaniel Vetter return NULL; 472f51b7662SDaniel Vetter 473f51b7662SDaniel Vetter new = agp_create_memory(pg_count); 474f51b7662SDaniel Vetter if (new == NULL) 475f51b7662SDaniel Vetter return NULL; 476f51b7662SDaniel Vetter 477f51b7662SDaniel Vetter new->pages[0] = page; 478f51b7662SDaniel Vetter if (pg_count == 4) { 479f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 480f51b7662SDaniel Vetter new->pages[1] = new->pages[0] + 1; 481f51b7662SDaniel Vetter new->pages[2] = new->pages[1] + 1; 482f51b7662SDaniel Vetter new->pages[3] = new->pages[2] + 1; 483f51b7662SDaniel Vetter } 484f51b7662SDaniel Vetter new->page_count = pg_count; 485f51b7662SDaniel Vetter new->num_scratch_pages = pg_count; 486f51b7662SDaniel Vetter new->type = AGP_PHYS_MEMORY; 487f51b7662SDaniel Vetter new->physical = page_to_phys(new->pages[0]); 488f51b7662SDaniel Vetter return new; 489f51b7662SDaniel Vetter } 490f51b7662SDaniel Vetter 491f51b7662SDaniel Vetter static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) 492f51b7662SDaniel Vetter { 493f51b7662SDaniel Vetter struct agp_memory *new; 494f51b7662SDaniel Vetter 495f51b7662SDaniel Vetter if (type == AGP_DCACHE_MEMORY) { 496f51b7662SDaniel Vetter if (pg_count != intel_private.num_dcache_entries) 497f51b7662SDaniel Vetter return NULL; 498f51b7662SDaniel Vetter 499f51b7662SDaniel Vetter new = agp_create_memory(1); 500f51b7662SDaniel Vetter if (new == NULL) 501f51b7662SDaniel Vetter return NULL; 502f51b7662SDaniel Vetter 503f51b7662SDaniel Vetter new->type = AGP_DCACHE_MEMORY; 504f51b7662SDaniel Vetter new->page_count = pg_count; 505f51b7662SDaniel Vetter new->num_scratch_pages = 0; 506f51b7662SDaniel Vetter agp_free_page_array(new); 507f51b7662SDaniel Vetter return new; 508f51b7662SDaniel Vetter } 509f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 510f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 511f51b7662SDaniel Vetter return NULL; 512f51b7662SDaniel Vetter } 513f51b7662SDaniel Vetter 514f51b7662SDaniel Vetter static void intel_i810_free_by_type(struct agp_memory *curr) 515f51b7662SDaniel Vetter { 516f51b7662SDaniel Vetter agp_free_key(curr->key); 517f51b7662SDaniel Vetter if (curr->type == AGP_PHYS_MEMORY) { 518f51b7662SDaniel Vetter if (curr->page_count == 4) 519f51b7662SDaniel Vetter i8xx_destroy_pages(curr->pages[0]); 520f51b7662SDaniel Vetter else { 521f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 522f51b7662SDaniel Vetter AGP_PAGE_DESTROY_UNMAP); 523f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 524f51b7662SDaniel Vetter AGP_PAGE_DESTROY_FREE); 525f51b7662SDaniel Vetter } 526f51b7662SDaniel Vetter agp_free_page_array(curr); 527f51b7662SDaniel Vetter } 528f51b7662SDaniel Vetter kfree(curr); 529f51b7662SDaniel Vetter } 530f51b7662SDaniel Vetter 531f51b7662SDaniel Vetter static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, 532f51b7662SDaniel Vetter dma_addr_t addr, int type) 533f51b7662SDaniel Vetter { 534f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 535f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 536f51b7662SDaniel Vetter } 537f51b7662SDaniel Vetter 538ffdd7510SDaniel Vetter static struct aper_size_info_fixed intel_fake_agp_sizes[] = 539f51b7662SDaniel Vetter { 540f51b7662SDaniel Vetter {128, 32768, 5}, 541f51b7662SDaniel Vetter /* The 64M mode still requires a 128k gatt */ 542f51b7662SDaniel Vetter {64, 16384, 5}, 543f51b7662SDaniel Vetter {256, 65536, 6}, 544f51b7662SDaniel Vetter {512, 131072, 7}, 545f51b7662SDaniel Vetter }; 546f51b7662SDaniel Vetter 547bfde067bSDaniel Vetter static unsigned int intel_gtt_stolen_entries(void) 548f51b7662SDaniel Vetter { 549f51b7662SDaniel Vetter u16 gmch_ctrl; 550f51b7662SDaniel Vetter u8 rdct; 551f51b7662SDaniel Vetter int local = 0; 552f51b7662SDaniel Vetter static const int ddt[4] = { 0, 16, 32, 64 }; 553d8d9abcdSDaniel Vetter unsigned int overhead_entries, stolen_entries; 554d8d9abcdSDaniel Vetter unsigned int stolen_size = 0; 555f51b7662SDaniel Vetter 556d7cca2f7SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 557d7cca2f7SDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 558f51b7662SDaniel Vetter 5591a997ff2SDaniel Vetter if (INTEL_GTT_GEN > 4 || IS_PINEVIEW) 560fbe40783SDaniel Vetter overhead_entries = 0; 561fbe40783SDaniel Vetter else 562fbe40783SDaniel Vetter overhead_entries = intel_private.base.gtt_mappable_entries 563fbe40783SDaniel Vetter / 1024; 564f51b7662SDaniel Vetter 565fbe40783SDaniel Vetter overhead_entries += 1; /* BIOS popup */ 566d8d9abcdSDaniel Vetter 567d7cca2f7SDaniel Vetter if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || 568d7cca2f7SDaniel Vetter intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { 569f51b7662SDaniel Vetter switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 570f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_512: 571d8d9abcdSDaniel Vetter stolen_size = KB(512); 572f51b7662SDaniel Vetter break; 573f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_1024: 574d8d9abcdSDaniel Vetter stolen_size = MB(1); 575f51b7662SDaniel Vetter break; 576f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_8192: 577d8d9abcdSDaniel Vetter stolen_size = MB(8); 578f51b7662SDaniel Vetter break; 579f51b7662SDaniel Vetter case I830_GMCH_GMS_LOCAL: 580f51b7662SDaniel Vetter rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); 581d8d9abcdSDaniel Vetter stolen_size = (I830_RDRAM_ND(rdct) + 1) * 582f51b7662SDaniel Vetter MB(ddt[I830_RDRAM_DDT(rdct)]); 583f51b7662SDaniel Vetter local = 1; 584f51b7662SDaniel Vetter break; 585f51b7662SDaniel Vetter default: 586d8d9abcdSDaniel Vetter stolen_size = 0; 587f51b7662SDaniel Vetter break; 588f51b7662SDaniel Vetter } 5891a997ff2SDaniel Vetter } else if (INTEL_GTT_GEN == 6) { 590f51b7662SDaniel Vetter /* 591f51b7662SDaniel Vetter * SandyBridge has new memory control reg at 0x50.w 592f51b7662SDaniel Vetter */ 593f51b7662SDaniel Vetter u16 snb_gmch_ctl; 594f51b7662SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 595f51b7662SDaniel Vetter switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { 596f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_32M: 597d8d9abcdSDaniel Vetter stolen_size = MB(32); 598f51b7662SDaniel Vetter break; 599f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_64M: 600d8d9abcdSDaniel Vetter stolen_size = MB(64); 601f51b7662SDaniel Vetter break; 602f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_96M: 603d8d9abcdSDaniel Vetter stolen_size = MB(96); 604f51b7662SDaniel Vetter break; 605f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_128M: 606d8d9abcdSDaniel Vetter stolen_size = MB(128); 607f51b7662SDaniel Vetter break; 608f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_160M: 609d8d9abcdSDaniel Vetter stolen_size = MB(160); 610f51b7662SDaniel Vetter break; 611f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_192M: 612d8d9abcdSDaniel Vetter stolen_size = MB(192); 613f51b7662SDaniel Vetter break; 614f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_224M: 615d8d9abcdSDaniel Vetter stolen_size = MB(224); 616f51b7662SDaniel Vetter break; 617f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_256M: 618d8d9abcdSDaniel Vetter stolen_size = MB(256); 619f51b7662SDaniel Vetter break; 620f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_288M: 621d8d9abcdSDaniel Vetter stolen_size = MB(288); 622f51b7662SDaniel Vetter break; 623f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_320M: 624d8d9abcdSDaniel Vetter stolen_size = MB(320); 625f51b7662SDaniel Vetter break; 626f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_352M: 627d8d9abcdSDaniel Vetter stolen_size = MB(352); 628f51b7662SDaniel Vetter break; 629f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_384M: 630d8d9abcdSDaniel Vetter stolen_size = MB(384); 631f51b7662SDaniel Vetter break; 632f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_416M: 633d8d9abcdSDaniel Vetter stolen_size = MB(416); 634f51b7662SDaniel Vetter break; 635f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_448M: 636d8d9abcdSDaniel Vetter stolen_size = MB(448); 637f51b7662SDaniel Vetter break; 638f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_480M: 639d8d9abcdSDaniel Vetter stolen_size = MB(480); 640f51b7662SDaniel Vetter break; 641f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_512M: 642d8d9abcdSDaniel Vetter stolen_size = MB(512); 643f51b7662SDaniel Vetter break; 644f51b7662SDaniel Vetter } 645f51b7662SDaniel Vetter } else { 646f51b7662SDaniel Vetter switch (gmch_ctrl & I855_GMCH_GMS_MASK) { 647f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_1M: 648d8d9abcdSDaniel Vetter stolen_size = MB(1); 649f51b7662SDaniel Vetter break; 650f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_4M: 651d8d9abcdSDaniel Vetter stolen_size = MB(4); 652f51b7662SDaniel Vetter break; 653f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_8M: 654d8d9abcdSDaniel Vetter stolen_size = MB(8); 655f51b7662SDaniel Vetter break; 656f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_16M: 657d8d9abcdSDaniel Vetter stolen_size = MB(16); 658f51b7662SDaniel Vetter break; 659f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_32M: 660d8d9abcdSDaniel Vetter stolen_size = MB(32); 661f51b7662SDaniel Vetter break; 662f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_48M: 663d8d9abcdSDaniel Vetter stolen_size = MB(48); 664f51b7662SDaniel Vetter break; 665f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_64M: 666d8d9abcdSDaniel Vetter stolen_size = MB(64); 667f51b7662SDaniel Vetter break; 668f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_128M: 669d8d9abcdSDaniel Vetter stolen_size = MB(128); 670f51b7662SDaniel Vetter break; 671f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_256M: 672d8d9abcdSDaniel Vetter stolen_size = MB(256); 673f51b7662SDaniel Vetter break; 674f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_96M: 675d8d9abcdSDaniel Vetter stolen_size = MB(96); 676f51b7662SDaniel Vetter break; 677f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_160M: 678d8d9abcdSDaniel Vetter stolen_size = MB(160); 679f51b7662SDaniel Vetter break; 680f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_224M: 681d8d9abcdSDaniel Vetter stolen_size = MB(224); 682f51b7662SDaniel Vetter break; 683f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_352M: 684d8d9abcdSDaniel Vetter stolen_size = MB(352); 685f51b7662SDaniel Vetter break; 686f51b7662SDaniel Vetter default: 687d8d9abcdSDaniel Vetter stolen_size = 0; 688f51b7662SDaniel Vetter break; 689f51b7662SDaniel Vetter } 690f51b7662SDaniel Vetter } 6911784a5fbSDaniel Vetter 692d8d9abcdSDaniel Vetter if (!local && stolen_size > intel_max_stolen) { 693d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 694d1d6ca73SJesse Barnes "detected %dK stolen memory, trimming to %dK\n", 695d8d9abcdSDaniel Vetter stolen_size / KB(1), intel_max_stolen / KB(1)); 696d8d9abcdSDaniel Vetter stolen_size = intel_max_stolen; 697d8d9abcdSDaniel Vetter } else if (stolen_size > 0) { 698d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", 699d8d9abcdSDaniel Vetter stolen_size / KB(1), local ? "local" : "stolen"); 700f51b7662SDaniel Vetter } else { 701d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 702f51b7662SDaniel Vetter "no pre-allocated video memory detected\n"); 703d8d9abcdSDaniel Vetter stolen_size = 0; 704f51b7662SDaniel Vetter } 705f51b7662SDaniel Vetter 706d8d9abcdSDaniel Vetter stolen_entries = stolen_size/KB(4) - overhead_entries; 707d8d9abcdSDaniel Vetter 708d8d9abcdSDaniel Vetter return stolen_entries; 709f51b7662SDaniel Vetter } 710f51b7662SDaniel Vetter 711fbe40783SDaniel Vetter static unsigned int intel_gtt_total_entries(void) 712fbe40783SDaniel Vetter { 713fbe40783SDaniel Vetter int size; 714fbe40783SDaniel Vetter 715210b23c2SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) { 716fbe40783SDaniel Vetter u32 pgetbl_ctl; 717fbe40783SDaniel Vetter pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); 718fbe40783SDaniel Vetter 719fbe40783SDaniel Vetter switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { 720fbe40783SDaniel Vetter case I965_PGETBL_SIZE_128KB: 721e5e408fcSDaniel Vetter size = KB(128); 722fbe40783SDaniel Vetter break; 723fbe40783SDaniel Vetter case I965_PGETBL_SIZE_256KB: 724e5e408fcSDaniel Vetter size = KB(256); 725fbe40783SDaniel Vetter break; 726fbe40783SDaniel Vetter case I965_PGETBL_SIZE_512KB: 727e5e408fcSDaniel Vetter size = KB(512); 728fbe40783SDaniel Vetter break; 729fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1MB: 730e5e408fcSDaniel Vetter size = KB(1024); 731fbe40783SDaniel Vetter break; 732fbe40783SDaniel Vetter case I965_PGETBL_SIZE_2MB: 733e5e408fcSDaniel Vetter size = KB(2048); 734fbe40783SDaniel Vetter break; 735fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1_5MB: 736e5e408fcSDaniel Vetter size = KB(1024 + 512); 737fbe40783SDaniel Vetter break; 738fbe40783SDaniel Vetter default: 739fbe40783SDaniel Vetter dev_info(&intel_private.pcidev->dev, 740fbe40783SDaniel Vetter "unknown page table size, assuming 512KB\n"); 741e5e408fcSDaniel Vetter size = KB(512); 742fbe40783SDaniel Vetter } 743e5e408fcSDaniel Vetter 744e5e408fcSDaniel Vetter return size/4; 745210b23c2SDaniel Vetter } else if (INTEL_GTT_GEN == 6) { 746210b23c2SDaniel Vetter u16 snb_gmch_ctl; 747210b23c2SDaniel Vetter 748210b23c2SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 749210b23c2SDaniel Vetter switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { 750210b23c2SDaniel Vetter default: 751210b23c2SDaniel Vetter case SNB_GTT_SIZE_0M: 752210b23c2SDaniel Vetter printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); 753210b23c2SDaniel Vetter size = MB(0); 754210b23c2SDaniel Vetter break; 755210b23c2SDaniel Vetter case SNB_GTT_SIZE_1M: 756210b23c2SDaniel Vetter size = MB(1); 757210b23c2SDaniel Vetter break; 758210b23c2SDaniel Vetter case SNB_GTT_SIZE_2M: 759210b23c2SDaniel Vetter size = MB(2); 760210b23c2SDaniel Vetter break; 761210b23c2SDaniel Vetter } 762210b23c2SDaniel Vetter return size/4; 763fbe40783SDaniel Vetter } else { 764fbe40783SDaniel Vetter /* On previous hardware, the GTT size was just what was 765fbe40783SDaniel Vetter * required to map the aperture. 766fbe40783SDaniel Vetter */ 767e5e408fcSDaniel Vetter return intel_private.base.gtt_mappable_entries; 768fbe40783SDaniel Vetter } 769fbe40783SDaniel Vetter } 770fbe40783SDaniel Vetter 7711784a5fbSDaniel Vetter static unsigned int intel_gtt_mappable_entries(void) 7721784a5fbSDaniel Vetter { 7731784a5fbSDaniel Vetter unsigned int aperture_size; 7741784a5fbSDaniel Vetter u16 gmch_ctrl; 7751784a5fbSDaniel Vetter 7761784a5fbSDaniel Vetter aperture_size = 1024 * 1024; 7771784a5fbSDaniel Vetter 7781784a5fbSDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 7791784a5fbSDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 7801784a5fbSDaniel Vetter 7811784a5fbSDaniel Vetter switch (intel_private.pcidev->device) { 7821784a5fbSDaniel Vetter case PCI_DEVICE_ID_INTEL_82830_CGC: 7831784a5fbSDaniel Vetter case PCI_DEVICE_ID_INTEL_82845G_IG: 7841784a5fbSDaniel Vetter case PCI_DEVICE_ID_INTEL_82855GM_IG: 7851784a5fbSDaniel Vetter case PCI_DEVICE_ID_INTEL_82865_IG: 7861784a5fbSDaniel Vetter if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M) 7871784a5fbSDaniel Vetter aperture_size *= 64; 7881784a5fbSDaniel Vetter else 7891784a5fbSDaniel Vetter aperture_size *= 128; 7901784a5fbSDaniel Vetter break; 7911784a5fbSDaniel Vetter default: 7921784a5fbSDaniel Vetter /* 9xx supports large sizes, just look at the length */ 7931784a5fbSDaniel Vetter aperture_size = pci_resource_len(intel_private.pcidev, 2); 7941784a5fbSDaniel Vetter break; 7951784a5fbSDaniel Vetter } 7961784a5fbSDaniel Vetter 7971784a5fbSDaniel Vetter return aperture_size >> PAGE_SHIFT; 7981784a5fbSDaniel Vetter } 7991784a5fbSDaniel Vetter 8001784a5fbSDaniel Vetter static int intel_gtt_init(void) 8011784a5fbSDaniel Vetter { 8021784a5fbSDaniel Vetter /* we have to call this as early as possible after the MMIO base address is known */ 8031784a5fbSDaniel Vetter intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries(); 8041784a5fbSDaniel Vetter if (intel_private.base.gtt_stolen_entries == 0) { 8051784a5fbSDaniel Vetter iounmap(intel_private.registers); 8061784a5fbSDaniel Vetter return -ENOMEM; 8071784a5fbSDaniel Vetter } 8081784a5fbSDaniel Vetter 8091784a5fbSDaniel Vetter return 0; 8101784a5fbSDaniel Vetter } 8111784a5fbSDaniel Vetter 8123e921f98SDaniel Vetter static int intel_fake_agp_fetch_size(void) 8133e921f98SDaniel Vetter { 8143e921f98SDaniel Vetter unsigned int aper_size; 8153e921f98SDaniel Vetter int i; 816ffdd7510SDaniel Vetter int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); 8173e921f98SDaniel Vetter 8183e921f98SDaniel Vetter aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) 8193e921f98SDaniel Vetter / MB(1); 8203e921f98SDaniel Vetter 8213e921f98SDaniel Vetter for (i = 0; i < num_sizes; i++) { 822ffdd7510SDaniel Vetter if (aper_size == intel_fake_agp_sizes[i].size) { 823ffdd7510SDaniel Vetter agp_bridge->current_size = intel_fake_agp_sizes + i; 8243e921f98SDaniel Vetter return aper_size; 8253e921f98SDaniel Vetter } 8263e921f98SDaniel Vetter } 8273e921f98SDaniel Vetter 8283e921f98SDaniel Vetter return 0; 8293e921f98SDaniel Vetter } 8303e921f98SDaniel Vetter 831f51b7662SDaniel Vetter static void intel_i830_fini_flush(void) 832f51b7662SDaniel Vetter { 833f51b7662SDaniel Vetter kunmap(intel_private.i8xx_page); 834f51b7662SDaniel Vetter intel_private.i8xx_flush_page = NULL; 835f51b7662SDaniel Vetter unmap_page_from_agp(intel_private.i8xx_page); 836f51b7662SDaniel Vetter 837f51b7662SDaniel Vetter __free_page(intel_private.i8xx_page); 838f51b7662SDaniel Vetter intel_private.i8xx_page = NULL; 839f51b7662SDaniel Vetter } 840f51b7662SDaniel Vetter 841f51b7662SDaniel Vetter static void intel_i830_setup_flush(void) 842f51b7662SDaniel Vetter { 843f51b7662SDaniel Vetter /* return if we've already set the flush mechanism up */ 844f51b7662SDaniel Vetter if (intel_private.i8xx_page) 845f51b7662SDaniel Vetter return; 846f51b7662SDaniel Vetter 847f51b7662SDaniel Vetter intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); 848f51b7662SDaniel Vetter if (!intel_private.i8xx_page) 849f51b7662SDaniel Vetter return; 850f51b7662SDaniel Vetter 851f51b7662SDaniel Vetter intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); 852f51b7662SDaniel Vetter if (!intel_private.i8xx_flush_page) 853f51b7662SDaniel Vetter intel_i830_fini_flush(); 854f51b7662SDaniel Vetter } 855f51b7662SDaniel Vetter 856f51b7662SDaniel Vetter /* The chipset_flush interface needs to get data that has already been 857f51b7662SDaniel Vetter * flushed out of the CPU all the way out to main memory, because the GPU 858f51b7662SDaniel Vetter * doesn't snoop those buffers. 859f51b7662SDaniel Vetter * 860f51b7662SDaniel Vetter * The 8xx series doesn't have the same lovely interface for flushing the 861f51b7662SDaniel Vetter * chipset write buffers that the later chips do. According to the 865 862f51b7662SDaniel Vetter * specs, it's 64 octwords, or 1KB. So, to get those previous things in 863f51b7662SDaniel Vetter * that buffer out, we just fill 1KB and clflush it out, on the assumption 864f51b7662SDaniel Vetter * that it'll push whatever was in there out. It appears to work. 865f51b7662SDaniel Vetter */ 866f51b7662SDaniel Vetter static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) 867f51b7662SDaniel Vetter { 868f51b7662SDaniel Vetter unsigned int *pg = intel_private.i8xx_flush_page; 869f51b7662SDaniel Vetter 870f51b7662SDaniel Vetter memset(pg, 0, 1024); 871f51b7662SDaniel Vetter 872f51b7662SDaniel Vetter if (cpu_has_clflush) 873f51b7662SDaniel Vetter clflush_cache_range(pg, 1024); 874f51b7662SDaniel Vetter else if (wbinvd_on_all_cpus() != 0) 875f51b7662SDaniel Vetter printk(KERN_ERR "Timed out waiting for cache flush.\n"); 876f51b7662SDaniel Vetter } 877f51b7662SDaniel Vetter 878f51b7662SDaniel Vetter /* The intel i830 automatically initializes the agp aperture during POST. 879f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 880f51b7662SDaniel Vetter */ 881f51b7662SDaniel Vetter static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) 882f51b7662SDaniel Vetter { 8831784a5fbSDaniel Vetter int page_order, ret; 884f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 885f51b7662SDaniel Vetter int num_entries; 886f51b7662SDaniel Vetter u32 temp; 887f51b7662SDaniel Vetter 888f51b7662SDaniel Vetter size = agp_bridge->current_size; 889f51b7662SDaniel Vetter page_order = size->page_order; 890f51b7662SDaniel Vetter num_entries = size->num_entries; 891f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 892f51b7662SDaniel Vetter 893f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); 894f51b7662SDaniel Vetter temp &= 0xfff80000; 895f51b7662SDaniel Vetter 896f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 897f51b7662SDaniel Vetter if (!intel_private.registers) 898f51b7662SDaniel Vetter return -ENOMEM; 899f51b7662SDaniel Vetter 900f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 901f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ?? */ 902f51b7662SDaniel Vetter 9031784a5fbSDaniel Vetter ret = intel_gtt_init(); 9041784a5fbSDaniel Vetter if (ret != 0) 9051784a5fbSDaniel Vetter return ret; 906f51b7662SDaniel Vetter 907f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 908f51b7662SDaniel Vetter 909f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 910f51b7662SDaniel Vetter 911f51b7662SDaniel Vetter return 0; 912f51b7662SDaniel Vetter } 913f51b7662SDaniel Vetter 914f51b7662SDaniel Vetter /* Return the gatt table to a sane state. Use the top of stolen 915f51b7662SDaniel Vetter * memory for the GTT. 916f51b7662SDaniel Vetter */ 917ffdd7510SDaniel Vetter static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) 918f51b7662SDaniel Vetter { 919f51b7662SDaniel Vetter return 0; 920f51b7662SDaniel Vetter } 921f51b7662SDaniel Vetter 922f51b7662SDaniel Vetter static int intel_i830_configure(void) 923f51b7662SDaniel Vetter { 924f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 925f51b7662SDaniel Vetter u32 temp; 926f51b7662SDaniel Vetter u16 gmch_ctrl; 927f51b7662SDaniel Vetter int i; 928f51b7662SDaniel Vetter 929f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 930f51b7662SDaniel Vetter 931f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); 932f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 933f51b7662SDaniel Vetter 934d7cca2f7SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); 935f51b7662SDaniel Vetter gmch_ctrl |= I830_GMCH_ENABLED; 936d7cca2f7SDaniel Vetter pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); 937f51b7662SDaniel Vetter 938f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 939f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 940f51b7662SDaniel Vetter 941f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 9420ade6386SDaniel Vetter for (i = intel_private.base.gtt_stolen_entries; i < current_size->num_entries; i++) { 943f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 944f51b7662SDaniel Vetter } 945f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ 946f51b7662SDaniel Vetter } 947f51b7662SDaniel Vetter 948f51b7662SDaniel Vetter global_cache_flush(); 949f51b7662SDaniel Vetter 950f51b7662SDaniel Vetter intel_i830_setup_flush(); 951f51b7662SDaniel Vetter return 0; 952f51b7662SDaniel Vetter } 953f51b7662SDaniel Vetter 954f51b7662SDaniel Vetter static void intel_i830_cleanup(void) 955f51b7662SDaniel Vetter { 956f51b7662SDaniel Vetter iounmap(intel_private.registers); 957f51b7662SDaniel Vetter } 958f51b7662SDaniel Vetter 959f51b7662SDaniel Vetter static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, 960f51b7662SDaniel Vetter int type) 961f51b7662SDaniel Vetter { 962f51b7662SDaniel Vetter int i, j, num_entries; 963f51b7662SDaniel Vetter void *temp; 964f51b7662SDaniel Vetter int ret = -EINVAL; 965f51b7662SDaniel Vetter int mask_type; 966f51b7662SDaniel Vetter 967f51b7662SDaniel Vetter if (mem->page_count == 0) 968f51b7662SDaniel Vetter goto out; 969f51b7662SDaniel Vetter 970f51b7662SDaniel Vetter temp = agp_bridge->current_size; 971f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 972f51b7662SDaniel Vetter 9730ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 974f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 9750ade6386SDaniel Vetter "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", 9760ade6386SDaniel Vetter pg_start, intel_private.base.gtt_stolen_entries); 977f51b7662SDaniel Vetter 978f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 979f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 980f51b7662SDaniel Vetter goto out_err; 981f51b7662SDaniel Vetter } 982f51b7662SDaniel Vetter 983f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 984f51b7662SDaniel Vetter goto out_err; 985f51b7662SDaniel Vetter 986f51b7662SDaniel Vetter /* The i830 can't check the GTT for entries since its read only, 987f51b7662SDaniel Vetter * depend on the caller to make the correct offset decisions. 988f51b7662SDaniel Vetter */ 989f51b7662SDaniel Vetter 990f51b7662SDaniel Vetter if (type != mem->type) 991f51b7662SDaniel Vetter goto out_err; 992f51b7662SDaniel Vetter 993f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 994f51b7662SDaniel Vetter 995f51b7662SDaniel Vetter if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && 996f51b7662SDaniel Vetter mask_type != INTEL_AGP_CACHED_MEMORY) 997f51b7662SDaniel Vetter goto out_err; 998f51b7662SDaniel Vetter 999f51b7662SDaniel Vetter if (!mem->is_flushed) 1000f51b7662SDaniel Vetter global_cache_flush(); 1001f51b7662SDaniel Vetter 1002f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1003f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 1004f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 1005f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(j*4)); 1006f51b7662SDaniel Vetter } 1007f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 1008f51b7662SDaniel Vetter 1009f51b7662SDaniel Vetter out: 1010f51b7662SDaniel Vetter ret = 0; 1011f51b7662SDaniel Vetter out_err: 1012f51b7662SDaniel Vetter mem->is_flushed = true; 1013f51b7662SDaniel Vetter return ret; 1014f51b7662SDaniel Vetter } 1015f51b7662SDaniel Vetter 1016f51b7662SDaniel Vetter static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, 1017f51b7662SDaniel Vetter int type) 1018f51b7662SDaniel Vetter { 1019f51b7662SDaniel Vetter int i; 1020f51b7662SDaniel Vetter 1021f51b7662SDaniel Vetter if (mem->page_count == 0) 1022f51b7662SDaniel Vetter return 0; 1023f51b7662SDaniel Vetter 10240ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1025f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1026f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 1027f51b7662SDaniel Vetter return -EINVAL; 1028f51b7662SDaniel Vetter } 1029f51b7662SDaniel Vetter 1030f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 1031f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 1032f51b7662SDaniel Vetter } 1033f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 1034f51b7662SDaniel Vetter 1035f51b7662SDaniel Vetter return 0; 1036f51b7662SDaniel Vetter } 1037f51b7662SDaniel Vetter 1038ffdd7510SDaniel Vetter static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, 1039ffdd7510SDaniel Vetter int type) 1040f51b7662SDaniel Vetter { 1041f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 1042f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 1043f51b7662SDaniel Vetter /* always return NULL for other allocation types for now */ 1044f51b7662SDaniel Vetter return NULL; 1045f51b7662SDaniel Vetter } 1046f51b7662SDaniel Vetter 1047f51b7662SDaniel Vetter static int intel_alloc_chipset_flush_resource(void) 1048f51b7662SDaniel Vetter { 1049f51b7662SDaniel Vetter int ret; 1050d7cca2f7SDaniel Vetter ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 1051f51b7662SDaniel Vetter PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 1052d7cca2f7SDaniel Vetter pcibios_align_resource, intel_private.bridge_dev); 1053f51b7662SDaniel Vetter 1054f51b7662SDaniel Vetter return ret; 1055f51b7662SDaniel Vetter } 1056f51b7662SDaniel Vetter 1057f51b7662SDaniel Vetter static void intel_i915_setup_chipset_flush(void) 1058f51b7662SDaniel Vetter { 1059f51b7662SDaniel Vetter int ret; 1060f51b7662SDaniel Vetter u32 temp; 1061f51b7662SDaniel Vetter 1062d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp); 1063f51b7662SDaniel Vetter if (!(temp & 0x1)) { 1064f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1065f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1066d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1067f51b7662SDaniel Vetter } else { 1068f51b7662SDaniel Vetter temp &= ~1; 1069f51b7662SDaniel Vetter 1070f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1071f51b7662SDaniel Vetter intel_private.ifp_resource.start = temp; 1072f51b7662SDaniel Vetter intel_private.ifp_resource.end = temp + PAGE_SIZE; 1073f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1074f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1075f51b7662SDaniel Vetter if (ret) 1076f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1077f51b7662SDaniel Vetter } 1078f51b7662SDaniel Vetter } 1079f51b7662SDaniel Vetter 1080f51b7662SDaniel Vetter static void intel_i965_g33_setup_chipset_flush(void) 1081f51b7662SDaniel Vetter { 1082f51b7662SDaniel Vetter u32 temp_hi, temp_lo; 1083f51b7662SDaniel Vetter int ret; 1084f51b7662SDaniel Vetter 1085d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi); 1086d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo); 1087f51b7662SDaniel Vetter 1088f51b7662SDaniel Vetter if (!(temp_lo & 0x1)) { 1089f51b7662SDaniel Vetter 1090f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1091f51b7662SDaniel Vetter 1092f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1093d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, 1094f51b7662SDaniel Vetter upper_32_bits(intel_private.ifp_resource.start)); 1095d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1096f51b7662SDaniel Vetter } else { 1097f51b7662SDaniel Vetter u64 l64; 1098f51b7662SDaniel Vetter 1099f51b7662SDaniel Vetter temp_lo &= ~0x1; 1100f51b7662SDaniel Vetter l64 = ((u64)temp_hi << 32) | temp_lo; 1101f51b7662SDaniel Vetter 1102f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1103f51b7662SDaniel Vetter intel_private.ifp_resource.start = l64; 1104f51b7662SDaniel Vetter intel_private.ifp_resource.end = l64 + PAGE_SIZE; 1105f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1106f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1107f51b7662SDaniel Vetter if (ret) 1108f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1109f51b7662SDaniel Vetter } 1110f51b7662SDaniel Vetter } 1111f51b7662SDaniel Vetter 1112f51b7662SDaniel Vetter static void intel_i9xx_setup_flush(void) 1113f51b7662SDaniel Vetter { 1114f51b7662SDaniel Vetter /* return if already configured */ 1115f51b7662SDaniel Vetter if (intel_private.ifp_resource.start) 1116f51b7662SDaniel Vetter return; 1117f51b7662SDaniel Vetter 11181a997ff2SDaniel Vetter if (INTEL_GTT_GEN == 6) 1119f51b7662SDaniel Vetter return; 1120f51b7662SDaniel Vetter 1121f51b7662SDaniel Vetter /* setup a resource for this object */ 1122f51b7662SDaniel Vetter intel_private.ifp_resource.name = "Intel Flush Page"; 1123f51b7662SDaniel Vetter intel_private.ifp_resource.flags = IORESOURCE_MEM; 1124f51b7662SDaniel Vetter 1125f51b7662SDaniel Vetter /* Setup chipset flush for 915 */ 11261a997ff2SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN >= 4) { 1127f51b7662SDaniel Vetter intel_i965_g33_setup_chipset_flush(); 1128f51b7662SDaniel Vetter } else { 1129f51b7662SDaniel Vetter intel_i915_setup_chipset_flush(); 1130f51b7662SDaniel Vetter } 1131f51b7662SDaniel Vetter 1132df51e7aaSChris Wilson if (intel_private.ifp_resource.start) 1133f51b7662SDaniel Vetter intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 1134f51b7662SDaniel Vetter if (!intel_private.i9xx_flush_page) 1135df51e7aaSChris Wilson dev_err(&intel_private.pcidev->dev, 1136df51e7aaSChris Wilson "can't ioremap flush page - no chipset flushing\n"); 1137f51b7662SDaniel Vetter } 1138f51b7662SDaniel Vetter 1139f1befe71SChris Wilson static int intel_i9xx_configure(void) 1140f51b7662SDaniel Vetter { 1141f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 1142f51b7662SDaniel Vetter u32 temp; 1143f51b7662SDaniel Vetter u16 gmch_ctrl; 1144f51b7662SDaniel Vetter int i; 1145f51b7662SDaniel Vetter 1146f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 1147f51b7662SDaniel Vetter 1148f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp); 1149f51b7662SDaniel Vetter 1150f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 1151f51b7662SDaniel Vetter 1152d7cca2f7SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); 1153f51b7662SDaniel Vetter gmch_ctrl |= I830_GMCH_ENABLED; 1154d7cca2f7SDaniel Vetter pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); 1155f51b7662SDaniel Vetter 1156f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 1157f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 1158f51b7662SDaniel Vetter 1159f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 11600ade6386SDaniel Vetter for (i = intel_private.base.gtt_stolen_entries; i < 11610ade6386SDaniel Vetter intel_private.base.gtt_total_entries; i++) { 1162f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.gtt+i); 1163f51b7662SDaniel Vetter } 1164f51b7662SDaniel Vetter readl(intel_private.gtt+i-1); /* PCI Posting. */ 1165f51b7662SDaniel Vetter } 1166f51b7662SDaniel Vetter 1167f51b7662SDaniel Vetter global_cache_flush(); 1168f51b7662SDaniel Vetter 1169f51b7662SDaniel Vetter intel_i9xx_setup_flush(); 1170f51b7662SDaniel Vetter 1171f51b7662SDaniel Vetter return 0; 1172f51b7662SDaniel Vetter } 1173f51b7662SDaniel Vetter 1174f51b7662SDaniel Vetter static void intel_i915_cleanup(void) 1175f51b7662SDaniel Vetter { 1176f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1177f51b7662SDaniel Vetter iounmap(intel_private.i9xx_flush_page); 1178f51b7662SDaniel Vetter if (intel_private.resource_valid) 1179f51b7662SDaniel Vetter release_resource(&intel_private.ifp_resource); 1180f51b7662SDaniel Vetter intel_private.ifp_resource.start = 0; 1181f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1182f51b7662SDaniel Vetter iounmap(intel_private.gtt); 1183f51b7662SDaniel Vetter iounmap(intel_private.registers); 1184f51b7662SDaniel Vetter } 1185f51b7662SDaniel Vetter 1186f51b7662SDaniel Vetter static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 1187f51b7662SDaniel Vetter { 1188f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1189f51b7662SDaniel Vetter writel(1, intel_private.i9xx_flush_page); 1190f51b7662SDaniel Vetter } 1191f51b7662SDaniel Vetter 1192f51b7662SDaniel Vetter static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, 1193f51b7662SDaniel Vetter int type) 1194f51b7662SDaniel Vetter { 1195f51b7662SDaniel Vetter int num_entries; 1196f51b7662SDaniel Vetter void *temp; 1197f51b7662SDaniel Vetter int ret = -EINVAL; 1198f51b7662SDaniel Vetter int mask_type; 1199f51b7662SDaniel Vetter 1200f51b7662SDaniel Vetter if (mem->page_count == 0) 1201f51b7662SDaniel Vetter goto out; 1202f51b7662SDaniel Vetter 1203f51b7662SDaniel Vetter temp = agp_bridge->current_size; 1204f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 1205f51b7662SDaniel Vetter 12060ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1207f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 12080ade6386SDaniel Vetter "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", 12090ade6386SDaniel Vetter pg_start, intel_private.base.gtt_stolen_entries); 1210f51b7662SDaniel Vetter 1211f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1212f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 1213f51b7662SDaniel Vetter goto out_err; 1214f51b7662SDaniel Vetter } 1215f51b7662SDaniel Vetter 1216f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 1217f51b7662SDaniel Vetter goto out_err; 1218f51b7662SDaniel Vetter 1219f51b7662SDaniel Vetter /* The i915 can't check the GTT for entries since it's read only; 1220f51b7662SDaniel Vetter * depend on the caller to make the correct offset decisions. 1221f51b7662SDaniel Vetter */ 1222f51b7662SDaniel Vetter 1223f51b7662SDaniel Vetter if (type != mem->type) 1224f51b7662SDaniel Vetter goto out_err; 1225f51b7662SDaniel Vetter 1226f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 1227f51b7662SDaniel Vetter 12281a997ff2SDaniel Vetter if (INTEL_GTT_GEN != 6 && mask_type != 0 && 12291a997ff2SDaniel Vetter mask_type != AGP_PHYS_MEMORY && 1230f51b7662SDaniel Vetter mask_type != INTEL_AGP_CACHED_MEMORY) 1231f51b7662SDaniel Vetter goto out_err; 1232f51b7662SDaniel Vetter 1233f51b7662SDaniel Vetter if (!mem->is_flushed) 1234f51b7662SDaniel Vetter global_cache_flush(); 1235f51b7662SDaniel Vetter 1236f51b7662SDaniel Vetter intel_agp_insert_sg_entries(mem, pg_start, mask_type); 1237f51b7662SDaniel Vetter 1238f51b7662SDaniel Vetter out: 1239f51b7662SDaniel Vetter ret = 0; 1240f51b7662SDaniel Vetter out_err: 1241f51b7662SDaniel Vetter mem->is_flushed = true; 1242f51b7662SDaniel Vetter return ret; 1243f51b7662SDaniel Vetter } 1244f51b7662SDaniel Vetter 1245f51b7662SDaniel Vetter static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, 1246f51b7662SDaniel Vetter int type) 1247f51b7662SDaniel Vetter { 1248f51b7662SDaniel Vetter int i; 1249f51b7662SDaniel Vetter 1250f51b7662SDaniel Vetter if (mem->page_count == 0) 1251f51b7662SDaniel Vetter return 0; 1252f51b7662SDaniel Vetter 12530ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1254f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1255f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 1256f51b7662SDaniel Vetter return -EINVAL; 1257f51b7662SDaniel Vetter } 1258f51b7662SDaniel Vetter 1259f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) 1260f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.gtt+i); 1261f51b7662SDaniel Vetter 1262f51b7662SDaniel Vetter readl(intel_private.gtt+i-1); 1263f51b7662SDaniel Vetter 1264f51b7662SDaniel Vetter return 0; 1265f51b7662SDaniel Vetter } 1266f51b7662SDaniel Vetter 1267f51b7662SDaniel Vetter /* The intel i915 automatically initializes the agp aperture during POST. 1268f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 1269f51b7662SDaniel Vetter */ 1270f51b7662SDaniel Vetter static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) 1271f51b7662SDaniel Vetter { 12721784a5fbSDaniel Vetter int page_order, ret; 1273f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 1274f51b7662SDaniel Vetter int num_entries; 1275f51b7662SDaniel Vetter u32 temp, temp2; 1276f1befe71SChris Wilson int gtt_map_size; 1277f51b7662SDaniel Vetter 1278f51b7662SDaniel Vetter size = agp_bridge->current_size; 1279f51b7662SDaniel Vetter page_order = size->page_order; 1280f51b7662SDaniel Vetter num_entries = size->num_entries; 1281f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 1282f51b7662SDaniel Vetter 1283f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); 1284f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); 1285f51b7662SDaniel Vetter 1286f51b7662SDaniel Vetter temp &= 0xfff80000; 1287f51b7662SDaniel Vetter 1288f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 1289ccc4e67bSDaniel Vetter if (!intel_private.registers) 1290ccc4e67bSDaniel Vetter return -ENOMEM; 1291ccc4e67bSDaniel Vetter 1292ccc4e67bSDaniel Vetter intel_private.base.gtt_total_entries = intel_gtt_total_entries(); 1293ccc4e67bSDaniel Vetter gtt_map_size = intel_private.base.gtt_total_entries * 4; 1294ccc4e67bSDaniel Vetter 1295ccc4e67bSDaniel Vetter intel_private.gtt = ioremap(temp2, gtt_map_size); 1296ccc4e67bSDaniel Vetter if (!intel_private.gtt) { 1297ccc4e67bSDaniel Vetter iounmap(intel_private.registers); 1298f51b7662SDaniel Vetter return -ENOMEM; 1299f51b7662SDaniel Vetter } 1300f51b7662SDaniel Vetter 1301f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 1302f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 1303f51b7662SDaniel Vetter 13041784a5fbSDaniel Vetter ret = intel_gtt_init(); 13051784a5fbSDaniel Vetter if (ret != 0) { 13068699be3eSOndrej Zary iounmap(intel_private.gtt); 13071784a5fbSDaniel Vetter return ret; 13088699be3eSOndrej Zary } 1309f51b7662SDaniel Vetter 1310f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 1311f51b7662SDaniel Vetter 1312f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 1313f51b7662SDaniel Vetter 1314f51b7662SDaniel Vetter return 0; 1315f51b7662SDaniel Vetter } 1316f51b7662SDaniel Vetter 1317f51b7662SDaniel Vetter /* 1318f51b7662SDaniel Vetter * The i965 supports 36-bit physical addresses, but to keep 1319f51b7662SDaniel Vetter * the format of the GTT the same, the bits that don't fit 1320f51b7662SDaniel Vetter * in a 32-bit word are shifted down to bits 4..7. 1321f51b7662SDaniel Vetter * 1322f51b7662SDaniel Vetter * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" 1323f51b7662SDaniel Vetter * is always zero on 32-bit architectures, so no need to make 1324f51b7662SDaniel Vetter * this conditional. 1325f51b7662SDaniel Vetter */ 1326f51b7662SDaniel Vetter static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, 1327f51b7662SDaniel Vetter dma_addr_t addr, int type) 1328f51b7662SDaniel Vetter { 1329f51b7662SDaniel Vetter /* Shift high bits down */ 1330f51b7662SDaniel Vetter addr |= (addr >> 28) & 0xf0; 1331f51b7662SDaniel Vetter 1332f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 1333f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 1334f51b7662SDaniel Vetter } 1335f51b7662SDaniel Vetter 13363869d4a8SZhenyu Wang static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, 13373869d4a8SZhenyu Wang dma_addr_t addr, int type) 13383869d4a8SZhenyu Wang { 13398dfc2b14SZhenyu Wang /* gen6 has bit11-4 for physical addr bit39-32 */ 13408dfc2b14SZhenyu Wang addr |= (addr >> 28) & 0xff0; 13413869d4a8SZhenyu Wang 13423869d4a8SZhenyu Wang /* Type checking must be done elsewhere */ 13433869d4a8SZhenyu Wang return addr | bridge->driver->masks[type].mask; 13443869d4a8SZhenyu Wang } 13453869d4a8SZhenyu Wang 1346f51b7662SDaniel Vetter static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) 1347f51b7662SDaniel Vetter { 1348210b23c2SDaniel Vetter switch (INTEL_GTT_GEN) { 1349210b23c2SDaniel Vetter case 5: 1350210b23c2SDaniel Vetter case 6: 1351f51b7662SDaniel Vetter *gtt_offset = MB(2); 1352210b23c2SDaniel Vetter break; 1353210b23c2SDaniel Vetter case 4: 1354210b23c2SDaniel Vetter default: 1355210b23c2SDaniel Vetter *gtt_offset = KB(512); 1356210b23c2SDaniel Vetter break; 1357210b23c2SDaniel Vetter } 1358f51b7662SDaniel Vetter 1359210b23c2SDaniel Vetter *gtt_size = intel_private.base.gtt_total_entries * 4; 1360f51b7662SDaniel Vetter } 1361f51b7662SDaniel Vetter 1362f51b7662SDaniel Vetter /* The intel i965 automatically initializes the agp aperture during POST. 1363f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 1364f51b7662SDaniel Vetter */ 1365f51b7662SDaniel Vetter static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) 1366f51b7662SDaniel Vetter { 13671784a5fbSDaniel Vetter int page_order, ret; 1368f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 1369f51b7662SDaniel Vetter int num_entries; 1370f51b7662SDaniel Vetter u32 temp; 1371f51b7662SDaniel Vetter int gtt_offset, gtt_size; 1372f51b7662SDaniel Vetter 1373f51b7662SDaniel Vetter size = agp_bridge->current_size; 1374f51b7662SDaniel Vetter page_order = size->page_order; 1375f51b7662SDaniel Vetter num_entries = size->num_entries; 1376f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 1377f51b7662SDaniel Vetter 1378f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); 1379f51b7662SDaniel Vetter 1380f51b7662SDaniel Vetter temp &= 0xfff00000; 1381f51b7662SDaniel Vetter 1382210b23c2SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 1383210b23c2SDaniel Vetter if (!intel_private.registers) 1384210b23c2SDaniel Vetter return -ENOMEM; 1385210b23c2SDaniel Vetter 1386210b23c2SDaniel Vetter intel_private.base.gtt_total_entries = intel_gtt_total_entries(); 1387210b23c2SDaniel Vetter 1388f51b7662SDaniel Vetter intel_i965_get_gtt_range(>t_offset, >t_size); 1389f51b7662SDaniel Vetter 1390f51b7662SDaniel Vetter intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size); 1391f51b7662SDaniel Vetter 1392210b23c2SDaniel Vetter if (!intel_private.gtt) { 1393f51b7662SDaniel Vetter iounmap(intel_private.gtt); 1394f51b7662SDaniel Vetter return -ENOMEM; 1395f51b7662SDaniel Vetter } 1396f51b7662SDaniel Vetter 1397f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 1398f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 1399f51b7662SDaniel Vetter 14001784a5fbSDaniel Vetter ret = intel_gtt_init(); 14011784a5fbSDaniel Vetter if (ret != 0) { 14028699be3eSOndrej Zary iounmap(intel_private.gtt); 14031784a5fbSDaniel Vetter return ret; 14048699be3eSOndrej Zary } 1405f51b7662SDaniel Vetter 1406f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 1407f51b7662SDaniel Vetter 1408f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 1409f51b7662SDaniel Vetter 1410f51b7662SDaniel Vetter return 0; 1411f51b7662SDaniel Vetter } 1412f51b7662SDaniel Vetter 1413f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_810_driver = { 1414f51b7662SDaniel Vetter .owner = THIS_MODULE, 1415f51b7662SDaniel Vetter .aperture_sizes = intel_i810_sizes, 1416f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1417f51b7662SDaniel Vetter .num_aperture_sizes = 2, 1418f51b7662SDaniel Vetter .needs_scratch_page = true, 1419f51b7662SDaniel Vetter .configure = intel_i810_configure, 1420f51b7662SDaniel Vetter .fetch_size = intel_i810_fetch_size, 1421f51b7662SDaniel Vetter .cleanup = intel_i810_cleanup, 1422f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1423f51b7662SDaniel Vetter .masks = intel_i810_masks, 1424ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1425f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1426f51b7662SDaniel Vetter .create_gatt_table = agp_generic_create_gatt_table, 1427f51b7662SDaniel Vetter .free_gatt_table = agp_generic_free_gatt_table, 1428f51b7662SDaniel Vetter .insert_memory = intel_i810_insert_entries, 1429f51b7662SDaniel Vetter .remove_memory = intel_i810_remove_entries, 1430f51b7662SDaniel Vetter .alloc_by_type = intel_i810_alloc_by_type, 1431f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1432f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1433f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1434f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1435f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1436f51b7662SDaniel Vetter .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1437f51b7662SDaniel Vetter }; 1438f51b7662SDaniel Vetter 1439f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_830_driver = { 1440f51b7662SDaniel Vetter .owner = THIS_MODULE, 1441ffdd7510SDaniel Vetter .aperture_sizes = intel_fake_agp_sizes, 1442f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1443f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1444f51b7662SDaniel Vetter .needs_scratch_page = true, 1445f51b7662SDaniel Vetter .configure = intel_i830_configure, 14463e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1447f51b7662SDaniel Vetter .cleanup = intel_i830_cleanup, 1448f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1449f51b7662SDaniel Vetter .masks = intel_i810_masks, 1450ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1451f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1452f51b7662SDaniel Vetter .create_gatt_table = intel_i830_create_gatt_table, 1453ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1454f51b7662SDaniel Vetter .insert_memory = intel_i830_insert_entries, 1455f51b7662SDaniel Vetter .remove_memory = intel_i830_remove_entries, 1456ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1457f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1458f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1459f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1460f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1461f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1462f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1463f51b7662SDaniel Vetter .chipset_flush = intel_i830_chipset_flush, 1464f51b7662SDaniel Vetter }; 1465f51b7662SDaniel Vetter 1466f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_915_driver = { 1467f51b7662SDaniel Vetter .owner = THIS_MODULE, 1468ffdd7510SDaniel Vetter .aperture_sizes = intel_fake_agp_sizes, 1469f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1470f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1471f51b7662SDaniel Vetter .needs_scratch_page = true, 1472f1befe71SChris Wilson .configure = intel_i9xx_configure, 14733e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1474f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1475f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1476f51b7662SDaniel Vetter .masks = intel_i810_masks, 1477ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1478f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1479f51b7662SDaniel Vetter .create_gatt_table = intel_i915_create_gatt_table, 1480ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1481f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1482f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1483ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1484f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1485f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1486f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1487f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1488f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1489f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1490f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1491f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1492f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1493f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1494f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1495f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1496f51b7662SDaniel Vetter #endif 1497f51b7662SDaniel Vetter }; 1498f51b7662SDaniel Vetter 1499f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_i965_driver = { 1500f51b7662SDaniel Vetter .owner = THIS_MODULE, 1501ffdd7510SDaniel Vetter .aperture_sizes = intel_fake_agp_sizes, 1502f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1503f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1504f51b7662SDaniel Vetter .needs_scratch_page = true, 1505f1befe71SChris Wilson .configure = intel_i9xx_configure, 15063e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1507f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1508f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1509f51b7662SDaniel Vetter .masks = intel_i810_masks, 1510ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1511f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1512f51b7662SDaniel Vetter .create_gatt_table = intel_i965_create_gatt_table, 1513ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1514f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1515f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1516ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1517f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1518f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1519f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1520f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1521f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1522f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1523f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1524f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1525f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1526f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1527f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1528f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1529f51b7662SDaniel Vetter #endif 1530f51b7662SDaniel Vetter }; 1531f51b7662SDaniel Vetter 15323869d4a8SZhenyu Wang static const struct agp_bridge_driver intel_gen6_driver = { 15333869d4a8SZhenyu Wang .owner = THIS_MODULE, 1534ffdd7510SDaniel Vetter .aperture_sizes = intel_fake_agp_sizes, 15353869d4a8SZhenyu Wang .size_type = FIXED_APER_SIZE, 15363869d4a8SZhenyu Wang .num_aperture_sizes = 4, 15373869d4a8SZhenyu Wang .needs_scratch_page = true, 15383869d4a8SZhenyu Wang .configure = intel_i9xx_configure, 15393e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 15403869d4a8SZhenyu Wang .cleanup = intel_i915_cleanup, 15413869d4a8SZhenyu Wang .mask_memory = intel_gen6_mask_memory, 1542f8f235e5SZhenyu Wang .masks = intel_gen6_masks, 1543ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 15443869d4a8SZhenyu Wang .cache_flush = global_cache_flush, 15453869d4a8SZhenyu Wang .create_gatt_table = intel_i965_create_gatt_table, 1546ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 15473869d4a8SZhenyu Wang .insert_memory = intel_i915_insert_entries, 15483869d4a8SZhenyu Wang .remove_memory = intel_i915_remove_entries, 1549ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 15503869d4a8SZhenyu Wang .free_by_type = intel_i810_free_by_type, 15513869d4a8SZhenyu Wang .agp_alloc_page = agp_generic_alloc_page, 15523869d4a8SZhenyu Wang .agp_alloc_pages = agp_generic_alloc_pages, 15533869d4a8SZhenyu Wang .agp_destroy_page = agp_generic_destroy_page, 15543869d4a8SZhenyu Wang .agp_destroy_pages = agp_generic_destroy_pages, 1555f8f235e5SZhenyu Wang .agp_type_to_mask_type = intel_gen6_type_to_mask_type, 15563869d4a8SZhenyu Wang .chipset_flush = intel_i915_chipset_flush, 15573869d4a8SZhenyu Wang #ifdef USE_PCI_DMA_API 15583869d4a8SZhenyu Wang .agp_map_page = intel_agp_map_page, 15593869d4a8SZhenyu Wang .agp_unmap_page = intel_agp_unmap_page, 15603869d4a8SZhenyu Wang .agp_map_memory = intel_agp_map_memory, 15613869d4a8SZhenyu Wang .agp_unmap_memory = intel_agp_unmap_memory, 15623869d4a8SZhenyu Wang #endif 15633869d4a8SZhenyu Wang }; 15643869d4a8SZhenyu Wang 1565f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_g33_driver = { 1566f51b7662SDaniel Vetter .owner = THIS_MODULE, 1567ffdd7510SDaniel Vetter .aperture_sizes = intel_fake_agp_sizes, 1568f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1569f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1570f51b7662SDaniel Vetter .needs_scratch_page = true, 1571f1befe71SChris Wilson .configure = intel_i9xx_configure, 15723e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1573f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1574f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1575f51b7662SDaniel Vetter .masks = intel_i810_masks, 1576ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1577f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1578f51b7662SDaniel Vetter .create_gatt_table = intel_i915_create_gatt_table, 1579ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1580f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1581f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1582ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1583f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1584f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1585f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1586f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1587f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1588f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1589f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1590f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1591f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1592f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1593f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1594f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1595f51b7662SDaniel Vetter #endif 1596f51b7662SDaniel Vetter }; 159702c026ceSDaniel Vetter 15981a997ff2SDaniel Vetter static const struct intel_gtt_driver i8xx_gtt_driver = { 15991a997ff2SDaniel Vetter .gen = 2, 16001a997ff2SDaniel Vetter }; 16011a997ff2SDaniel Vetter static const struct intel_gtt_driver i915_gtt_driver = { 16021a997ff2SDaniel Vetter .gen = 3, 16031a997ff2SDaniel Vetter }; 16041a997ff2SDaniel Vetter static const struct intel_gtt_driver g33_gtt_driver = { 16051a997ff2SDaniel Vetter .gen = 3, 16061a997ff2SDaniel Vetter .is_g33 = 1, 16071a997ff2SDaniel Vetter }; 16081a997ff2SDaniel Vetter static const struct intel_gtt_driver pineview_gtt_driver = { 16091a997ff2SDaniel Vetter .gen = 3, 16101a997ff2SDaniel Vetter .is_pineview = 1, .is_g33 = 1, 16111a997ff2SDaniel Vetter }; 16121a997ff2SDaniel Vetter static const struct intel_gtt_driver i965_gtt_driver = { 16131a997ff2SDaniel Vetter .gen = 4, 16141a997ff2SDaniel Vetter }; 16151a997ff2SDaniel Vetter static const struct intel_gtt_driver g4x_gtt_driver = { 16161a997ff2SDaniel Vetter .gen = 5, 16171a997ff2SDaniel Vetter }; 16181a997ff2SDaniel Vetter static const struct intel_gtt_driver ironlake_gtt_driver = { 16191a997ff2SDaniel Vetter .gen = 5, 16201a997ff2SDaniel Vetter .is_ironlake = 1, 16211a997ff2SDaniel Vetter }; 16221a997ff2SDaniel Vetter static const struct intel_gtt_driver sandybridge_gtt_driver = { 16231a997ff2SDaniel Vetter .gen = 6, 16241a997ff2SDaniel Vetter }; 16251a997ff2SDaniel Vetter 162602c026ceSDaniel Vetter /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of 162702c026ceSDaniel Vetter * driver and gmch_driver must be non-null, and find_gmch will determine 162802c026ceSDaniel Vetter * which one should be used if a gmch_chip_id is present. 162902c026ceSDaniel Vetter */ 163002c026ceSDaniel Vetter static const struct intel_gtt_driver_description { 163102c026ceSDaniel Vetter unsigned int gmch_chip_id; 163202c026ceSDaniel Vetter char *name; 163302c026ceSDaniel Vetter const struct agp_bridge_driver *gmch_driver; 16341a997ff2SDaniel Vetter const struct intel_gtt_driver *gtt_driver; 163502c026ceSDaniel Vetter } intel_gtt_chipsets[] = { 16361a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver , NULL}, 16371a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver , NULL}, 16381a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver , NULL}, 16391a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver , NULL}, 16401a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", 16411a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16421a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", 16431a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16441a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82854_IG, "854", 16451a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16461a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", 16471a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16481a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82865_IG, "865", 16491a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16501a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", 16511a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16521a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", 16531a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16541a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", 16551a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16561a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", 16571a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16581a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", 16591a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16601a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", 16611a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16621a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", 16631a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16641a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", 16651a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16661a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", 16671a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16681a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", 16691a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16701a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", 16711a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16721a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", 16731a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 16741a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G33_IG, "G33", 16751a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 16761a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", 16771a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 16781a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", 16791a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 16801a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", 16811a997ff2SDaniel Vetter &intel_g33_driver , &pineview_gtt_driver }, 16821a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", 16831a997ff2SDaniel Vetter &intel_g33_driver , &pineview_gtt_driver }, 16841a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", 16851a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 16861a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", 16871a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 16881a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", 16891a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 16901a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", 16911a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 16921a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_B43_IG, "B43", 16931a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 16941a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G41_IG, "G41", 16951a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 169602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 16971a997ff2SDaniel Vetter "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver }, 169802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 16991a997ff2SDaniel Vetter "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver }, 170002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, 17011a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 170202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, 17031a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 170402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, 17051a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 170602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, 17071a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 170802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, 17091a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 171002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, 17111a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 171202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, 17131a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 171402c026ceSDaniel Vetter { 0, NULL, NULL } 171502c026ceSDaniel Vetter }; 171602c026ceSDaniel Vetter 171702c026ceSDaniel Vetter static int find_gmch(u16 device) 171802c026ceSDaniel Vetter { 171902c026ceSDaniel Vetter struct pci_dev *gmch_device; 172002c026ceSDaniel Vetter 172102c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); 172202c026ceSDaniel Vetter if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { 172302c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, 172402c026ceSDaniel Vetter device, gmch_device); 172502c026ceSDaniel Vetter } 172602c026ceSDaniel Vetter 172702c026ceSDaniel Vetter if (!gmch_device) 172802c026ceSDaniel Vetter return 0; 172902c026ceSDaniel Vetter 173002c026ceSDaniel Vetter intel_private.pcidev = gmch_device; 173102c026ceSDaniel Vetter return 1; 173202c026ceSDaniel Vetter } 173302c026ceSDaniel Vetter 1734e2404e7cSDaniel Vetter int intel_gmch_probe(struct pci_dev *pdev, 173502c026ceSDaniel Vetter struct agp_bridge_data *bridge) 173602c026ceSDaniel Vetter { 173702c026ceSDaniel Vetter int i, mask; 173802c026ceSDaniel Vetter bridge->driver = NULL; 173902c026ceSDaniel Vetter 174002c026ceSDaniel Vetter for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { 174102c026ceSDaniel Vetter if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { 174202c026ceSDaniel Vetter bridge->driver = 174302c026ceSDaniel Vetter intel_gtt_chipsets[i].gmch_driver; 17441a997ff2SDaniel Vetter intel_private.driver = 17451a997ff2SDaniel Vetter intel_gtt_chipsets[i].gtt_driver; 174602c026ceSDaniel Vetter break; 174702c026ceSDaniel Vetter } 174802c026ceSDaniel Vetter } 174902c026ceSDaniel Vetter 175002c026ceSDaniel Vetter if (!bridge->driver) 175102c026ceSDaniel Vetter return 0; 175202c026ceSDaniel Vetter 175302c026ceSDaniel Vetter bridge->dev_private_data = &intel_private; 175402c026ceSDaniel Vetter bridge->dev = pdev; 175502c026ceSDaniel Vetter 1756d7cca2f7SDaniel Vetter intel_private.bridge_dev = pci_dev_get(pdev); 1757d7cca2f7SDaniel Vetter 175802c026ceSDaniel Vetter dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); 175902c026ceSDaniel Vetter 176002c026ceSDaniel Vetter if (bridge->driver->mask_memory == intel_gen6_mask_memory) 176102c026ceSDaniel Vetter mask = 40; 176202c026ceSDaniel Vetter else if (bridge->driver->mask_memory == intel_i965_mask_memory) 176302c026ceSDaniel Vetter mask = 36; 176402c026ceSDaniel Vetter else 176502c026ceSDaniel Vetter mask = 32; 176602c026ceSDaniel Vetter 176702c026ceSDaniel Vetter if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) 176802c026ceSDaniel Vetter dev_err(&intel_private.pcidev->dev, 176902c026ceSDaniel Vetter "set gfx device dma mask %d-bit failed!\n", mask); 177002c026ceSDaniel Vetter else 177102c026ceSDaniel Vetter pci_set_consistent_dma_mask(intel_private.pcidev, 177202c026ceSDaniel Vetter DMA_BIT_MASK(mask)); 177302c026ceSDaniel Vetter 17741784a5fbSDaniel Vetter if (bridge->driver == &intel_810_driver) 17751784a5fbSDaniel Vetter return 1; 17761784a5fbSDaniel Vetter 17771784a5fbSDaniel Vetter intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); 17781784a5fbSDaniel Vetter 177902c026ceSDaniel Vetter return 1; 178002c026ceSDaniel Vetter } 1781e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_probe); 178202c026ceSDaniel Vetter 1783e2404e7cSDaniel Vetter void intel_gmch_remove(struct pci_dev *pdev) 178402c026ceSDaniel Vetter { 178502c026ceSDaniel Vetter if (intel_private.pcidev) 178602c026ceSDaniel Vetter pci_dev_put(intel_private.pcidev); 1787d7cca2f7SDaniel Vetter if (intel_private.bridge_dev) 1788d7cca2f7SDaniel Vetter pci_dev_put(intel_private.bridge_dev); 178902c026ceSDaniel Vetter } 1790e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_remove); 1791e2404e7cSDaniel Vetter 1792e2404e7cSDaniel Vetter MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); 1793e2404e7cSDaniel Vetter MODULE_LICENSE("GPL and additional rights"); 1794