vserver 1.9.5.x5
[linux-2.6.git] / drivers / media / video / vino.c
1 /*
2  * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys.
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License version 2 as published by the Free Software Foundation.
6  *
7  * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
8  */
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/types.h>
13 #include <linux/mm.h>
14 #include <linux/slab.h>
15 #include <linux/wrapper.h>
16 #include <linux/errno.h>
17 #include <linux/irq.h>
18 #include <linux/delay.h>
19 #include <linux/videodev.h>
20 #include <linux/i2c.h>
21 #include <linux/i2c-algo-sgi.h>
22
23 #include <asm/addrspace.h>
24 #include <asm/system.h>
25 #include <asm/bootinfo.h>
26 #include <asm/pgtable.h>
27 #include <asm/paccess.h>
28 #include <asm/io.h>
29 #include <asm/sgi/ip22.h>
30 #include <asm/sgi/hpc3.h>
31 #include <asm/sgi/mc.h>
32
33 #include "vino.h"
34
35 /* debugging? */
36 #if 1
37 #define DEBUG(x...)     printk(x);
38 #else
39 #define DEBUG(x...)
40 #endif
41
42
43 /* VINO ASIC registers */
44 struct sgi_vino *vino;
45
46 static const char *vinostr = "VINO IndyCam/TV";
47 static int threshold_a = 512;
48 static int threshold_b = 512;
49
50 struct vino_device {
51         struct video_device vdev;
52 #define VINO_CHAN_A             1
53 #define VINO_CHAN_B             2
54         int chan;
55 };
56
57 struct vino_client {
58         struct i2c_client *driver;
59         int owner;
60 };
61
62 struct vino_video {
63         struct vino_device chA;
64         struct vino_device chB;
65
66         struct vino_client decoder;
67         struct vino_client camera;
68
69         struct semaphore input_lock;
70
71         /* Loaded into VINO descriptors to clear End Of Descriptors table
72          * interupt condition */
73         unsigned long dummy_page;
74         unsigned int dummy_buf[4] __attribute__((aligned(8)));
75 };
76
77 static struct vino_video *Vino;
78
79 unsigned i2c_vino_getctrl(void *data)
80 {
81         return vino->i2c_control;
82 }
83
84 void i2c_vino_setctrl(void *data, unsigned val)
85 {
86         vino->i2c_control = val;
87 }
88
89 unsigned i2c_vino_rdata(void *data)
90 {
91         return vino->i2c_data;
92 }
93
94 void i2c_vino_wdata(void *data, unsigned val)
95 {
96         vino->i2c_data = val;
97 }
98
99 static struct i2c_algo_sgi_data i2c_sgi_vino_data =
100 {
101         .getctrl = &i2c_vino_getctrl,
102         .setctrl = &i2c_vino_setctrl,
103         .rdata   = &i2c_vino_rdata,
104         .wdata   = &i2c_vino_wdata,
105         .xfer_timeout = 200,
106         .ack_timeout  = 1000,
107 };
108
109 /*
110  * There are two possible clients on VINO I2C bus, so we limit usage only
111  * to them.
112  */
113 static int i2c_vino_client_reg(struct i2c_client *client)
114 {
115         int res = 0;
116
117         down(&Vino->input_lock);
118         switch (client->driver->id) {
119         case I2C_DRIVERID_SAA7191:
120                 if (Vino->decoder.driver)
121                         res = -EBUSY;
122                 else
123                         Vino->decoder.driver = client;
124                 break;
125         case I2C_DRIVERID_INDYCAM:
126                 if (Vino->camera.driver)
127                         res = -EBUSY;
128                 else
129                         Vino->camera.driver = client;
130                 break;
131         default:
132                 res = -ENODEV;
133         }
134         up(&Vino->input_lock);
135
136         return res;
137 }
138
139 static int i2c_vino_client_unreg(struct i2c_client *client)
140 {
141         int res = 0;
142
143         down(&Vino->input_lock);
144         if (client == Vino->decoder.driver) {
145                 if (Vino->decoder.owner)
146                         res = -EBUSY;
147                 else
148                         Vino->decoder.driver = NULL;
149         } else if (client == Vino->camera.driver) {
150                 if (Vino->camera.owner)
151                         res = -EBUSY;
152                 else
153                         Vino->camera.driver = NULL;
154         }
155         up(&Vino->input_lock);
156
157         return res;
158 }
159
160 static struct i2c_adapter vino_i2c_adapter =
161 {
162         .name                   = "VINO I2C bus",
163         .id                     = I2C_HW_SGI_VINO,
164         .algo_data              = &i2c_sgi_vino_data,
165         .client_register        = &i2c_vino_client_reg,
166         .client_unregister      = &i2c_vino_client_unreg,
167 };
168
169 static int vino_i2c_add_bus(void)
170 {
171         return i2c_sgi_add_bus(&vino_i2c_adapter);
172 }
173
174 static int vino_i2c_del_bus(void)
175 {
176         return i2c_sgi_del_bus(&vino_i2c_adapter);
177 }
178
179
180 static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
181 {
182 }
183
184 static int vino_open(struct video_device *dev, int flags)
185 {
186         struct vino_device *videv = (struct vino_device *)dev;
187
188         return 0;
189 }
190
191 static void vino_close(struct video_device *dev)
192 {
193         struct vino_device *videv = (struct vino_device *)dev;
194 }
195
196 static int vino_mmap(struct video_device *dev, const char *adr,
197                      unsigned long size)
198 {
199         struct vino_device *videv = (struct vino_device *)dev;
200
201         return -EINVAL;
202 }
203
204 static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
205 {
206         struct vino_device *videv = (struct vino_device *)dev;
207
208         return -EINVAL;
209 }
210
211 static const struct video_device vino_device = {
212         .owner          = THIS_MODULE,
213         .type           = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE,
214         .hardware       = VID_HARDWARE_VINO,
215         .name           = "VINO",
216         .open           = vino_open,
217         .close          = vino_close,
218         .ioctl          = vino_ioctl,
219         .mmap           = vino_mmap,
220 };
221
222 static int __init vino_init(void)
223 {
224         unsigned long rev;
225         int i, ret = 0;
226
227         /* VINO is Indy specific beast */
228         if (ip22_is_fullhouse())
229                 return -ENODEV;
230
231         /*
232          * VINO is in the EISA address space, so the sysid register will tell
233          * us if the EISA_PRESENT pin on MC has been pulled low.
234          *
235          * If EISA_PRESENT is not set we definitely don't have a VINO equiped
236          * system.
237          */
238         if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
239                 printk(KERN_ERR "VINO not found\n");
240                 return -ENODEV;
241         }
242
243         vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
244         if (!vino)
245                 return -EIO;
246
247         /* Okay, once we know that VINO is present we'll read its revision
248          * safe way. One never knows... */
249         if (get_dbe(rev, &(vino->rev_id))) {
250                 printk(KERN_ERR "VINO: failed to read revision register\n");
251                 ret = -ENODEV;
252                 goto out_unmap;
253         }
254         if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) {
255                 printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev);
256                 ret = -ENODEV;
257                 goto out_unmap;
258         }
259         printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev));
260
261         Vino = (struct vino_video *)
262                 kmalloc(sizeof(struct vino_video), GFP_KERNEL);
263         if (!Vino) {
264                 ret = -ENOMEM;
265                 goto out_unmap;
266         }
267
268         Vino->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
269         if (!Vino->dummy_page) {
270                 ret = -ENOMEM;
271                 goto out_free_vino;
272         }
273         for (i = 0; i < 4; i++)
274                 Vino->dummy_buf[i] = PHYSADDR(Vino->dummy_page);
275
276         vino->control = 0;
277         /* prevent VINO from throwing spurious interrupts */
278         vino->a.next_4_desc = PHYSADDR(Vino->dummy_buf);
279         vino->b.next_4_desc = PHYSADDR(Vino->dummy_buf);
280         udelay(5);
281         vino->intr_status = 0;
282         /* set threshold level */
283         vino->a.fifo_thres = threshold_a;
284         vino->b.fifo_thres = threshold_b;
285
286         init_MUTEX(&Vino->input_lock);
287
288         if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) {
289                 printk(KERN_ERR "VINO: irq%02d registration failed\n",
290                        SGI_VINO_IRQ);
291                 ret = -EAGAIN;
292                 goto out_free_page;
293         }
294
295         ret = vino_i2c_add_bus();
296         if (ret) {
297                 printk(KERN_ERR "VINO: I2C bus registration failed\n");
298                 goto out_free_irq;
299         }
300
301         if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) {
302                 printk("%s, chnl %d: device registration failed.\n",
303                         Vino->chA.vdev.name, Vino->chA.chan);
304                 ret = -EINVAL;
305                 goto out_i2c_del_bus;
306         }
307         if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) {
308                 printk("%s, chnl %d: device registration failed.\n",
309                         Vino->chB.vdev.name, Vino->chB.chan);
310                 ret = -EINVAL;
311                 goto out_unregister_vdev;
312         }
313
314         return 0;
315
316 out_unregister_vdev:
317         video_unregister_device(&Vino->chA.vdev);
318 out_i2c_del_bus:
319         vino_i2c_del_bus();
320 out_free_irq:
321         free_irq(SGI_VINO_IRQ, NULL);
322 out_free_page:
323         free_page(Vino->dummy_page);
324 out_free_vino:
325         kfree(Vino);
326 out_unmap:
327         iounmap(vino);
328
329         return ret;
330 }
331
332 static void __exit vino_exit(void)
333 {
334         video_unregister_device(&Vino->chA.vdev);
335         video_unregister_device(&Vino->chB.vdev);
336         vino_i2c_del_bus();
337         free_irq(SGI_VINO_IRQ, NULL);
338         free_page(Vino->dummy_page);
339         kfree(Vino);
340         iounmap(vino);
341 }
342
343 module_init(vino_init);
344 module_exit(vino_exit);
345
346 MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)");
347 MODULE_LICENSE("GPL");