1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * VIA AGPGART routines.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/types.h>
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/pci.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/agp_backend.h>
11*4882a593Smuzhiyun #include "agp.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun static const struct pci_device_id agp_via_pci_table[];
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define VIA_GARTCTRL 0x80
16*4882a593Smuzhiyun #define VIA_APSIZE 0x84
17*4882a593Smuzhiyun #define VIA_ATTBASE 0x88
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define VIA_AGP3_GARTCTRL 0x90
20*4882a593Smuzhiyun #define VIA_AGP3_APSIZE 0x94
21*4882a593Smuzhiyun #define VIA_AGP3_ATTBASE 0x98
22*4882a593Smuzhiyun #define VIA_AGPSEL 0xfd
23*4882a593Smuzhiyun
via_fetch_size(void)24*4882a593Smuzhiyun static int via_fetch_size(void)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun int i;
27*4882a593Smuzhiyun u8 temp;
28*4882a593Smuzhiyun struct aper_size_info_8 *values;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
31*4882a593Smuzhiyun pci_read_config_byte(agp_bridge->dev, VIA_APSIZE, &temp);
32*4882a593Smuzhiyun for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
33*4882a593Smuzhiyun if (temp == values[i].size_value) {
34*4882a593Smuzhiyun agp_bridge->previous_size =
35*4882a593Smuzhiyun agp_bridge->current_size = (void *) (values + i);
36*4882a593Smuzhiyun agp_bridge->aperture_size_idx = i;
37*4882a593Smuzhiyun return values[i].size;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun printk(KERN_ERR PFX "Unknown aperture size from AGP bridge (0x%x)\n", temp);
41*4882a593Smuzhiyun return 0;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun
via_configure(void)45*4882a593Smuzhiyun static int via_configure(void)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun struct aper_size_info_8 *current_size;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun current_size = A_SIZE_8(agp_bridge->current_size);
50*4882a593Smuzhiyun /* aperture size */
51*4882a593Smuzhiyun pci_write_config_byte(agp_bridge->dev, VIA_APSIZE,
52*4882a593Smuzhiyun current_size->size_value);
53*4882a593Smuzhiyun /* address to map to */
54*4882a593Smuzhiyun agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
55*4882a593Smuzhiyun AGP_APERTURE_BAR);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* GART control register */
58*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* attbase - aperture GATT base */
61*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_ATTBASE,
62*4882a593Smuzhiyun (agp_bridge->gatt_bus_addr & 0xfffff000) | 3);
63*4882a593Smuzhiyun return 0;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun
via_cleanup(void)67*4882a593Smuzhiyun static void via_cleanup(void)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun struct aper_size_info_8 *previous_size;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun previous_size = A_SIZE_8(agp_bridge->previous_size);
72*4882a593Smuzhiyun pci_write_config_byte(agp_bridge->dev, VIA_APSIZE,
73*4882a593Smuzhiyun previous_size->size_value);
74*4882a593Smuzhiyun /* Do not disable by writing 0 to VIA_ATTBASE, it screws things up
75*4882a593Smuzhiyun * during reinitialization.
76*4882a593Smuzhiyun */
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun
via_tlbflush(struct agp_memory * mem)80*4882a593Smuzhiyun static void via_tlbflush(struct agp_memory *mem)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun u32 temp;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun pci_read_config_dword(agp_bridge->dev, VIA_GARTCTRL, &temp);
85*4882a593Smuzhiyun temp |= (1<<7);
86*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
87*4882a593Smuzhiyun temp &= ~(1<<7);
88*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun static const struct aper_size_info_8 via_generic_sizes[9] =
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun {256, 65536, 6, 0},
95*4882a593Smuzhiyun {128, 32768, 5, 128},
96*4882a593Smuzhiyun {64, 16384, 4, 192},
97*4882a593Smuzhiyun {32, 8192, 3, 224},
98*4882a593Smuzhiyun {16, 4096, 2, 240},
99*4882a593Smuzhiyun {8, 2048, 1, 248},
100*4882a593Smuzhiyun {4, 1024, 0, 252},
101*4882a593Smuzhiyun {2, 512, 0, 254},
102*4882a593Smuzhiyun {1, 256, 0, 255}
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun
via_fetch_size_agp3(void)106*4882a593Smuzhiyun static int via_fetch_size_agp3(void)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun int i;
109*4882a593Smuzhiyun u16 temp;
110*4882a593Smuzhiyun struct aper_size_info_16 *values;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
113*4882a593Smuzhiyun pci_read_config_word(agp_bridge->dev, VIA_AGP3_APSIZE, &temp);
114*4882a593Smuzhiyun temp &= 0xfff;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
117*4882a593Smuzhiyun if (temp == values[i].size_value) {
118*4882a593Smuzhiyun agp_bridge->previous_size =
119*4882a593Smuzhiyun agp_bridge->current_size = (void *) (values + i);
120*4882a593Smuzhiyun agp_bridge->aperture_size_idx = i;
121*4882a593Smuzhiyun return values[i].size;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun
via_configure_agp3(void)128*4882a593Smuzhiyun static int via_configure_agp3(void)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun u32 temp;
131*4882a593Smuzhiyun struct aper_size_info_16 *current_size;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun current_size = A_SIZE_16(agp_bridge->current_size);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* address to map to */
136*4882a593Smuzhiyun agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
137*4882a593Smuzhiyun AGP_APERTURE_BAR);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* attbase - aperture GATT base */
140*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE,
141*4882a593Smuzhiyun agp_bridge->gatt_bus_addr & 0xfffff000);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch
144*4882a593Smuzhiyun * translation table first.
145*4882a593Smuzhiyun * 2. Enable AGP aperture in RX91<0>. This bit controls the enabling of the
146*4882a593Smuzhiyun * graphics AGP aperture for the AGP3.0 port.
147*4882a593Smuzhiyun */
148*4882a593Smuzhiyun pci_read_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, &temp);
149*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7));
150*4882a593Smuzhiyun return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun
via_cleanup_agp3(void)154*4882a593Smuzhiyun static void via_cleanup_agp3(void)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun struct aper_size_info_16 *previous_size;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun previous_size = A_SIZE_16(agp_bridge->previous_size);
159*4882a593Smuzhiyun pci_write_config_byte(agp_bridge->dev, VIA_APSIZE, previous_size->size_value);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun
via_tlbflush_agp3(struct agp_memory * mem)163*4882a593Smuzhiyun static void via_tlbflush_agp3(struct agp_memory *mem)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun u32 temp;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun pci_read_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, &temp);
168*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp & ~(1<<7));
169*4882a593Smuzhiyun pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun static const struct agp_bridge_driver via_agp3_driver = {
174*4882a593Smuzhiyun .owner = THIS_MODULE,
175*4882a593Smuzhiyun .aperture_sizes = agp3_generic_sizes,
176*4882a593Smuzhiyun .size_type = U8_APER_SIZE,
177*4882a593Smuzhiyun .num_aperture_sizes = 10,
178*4882a593Smuzhiyun .needs_scratch_page = true,
179*4882a593Smuzhiyun .configure = via_configure_agp3,
180*4882a593Smuzhiyun .fetch_size = via_fetch_size_agp3,
181*4882a593Smuzhiyun .cleanup = via_cleanup_agp3,
182*4882a593Smuzhiyun .tlb_flush = via_tlbflush_agp3,
183*4882a593Smuzhiyun .mask_memory = agp_generic_mask_memory,
184*4882a593Smuzhiyun .masks = NULL,
185*4882a593Smuzhiyun .agp_enable = agp_generic_enable,
186*4882a593Smuzhiyun .cache_flush = global_cache_flush,
187*4882a593Smuzhiyun .create_gatt_table = agp_generic_create_gatt_table,
188*4882a593Smuzhiyun .free_gatt_table = agp_generic_free_gatt_table,
189*4882a593Smuzhiyun .insert_memory = agp_generic_insert_memory,
190*4882a593Smuzhiyun .remove_memory = agp_generic_remove_memory,
191*4882a593Smuzhiyun .alloc_by_type = agp_generic_alloc_by_type,
192*4882a593Smuzhiyun .free_by_type = agp_generic_free_by_type,
193*4882a593Smuzhiyun .agp_alloc_page = agp_generic_alloc_page,
194*4882a593Smuzhiyun .agp_alloc_pages = agp_generic_alloc_pages,
195*4882a593Smuzhiyun .agp_destroy_page = agp_generic_destroy_page,
196*4882a593Smuzhiyun .agp_destroy_pages = agp_generic_destroy_pages,
197*4882a593Smuzhiyun .agp_type_to_mask_type = agp_generic_type_to_mask_type,
198*4882a593Smuzhiyun };
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun static const struct agp_bridge_driver via_driver = {
201*4882a593Smuzhiyun .owner = THIS_MODULE,
202*4882a593Smuzhiyun .aperture_sizes = via_generic_sizes,
203*4882a593Smuzhiyun .size_type = U8_APER_SIZE,
204*4882a593Smuzhiyun .num_aperture_sizes = 9,
205*4882a593Smuzhiyun .needs_scratch_page = true,
206*4882a593Smuzhiyun .configure = via_configure,
207*4882a593Smuzhiyun .fetch_size = via_fetch_size,
208*4882a593Smuzhiyun .cleanup = via_cleanup,
209*4882a593Smuzhiyun .tlb_flush = via_tlbflush,
210*4882a593Smuzhiyun .mask_memory = agp_generic_mask_memory,
211*4882a593Smuzhiyun .masks = NULL,
212*4882a593Smuzhiyun .agp_enable = agp_generic_enable,
213*4882a593Smuzhiyun .cache_flush = global_cache_flush,
214*4882a593Smuzhiyun .create_gatt_table = agp_generic_create_gatt_table,
215*4882a593Smuzhiyun .free_gatt_table = agp_generic_free_gatt_table,
216*4882a593Smuzhiyun .insert_memory = agp_generic_insert_memory,
217*4882a593Smuzhiyun .remove_memory = agp_generic_remove_memory,
218*4882a593Smuzhiyun .alloc_by_type = agp_generic_alloc_by_type,
219*4882a593Smuzhiyun .free_by_type = agp_generic_free_by_type,
220*4882a593Smuzhiyun .agp_alloc_page = agp_generic_alloc_page,
221*4882a593Smuzhiyun .agp_alloc_pages = agp_generic_alloc_pages,
222*4882a593Smuzhiyun .agp_destroy_page = agp_generic_destroy_page,
223*4882a593Smuzhiyun .agp_destroy_pages = agp_generic_destroy_pages,
224*4882a593Smuzhiyun .agp_type_to_mask_type = agp_generic_type_to_mask_type,
225*4882a593Smuzhiyun };
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun static struct agp_device_ids via_agp_device_ids[] =
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_82C597_0,
231*4882a593Smuzhiyun .chipset_name = "Apollo VP3",
232*4882a593Smuzhiyun },
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_82C598_0,
236*4882a593Smuzhiyun .chipset_name = "Apollo MVP3",
237*4882a593Smuzhiyun },
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8501_0,
241*4882a593Smuzhiyun .chipset_name = "Apollo MVP4",
242*4882a593Smuzhiyun },
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /* VT8601 */
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8601_0,
247*4882a593Smuzhiyun .chipset_name = "Apollo ProMedia/PLE133Ta",
248*4882a593Smuzhiyun },
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* VT82C693A / VT28C694T */
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_82C691_0,
253*4882a593Smuzhiyun .chipset_name = "Apollo Pro 133",
254*4882a593Smuzhiyun },
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8371_0,
258*4882a593Smuzhiyun .chipset_name = "KX133",
259*4882a593Smuzhiyun },
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* VT8633 */
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8633_0,
264*4882a593Smuzhiyun .chipset_name = "Pro 266",
265*4882a593Smuzhiyun },
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_XN266,
269*4882a593Smuzhiyun .chipset_name = "Apollo Pro266",
270*4882a593Smuzhiyun },
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* VT8361 */
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8361,
275*4882a593Smuzhiyun .chipset_name = "KLE133",
276*4882a593Smuzhiyun },
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /* VT8365 / VT8362 */
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8363_0,
281*4882a593Smuzhiyun .chipset_name = "Twister-K/KT133x/KM133",
282*4882a593Smuzhiyun },
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /* VT8753A */
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8753_0,
287*4882a593Smuzhiyun .chipset_name = "P4X266",
288*4882a593Smuzhiyun },
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /* VT8366 */
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8367_0,
293*4882a593Smuzhiyun .chipset_name = "KT266/KY266x/KT333",
294*4882a593Smuzhiyun },
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /* VT8633 (for CuMine/ Celeron) */
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8653_0,
299*4882a593Smuzhiyun .chipset_name = "Pro266T",
300*4882a593Smuzhiyun },
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /* KM266 / PM266 */
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_XM266,
305*4882a593Smuzhiyun .chipset_name = "PM266/KM266",
306*4882a593Smuzhiyun },
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /* CLE266 */
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_862X_0,
311*4882a593Smuzhiyun .chipset_name = "CLE266",
312*4882a593Smuzhiyun },
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8377_0,
316*4882a593Smuzhiyun .chipset_name = "KT400/KT400A/KT600",
317*4882a593Smuzhiyun },
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /* VT8604 / VT8605 / VT8603
320*4882a593Smuzhiyun * (Apollo Pro133A chipset with S3 Savage4) */
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8605_0,
323*4882a593Smuzhiyun .chipset_name = "ProSavage PM133/PL133/PN133"
324*4882a593Smuzhiyun },
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /* P4M266x/P4N266 */
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8703_51_0,
329*4882a593Smuzhiyun .chipset_name = "P4M266x/P4N266",
330*4882a593Smuzhiyun },
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* VT8754 */
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8754C_0,
335*4882a593Smuzhiyun .chipset_name = "PT800",
336*4882a593Smuzhiyun },
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun /* P4X600 */
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8763_0,
341*4882a593Smuzhiyun .chipset_name = "P4X600"
342*4882a593Smuzhiyun },
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* KM400 */
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8378_0,
347*4882a593Smuzhiyun .chipset_name = "KM400/KM400A",
348*4882a593Smuzhiyun },
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /* PT880 */
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_PT880,
353*4882a593Smuzhiyun .chipset_name = "PT880",
354*4882a593Smuzhiyun },
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /* PT880 Ultra */
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_PT880ULTRA,
359*4882a593Smuzhiyun .chipset_name = "PT880 Ultra",
360*4882a593Smuzhiyun },
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun /* PT890 */
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_8783_0,
365*4882a593Smuzhiyun .chipset_name = "PT890",
366*4882a593Smuzhiyun },
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* PM800/PN800/PM880/PN880 */
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_PX8X0_0,
371*4882a593Smuzhiyun .chipset_name = "PM800/PN800/PM880/PN880",
372*4882a593Smuzhiyun },
373*4882a593Smuzhiyun /* KT880 */
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_3269_0,
376*4882a593Smuzhiyun .chipset_name = "KT880",
377*4882a593Smuzhiyun },
378*4882a593Smuzhiyun /* KTxxx/Px8xx */
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_83_87XX_1,
381*4882a593Smuzhiyun .chipset_name = "VT83xx/VT87xx/KTxxx/Px8xx",
382*4882a593Smuzhiyun },
383*4882a593Smuzhiyun /* P4M800 */
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_3296_0,
386*4882a593Smuzhiyun .chipset_name = "P4M800",
387*4882a593Smuzhiyun },
388*4882a593Smuzhiyun /* P4M800CE */
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_P4M800CE,
391*4882a593Smuzhiyun .chipset_name = "VT3314",
392*4882a593Smuzhiyun },
393*4882a593Smuzhiyun /* VT3324 / CX700 */
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_VT3324,
396*4882a593Smuzhiyun .chipset_name = "CX700",
397*4882a593Smuzhiyun },
398*4882a593Smuzhiyun /* VT3336 - this is a chipset for AMD Athlon/K8 CPU. Due to K8's unique
399*4882a593Smuzhiyun * architecture, the AGP resource and behavior are different from
400*4882a593Smuzhiyun * the traditional AGP which resides only in chipset. AGP is used
401*4882a593Smuzhiyun * by 3D driver which wasn't available for the VT3336 and VT3364
402*4882a593Smuzhiyun * generation until now. Unfortunately, by testing, VT3364 works
403*4882a593Smuzhiyun * but VT3336 doesn't. - explanation from via, just leave this as
404*4882a593Smuzhiyun * as a placeholder to avoid future patches adding it back in.
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyun #if 0
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_VT3336,
409*4882a593Smuzhiyun .chipset_name = "VT3336",
410*4882a593Smuzhiyun },
411*4882a593Smuzhiyun #endif
412*4882a593Smuzhiyun /* P4M890 */
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_P4M890,
415*4882a593Smuzhiyun .chipset_name = "P4M890",
416*4882a593Smuzhiyun },
417*4882a593Smuzhiyun /* P4M900 */
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun .device_id = PCI_DEVICE_ID_VIA_VT3364,
420*4882a593Smuzhiyun .chipset_name = "P4M900",
421*4882a593Smuzhiyun },
422*4882a593Smuzhiyun { }, /* dummy final entry, always present */
423*4882a593Smuzhiyun };
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /*
427*4882a593Smuzhiyun * VIA's AGP3 chipsets do magick to put the AGP bridge compliant
428*4882a593Smuzhiyun * with the same standards version as the graphics card.
429*4882a593Smuzhiyun */
check_via_agp3(struct agp_bridge_data * bridge)430*4882a593Smuzhiyun static void check_via_agp3 (struct agp_bridge_data *bridge)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun u8 reg;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun pci_read_config_byte(bridge->dev, VIA_AGPSEL, ®);
435*4882a593Smuzhiyun /* Check AGP 2.0 compatibility mode. */
436*4882a593Smuzhiyun if ((reg & (1<<1))==0)
437*4882a593Smuzhiyun bridge->driver = &via_agp3_driver;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun
agp_via_probe(struct pci_dev * pdev,const struct pci_device_id * ent)441*4882a593Smuzhiyun static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun struct agp_device_ids *devs = via_agp_device_ids;
444*4882a593Smuzhiyun struct agp_bridge_data *bridge;
445*4882a593Smuzhiyun int j = 0;
446*4882a593Smuzhiyun u8 cap_ptr;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
449*4882a593Smuzhiyun if (!cap_ptr)
450*4882a593Smuzhiyun return -ENODEV;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun j = ent - agp_via_pci_table;
453*4882a593Smuzhiyun printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun bridge = agp_alloc_bridge();
456*4882a593Smuzhiyun if (!bridge)
457*4882a593Smuzhiyun return -ENOMEM;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun bridge->dev = pdev;
460*4882a593Smuzhiyun bridge->capndx = cap_ptr;
461*4882a593Smuzhiyun bridge->driver = &via_driver;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /*
464*4882a593Smuzhiyun * Garg, there are KT400s with KT266 IDs.
465*4882a593Smuzhiyun */
466*4882a593Smuzhiyun if (pdev->device == PCI_DEVICE_ID_VIA_8367_0) {
467*4882a593Smuzhiyun /* Is there a KT400 subsystem ? */
468*4882a593Smuzhiyun if (pdev->subsystem_device == PCI_DEVICE_ID_VIA_8377_0) {
469*4882a593Smuzhiyun printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n");
470*4882a593Smuzhiyun check_via_agp3(bridge);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun /* If this is an AGP3 bridge, check which mode its in and adjust. */
475*4882a593Smuzhiyun get_agp_version(bridge);
476*4882a593Smuzhiyun if (bridge->major_version >= 3)
477*4882a593Smuzhiyun check_via_agp3(bridge);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Fill in the mode register */
480*4882a593Smuzhiyun pci_read_config_dword(pdev,
481*4882a593Smuzhiyun bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun pci_set_drvdata(pdev, bridge);
484*4882a593Smuzhiyun return agp_add_bridge(bridge);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
agp_via_remove(struct pci_dev * pdev)487*4882a593Smuzhiyun static void agp_via_remove(struct pci_dev *pdev)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun agp_remove_bridge(bridge);
492*4882a593Smuzhiyun agp_put_bridge(bridge);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun #ifdef CONFIG_PM
496*4882a593Smuzhiyun
agp_via_suspend(struct pci_dev * pdev,pm_message_t state)497*4882a593Smuzhiyun static int agp_via_suspend(struct pci_dev *pdev, pm_message_t state)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun pci_save_state (pdev);
500*4882a593Smuzhiyun pci_set_power_state (pdev, PCI_D3hot);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun return 0;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
agp_via_resume(struct pci_dev * pdev)505*4882a593Smuzhiyun static int agp_via_resume(struct pci_dev *pdev)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun pci_set_power_state (pdev, PCI_D0);
510*4882a593Smuzhiyun pci_restore_state(pdev);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (bridge->driver == &via_agp3_driver)
513*4882a593Smuzhiyun return via_configure_agp3();
514*4882a593Smuzhiyun else if (bridge->driver == &via_driver)
515*4882a593Smuzhiyun return via_configure();
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun #endif /* CONFIG_PM */
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun /* must be the same order as name table above */
523*4882a593Smuzhiyun static const struct pci_device_id agp_via_pci_table[] = {
524*4882a593Smuzhiyun #define ID(x) \
525*4882a593Smuzhiyun { \
526*4882a593Smuzhiyun .class = (PCI_CLASS_BRIDGE_HOST << 8), \
527*4882a593Smuzhiyun .class_mask = ~0, \
528*4882a593Smuzhiyun .vendor = PCI_VENDOR_ID_VIA, \
529*4882a593Smuzhiyun .device = x, \
530*4882a593Smuzhiyun .subvendor = PCI_ANY_ID, \
531*4882a593Smuzhiyun .subdevice = PCI_ANY_ID, \
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_82C597_0),
534*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_82C598_0),
535*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8501_0),
536*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8601_0),
537*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_82C691_0),
538*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8371_0),
539*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8633_0),
540*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_XN266),
541*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8361),
542*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8363_0),
543*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8753_0),
544*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8367_0),
545*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8653_0),
546*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_XM266),
547*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_862X_0),
548*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8377_0),
549*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8605_0),
550*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8703_51_0),
551*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8754C_0),
552*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8763_0),
553*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8378_0),
554*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_PT880),
555*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_PT880ULTRA),
556*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_8783_0),
557*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_PX8X0_0),
558*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_3269_0),
559*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_83_87XX_1),
560*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_3296_0),
561*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_P4M800CE),
562*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_VT3324),
563*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_P4M890),
564*4882a593Smuzhiyun ID(PCI_DEVICE_ID_VIA_VT3364),
565*4882a593Smuzhiyun { }
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, agp_via_pci_table);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun static struct pci_driver agp_via_pci_driver = {
572*4882a593Smuzhiyun .name = "agpgart-via",
573*4882a593Smuzhiyun .id_table = agp_via_pci_table,
574*4882a593Smuzhiyun .probe = agp_via_probe,
575*4882a593Smuzhiyun .remove = agp_via_remove,
576*4882a593Smuzhiyun #ifdef CONFIG_PM
577*4882a593Smuzhiyun .suspend = agp_via_suspend,
578*4882a593Smuzhiyun .resume = agp_via_resume,
579*4882a593Smuzhiyun #endif
580*4882a593Smuzhiyun };
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun
agp_via_init(void)583*4882a593Smuzhiyun static int __init agp_via_init(void)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun if (agp_off)
586*4882a593Smuzhiyun return -EINVAL;
587*4882a593Smuzhiyun return pci_register_driver(&agp_via_pci_driver);
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
agp_via_cleanup(void)590*4882a593Smuzhiyun static void __exit agp_via_cleanup(void)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun pci_unregister_driver(&agp_via_pci_driver);
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun module_init(agp_via_init);
596*4882a593Smuzhiyun module_exit(agp_via_cleanup);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun MODULE_LICENSE("GPL");
599*4882a593Smuzhiyun MODULE_AUTHOR("Dave Jones");
600