Rev 3037 | Rev 3480 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2325 | Serge | 1 | /* |
2 | * Intel GTT (Graphics Translation Table) routines |
||
3 | * |
||
4 | * Caveat: This driver implements the linux agp interface, but this is far from |
||
5 | * a agp driver! GTT support ended up here for purely historical reasons: The |
||
6 | * old userspace intel graphics drivers needed an interface to map memory into |
||
7 | * the GTT. And the drm provides a default interface for graphic devices sitting |
||
8 | * on an agp port. So it made sense to fake the GTT support as an agp port to |
||
9 | * avoid having to create a new api. |
||
10 | * |
||
11 | * With gem this does not make much sense anymore, just needlessly complicates |
||
12 | * the code. But as long as the old graphics stack is still support, it's stuck |
||
13 | * here. |
||
14 | * |
||
15 | * /fairy-tale-mode off |
||
16 | */ |
||
17 | |||
18 | #include |
||
19 | #include |
||
20 | #include |
||
21 | #include |
||
3031 | serge | 22 | #include |
3243 | Serge | 23 | #include |
24 | |||
2325 | Serge | 25 | //#include |
26 | //#include |
||
27 | //#include |
||
28 | #include |
||
29 | #include "agp.h" |
||
30 | #include "intel-agp.h" |
||
3243 | Serge | 31 | #include |
2325 | Serge | 32 | |
33 | #include |
||
34 | |||
35 | struct pci_dev * |
||
36 | pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from); |
||
37 | |||
38 | |||
39 | #define PCI_VENDOR_ID_INTEL 0x8086 |
||
40 | #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 |
||
41 | #define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 |
||
2339 | Serge | 42 | #define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 |
43 | #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 |
||
44 | #define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 |
||
45 | #define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 |
||
2325 | Serge | 46 | |
47 | |||
48 | #define AGP_NORMAL_MEMORY 0 |
||
49 | |||
50 | #define AGP_USER_TYPES (1 << 16) |
||
51 | #define AGP_USER_MEMORY (AGP_USER_TYPES) |
||
52 | #define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) |
||
53 | |||
54 | |||
55 | |||
56 | /* |
||
57 | * If we have Intel graphics, we're not going to have anything other than |
||
58 | * an Intel IOMMU. So make the correct use of the PCI DMA API contingent |
||
2339 | Serge | 59 | * on the Intel IOMMU support (CONFIG_INTEL_IOMMU). |
2325 | Serge | 60 | * Only newer chipsets need to bother with this, of course. |
61 | */ |
||
2339 | Serge | 62 | #ifdef CONFIG_INTEL_IOMMU |
2325 | Serge | 63 | #define USE_PCI_DMA_API 1 |
64 | #else |
||
65 | #define USE_PCI_DMA_API 0 |
||
66 | #endif |
||
67 | |||
68 | struct intel_gtt_driver { |
||
69 | unsigned int gen : 8; |
||
70 | unsigned int is_g33 : 1; |
||
71 | unsigned int is_pineview : 1; |
||
72 | unsigned int is_ironlake : 1; |
||
73 | unsigned int has_pgtbl_enable : 1; |
||
74 | unsigned int dma_mask_size : 8; |
||
75 | /* Chipset specific GTT setup */ |
||
76 | int (*setup)(void); |
||
77 | /* This should undo anything done in ->setup() save the unmapping |
||
78 | * of the mmio register file, that's done in the generic code. */ |
||
79 | void (*cleanup)(void); |
||
80 | void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); |
||
81 | /* Flags is a more or less chipset specific opaque value. |
||
82 | * For chipsets that need to support old ums (non-gem) code, this |
||
83 | * needs to be identical to the various supported agp memory types! */ |
||
84 | bool (*check_flags)(unsigned int flags); |
||
85 | void (*chipset_flush)(void); |
||
86 | }; |
||
87 | |||
88 | static struct _intel_private { |
||
89 | struct intel_gtt base; |
||
90 | const struct intel_gtt_driver *driver; |
||
91 | struct pci_dev *pcidev; /* device one */ |
||
92 | struct pci_dev *bridge_dev; |
||
93 | u8 __iomem *registers; |
||
94 | phys_addr_t gtt_bus_addr; |
||
95 | u32 PGETBL_save; |
||
96 | u32 __iomem *gtt; /* I915G */ |
||
97 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ |
||
98 | int num_dcache_entries; |
||
99 | void __iomem *i9xx_flush_page; |
||
100 | char *i81x_gtt_table; |
||
101 | struct resource ifp_resource; |
||
102 | int resource_valid; |
||
103 | struct page *scratch_page; |
||
3031 | serge | 104 | int refcount; |
2325 | Serge | 105 | } intel_private; |
106 | |||
107 | #define INTEL_GTT_GEN intel_private.driver->gen |
||
108 | #define IS_G33 intel_private.driver->is_g33 |
||
109 | #define IS_PINEVIEW intel_private.driver->is_pineview |
||
110 | #define IS_IRONLAKE intel_private.driver->is_ironlake |
||
111 | #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable |
||
112 | |||
113 | static int intel_gtt_setup_scratch_page(void) |
||
114 | { |
||
3243 | Serge | 115 | struct page *page; |
3031 | serge | 116 | dma_addr_t dma_addr; |
2325 | Serge | 117 | |
3243 | Serge | 118 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); |
119 | if (page == NULL) |
||
2325 | Serge | 120 | return -ENOMEM; |
3243 | Serge | 121 | intel_private.base.scratch_page_dma = page_to_phys(page); |
2325 | Serge | 122 | |
3243 | Serge | 123 | intel_private.scratch_page = page; |
2325 | Serge | 124 | |
125 | return 0; |
||
126 | } |
||
127 | |||
128 | static unsigned int intel_gtt_stolen_size(void) |
||
129 | { |
||
130 | u16 gmch_ctrl; |
||
131 | u8 rdct; |
||
132 | int local = 0; |
||
133 | static const int ddt[4] = { 0, 16, 32, 64 }; |
||
134 | unsigned int stolen_size = 0; |
||
135 | |||
136 | if (INTEL_GTT_GEN == 1) |
||
137 | return 0; /* no stolen mem on i81x */ |
||
138 | |||
139 | pci_read_config_word(intel_private.bridge_dev, |
||
140 | I830_GMCH_CTRL, &gmch_ctrl); |
||
141 | |||
142 | if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || |
||
143 | intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { |
||
144 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { |
||
145 | case I830_GMCH_GMS_STOLEN_512: |
||
146 | stolen_size = KB(512); |
||
147 | break; |
||
148 | case I830_GMCH_GMS_STOLEN_1024: |
||
149 | stolen_size = MB(1); |
||
150 | break; |
||
151 | case I830_GMCH_GMS_STOLEN_8192: |
||
152 | stolen_size = MB(8); |
||
153 | break; |
||
154 | case I830_GMCH_GMS_LOCAL: |
||
155 | rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); |
||
156 | stolen_size = (I830_RDRAM_ND(rdct) + 1) * |
||
157 | MB(ddt[I830_RDRAM_DDT(rdct)]); |
||
158 | local = 1; |
||
159 | break; |
||
160 | default: |
||
161 | stolen_size = 0; |
||
162 | break; |
||
163 | } |
||
164 | } else { |
||
165 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { |
||
166 | case I855_GMCH_GMS_STOLEN_1M: |
||
167 | stolen_size = MB(1); |
||
168 | break; |
||
169 | case I855_GMCH_GMS_STOLEN_4M: |
||
170 | stolen_size = MB(4); |
||
171 | break; |
||
172 | case I855_GMCH_GMS_STOLEN_8M: |
||
173 | stolen_size = MB(8); |
||
174 | break; |
||
175 | case I855_GMCH_GMS_STOLEN_16M: |
||
176 | stolen_size = MB(16); |
||
177 | break; |
||
178 | case I855_GMCH_GMS_STOLEN_32M: |
||
179 | stolen_size = MB(32); |
||
180 | break; |
||
181 | case I915_GMCH_GMS_STOLEN_48M: |
||
182 | stolen_size = MB(48); |
||
183 | break; |
||
184 | case I915_GMCH_GMS_STOLEN_64M: |
||
185 | stolen_size = MB(64); |
||
186 | break; |
||
187 | case G33_GMCH_GMS_STOLEN_128M: |
||
188 | stolen_size = MB(128); |
||
189 | break; |
||
190 | case G33_GMCH_GMS_STOLEN_256M: |
||
191 | stolen_size = MB(256); |
||
192 | break; |
||
193 | case INTEL_GMCH_GMS_STOLEN_96M: |
||
194 | stolen_size = MB(96); |
||
195 | break; |
||
196 | case INTEL_GMCH_GMS_STOLEN_160M: |
||
197 | stolen_size = MB(160); |
||
198 | break; |
||
199 | case INTEL_GMCH_GMS_STOLEN_224M: |
||
200 | stolen_size = MB(224); |
||
201 | break; |
||
202 | case INTEL_GMCH_GMS_STOLEN_352M: |
||
203 | stolen_size = MB(352); |
||
204 | break; |
||
205 | default: |
||
206 | stolen_size = 0; |
||
207 | break; |
||
208 | } |
||
209 | } |
||
210 | |||
211 | if (stolen_size > 0) { |
||
2332 | Serge | 212 | dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", |
2325 | Serge | 213 | stolen_size / KB(1), local ? "local" : "stolen"); |
214 | } else { |
||
2332 | Serge | 215 | dev_info(&intel_private.bridge_dev->dev, |
216 | "no pre-allocated video memory detected\n"); |
||
2325 | Serge | 217 | stolen_size = 0; |
218 | } |
||
219 | |||
220 | return stolen_size; |
||
221 | } |
||
222 | |||
223 | static void i965_adjust_pgetbl_size(unsigned int size_flag) |
||
224 | { |
||
225 | u32 pgetbl_ctl, pgetbl_ctl2; |
||
226 | |||
227 | /* ensure that ppgtt is disabled */ |
||
228 | pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2); |
||
229 | pgetbl_ctl2 &= ~I810_PGETBL_ENABLED; |
||
230 | writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2); |
||
231 | |||
232 | /* write the new ggtt size */ |
||
233 | pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); |
||
234 | pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK; |
||
235 | pgetbl_ctl |= size_flag; |
||
236 | writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL); |
||
237 | } |
||
238 | |||
239 | static unsigned int i965_gtt_total_entries(void) |
||
240 | { |
||
241 | int size; |
||
242 | u32 pgetbl_ctl; |
||
243 | u16 gmch_ctl; |
||
244 | |||