]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/video/via/via-core.c
via: Do not attempt I/O on inactive I2C adapters
[mv-sheeva.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  * Create our subsidiary devices.
195  */
196 static struct viafb_subdev_info {
197         char *name;
198         struct platform_device *platdev;
199 } viafb_subdevs[] = {
200         {
201                 .name = "viafb-gpio",
202         },
203         {
204                 .name = "viafb-i2c",
205         }
206 };
207 #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
208
209 static int __devinit via_create_subdev(struct viafb_dev *vdev,
210                 struct viafb_subdev_info *info)
211 {
212         int ret;
213
214         info->platdev = platform_device_alloc(info->name, -1);
215         if (!info->platdev) {
216                 dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
217                         info->name);
218                 return -ENOMEM;
219         }
220         info->platdev->dev.parent = &vdev->pdev->dev;
221         info->platdev->dev.platform_data = vdev;
222         ret = platform_device_add(info->platdev);
223         if (ret) {
224                 dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
225                                 info->name);
226                 platform_device_put(info->platdev);
227                 info->platdev = NULL;
228         }
229         return ret;
230 }
231
232 static int __devinit via_setup_subdevs(struct viafb_dev *vdev)
233 {
234         int i;
235
236         /*
237          * Ignore return values.  Even if some of the devices
238          * fail to be created, we'll still be able to use some
239          * of the rest.
240          */
241         for (i = 0; i < N_SUBDEVS; i++)
242                 via_create_subdev(vdev, viafb_subdevs + i);
243         return 0;
244 }
245
246 static void __devexit via_teardown_subdevs(void)
247 {
248         int i;
249
250         for (i = 0; i < N_SUBDEVS; i++)
251                 if (viafb_subdevs[i].platdev) {
252                         viafb_subdevs[i].platdev->dev.platform_data = NULL;
253                         platform_device_unregister(viafb_subdevs[i].platdev);
254                 }
255 }
256
257
258 static int __devinit via_pci_probe(struct pci_dev *pdev,
259                 const struct pci_device_id *ent)
260 {
261         int ret;
262
263         ret = pci_enable_device(pdev);
264         if (ret)
265                 return ret;
266         /*
267          * Global device initialization.
268          */
269         memset(&global_dev, 0, sizeof(global_dev));
270         global_dev.pdev = pdev;
271         global_dev.chip_type = ent->driver_data;
272         global_dev.port_cfg = adap_configs;
273         spin_lock_init(&global_dev.reg_lock);
274         ret = via_pci_setup_mmio(&global_dev);
275         if (ret)
276                 goto out_disable;
277         /*
278          * Create our subdevices.  Continue even if some things fail.
279          */
280         via_setup_subdevs(&global_dev);
281         /*
282          * Set up the framebuffer.
283          */
284         ret = via_fb_pci_probe(&global_dev);
285         if (ret)
286                 goto out_subdevs;
287         return 0;
288
289 out_subdevs:
290         via_teardown_subdevs();
291         via_pci_teardown_mmio(&global_dev);
292 out_disable:
293         pci_disable_device(pdev);
294         return ret;
295 }
296
297 static void __devexit via_pci_remove(struct pci_dev *pdev)
298 {
299         via_teardown_subdevs();
300         via_fb_pci_remove(pdev);
301         via_pci_teardown_mmio(&global_dev);
302         pci_disable_device(pdev);
303 }
304
305
306 static struct pci_device_id via_pci_table[] __devinitdata = {
307         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
308           .driver_data = UNICHROME_CLE266 },
309         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
310           .driver_data = UNICHROME_PM800 },
311         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
312           .driver_data = UNICHROME_K400 },
313         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
314           .driver_data = UNICHROME_K800 },
315         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
316           .driver_data = UNICHROME_CN700 },
317         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
318           .driver_data = UNICHROME_K8M890 },
319         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
320           .driver_data = UNICHROME_CX700 },
321         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
322           .driver_data = UNICHROME_P4M900 },
323         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
324           .driver_data = UNICHROME_CN750 },
325         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
326           .driver_data = UNICHROME_VX800 },
327         { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
328           .driver_data = UNICHROME_VX855 },
329         { }
330 };
331 MODULE_DEVICE_TABLE(pci, via_pci_table);
332
333 static struct pci_driver via_driver = {
334         .name           = "viafb",
335         .id_table       = via_pci_table,
336         .probe          = via_pci_probe,
337         .remove         = __devexit_p(via_pci_remove),
338 };
339
340 static int __init via_core_init(void)
341 {
342         int ret;
343
344         ret = viafb_init();
345         if (ret)
346                 return ret;
347         viafb_i2c_init();
348         viafb_gpio_init();
349         return pci_register_driver(&via_driver);
350 }
351
352 static void __exit via_core_exit(void)
353 {
354         pci_unregister_driver(&via_driver);
355         viafb_gpio_exit();
356         viafb_i2c_exit();
357         viafb_exit();
358 }
359
360 module_init(via_core_init);
361 module_exit(via_core_exit);