viafb: Convert GPIO and i2c to the new indexed port ops
[pandora-kernel.git] / drivers / video / via / via-core.c
1 /*
2  * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4  * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
5  */
6
7 /*
8  * Core code for the Via multifunction framebuffer device.
9  */
10 #include "via-core.h"
11 #include "via_i2c.h"
12 #include "via-gpio.h"
13 #include "global.h"
14
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17
18 /*
19  * The default port config.
20  */
21 static struct via_port_cfg adap_configs[] = {
22         [VIA_PORT_26]   = { VIA_PORT_I2C,  VIA_MODE_OFF, VIASR, 0x26 },
23         [VIA_PORT_31]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
24         [VIA_PORT_25]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
25         [VIA_PORT_2C]   = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
26         [VIA_PORT_3D]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
27         { 0, 0, 0, 0 }
28 };
29
30 /*
31  * We currently only support one viafb device (will there ever be
32  * more than one?), so just declare it globally here.
33  */
34 static struct viafb_dev global_dev;
35
36
37 /*
38  * Figure out how big our framebuffer memory is.  Kind of ugly,
39  * but evidently we can't trust the information found in the
40  * fbdev configuration area.
41  */
42 static u16 via_function3[] = {
43         CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
44         CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
45         P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3,
46 };
47
48 /* Get the BIOS-configured framebuffer size from PCI configuration space
49  * of function 3 in the respective chipset */
50 static int viafb_get_fb_size_from_pci(int chip_type)
51 {
52         int i;
53         u8 offset = 0;
54         u32 FBSize;
55         u32 VideoMemSize;
56
57         /* search for the "FUNCTION3" device in this chipset */
58         for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
59                 struct pci_dev *pdev;
60
61                 pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
62                                       NULL);
63                 if (!pdev)
64                         continue;
65
66                 DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
67
68                 switch (pdev->device) {
69                 case CLE266_FUNCTION3:
70                 case KM400_FUNCTION3:
71                         offset = 0xE0;
72                         break;
73                 case CN400_FUNCTION3:
74                 case CN700_FUNCTION3:
75                 case CX700_FUNCTION3:
76                 case KM800_FUNCTION3:
77                 case KM890_FUNCTION3:
78                 case P4M890_FUNCTION3:
79                 case P4M900_FUNCTION3:
80                 case VX800_FUNCTION3:
81                 case VX855_FUNCTION3:
82                 /*case CN750_FUNCTION3: */
83                         offset = 0xA0;
84                         break;
85                 }
86
87                 if (!offset)
88                         break;
89
90                 pci_read_config_dword(pdev, offset, &FBSize);
91                 pci_dev_put(pdev);
92         }
93
94         if (!offset) {
95                 printk(KERN_ERR "cannot determine framebuffer size\n");
96                 return -EIO;
97         }
98
99         FBSize = FBSize & 0x00007000;
100         DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
101
102         if (chip_type < UNICHROME_CX700) {
103                 switch (FBSize) {
104                 case 0x00004000:
105                         VideoMemSize = (16 << 20);      /*16M */
106                         break;
107
108                 case 0x00005000:
109                         VideoMemSize = (32 << 20);      /*32M */
110                         break;
111
112                 case 0x00006000:
113                         VideoMemSize = (64 << 20);      /*64M */
114                         break;
115
116                 default:
117                         VideoMemSize = (32 << 20);      /*32M */
118                         break;
119                 }
120         } else {
121                 switch (FBSize) {
122                 case 0x00001000:
123                         VideoMemSize = (8 << 20);       /*8M */
124                         break;
125
126                 case 0x00002000:
127                         VideoMemSize = (16 << 20);      /*16M */
128                         break;
129
130                 case 0x00003000:
131                         VideoMemSize = (32 << 20);      /*32M */
132                         break;
133
134                 case 0x00004000:
135                         VideoMemSize = (64 << 20);      /*64M */
136                         break;
137
138                 case 0x00005000:
139                         VideoMemSize = (128 << 20);     /*128M */
140                         break;
141
142                 case 0x00006000:
143                         VideoMemSize = (256 << 20);     /*256M */
144                         break;
145
146                 case 0x00007000:        /* Only on VX855/875 */
147                         VideoMemSize = (512 << 20);     /*512M */
148                         break;
149
150                 default:
151                         VideoMemSize = (32 << 20);      /*32M */
152                         break;
153                 }
154         }
155
156         return VideoMemSize;
157 }
158
159
160 /*
161  * Figure out and map our MMIO regions.
162  */
163 static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
164 {
165         /*
166          * Hook up to the device registers.
167          */
168         vdev->engine_start = pci_resource_start(vdev->pdev, 1);
169         vdev->engine_len = pci_resource_len(vdev->pdev, 1);
170         /* If this fails, others will notice later */
171         vdev->engine_mmio = ioremap_nocache(vdev->engine_start,
172                         vdev->engine_len);
173
174         /*
175          * Likewise with I/O memory.
176          */
177         vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
178         vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
179         if (vdev->fbmem_len < 0)
180                 return vdev->fbmem_len;
181         vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len);
182         if (vdev->fbmem == NULL)
183                 return -ENOMEM;
184         return 0;
185 }
186
187 static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev)
188 {
189         iounmap(vdev->fbmem);
190         iounmap(vdev->engine_mmio);
191 }
192
193
194 static int __devinit via_pci_probe(struct pci_dev *pdev,
195                 const struct pci_device_id *ent)
196 {
197         int ret;
198
199         ret = pci_enable_device(pdev);
200         if (ret)
201                 return ret;
202         /*
203          * Global device initialization.
204          */
205         memset(&global_dev, 0, sizeof(global_dev));
206         global_dev.pdev = pdev;
207         global_dev.chip_type = ent->driver_data;
208         spin_lock_init(&global_dev.reg_lock);
209         ret = via_pci_setup_mmio(&global_dev);
210         if (ret)
211                 goto out_disable;
212         /*
213          * Create the I2C busses.  Bailing out on failure seems extreme,
214          * but that's what the code did before.
215          */
216         ret = viafb_create_i2c_busses(&global_dev, adap_configs);
217         if (ret)
218                 goto out_teardown;
219         /*
220          * Set up the framebuffer.
221          */
222         ret = via_fb_pci_probe(&global_dev);
223         if (ret)
224                 goto out_i2c;
225         /*
226          * Create the GPIOs.  We continue whether or not this succeeds;
227          * the framebuffer might be useful even without GPIO ports.
228          */
229         ret = viafb_create_gpios(&global_dev, adap_configs);
230         return 0;
231
232 out_i2c:
233         viafb_delete_i2c_busses();
234 out_teardown:
235         via_pci_teardown_mmio(&global_dev);
236 out_disable:
237         pci_disable_device(pdev);
238         return ret;
239 }
240
241 static void __devexit via_pci_remove(struct pci_dev *pdev)
242 {
243         viafb_destroy_gpios();
244         viafb_delete_i2c_busses();
245         via_fb_pci_remove(pdev);
246         via_pci_teardown_mmio(&global_dev);
247         pci_disable_device(pdev);
248 }
249
250
251 static struct pci_device_id via_pci_table[] __devinitdata = {
252         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
253           .driver_data = UNICHROME_CLE266 },
254         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
255           .driver_data = UNICHROME_PM800 },
256         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
257           .driver_data = UNICHROME_K400 },
258         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
259           .driver_data = UNICHROME_K800 },
260         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
261           .driver_data = UNICHROME_CN700 },
262         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
263           .driver_data = UNICHROME_K8M890 },
264         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
265           .driver_data = UNICHROME_CX700 },
266         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
267           .driver_data = UNICHROME_P4M900 },
268         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
269           .driver_data = UNICHROME_CN750 },
270         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
271           .driver_data = UNICHROME_VX800 },
272         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
273           .driver_data = UNICHROME_VX855 },
274         { }
275 };
276 MODULE_DEVICE_TABLE(pci, via_pci_table);
277
278 static struct pci_driver via_driver = {
279         .name           = "viafb",
280         .id_table       = via_pci_table,
281         .probe          = via_pci_probe,
282         .remove         = __devexit_p(via_pci_remove),
283 };
284
285 static int __init via_core_init(void)
286 {
287         int ret;
288
289         ret = viafb_init();
290         if (ret)
291                 return ret;
292         return pci_register_driver(&via_driver);
293 }
294
295 static void __exit via_core_exit(void)
296 {
297         pci_unregister_driver(&via_driver);
298         viafb_exit();
299 }
300
301 module_init(via_core_init);
302 module_exit(via_core_exit);