2 * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys.
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.
7 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/types.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>
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>
29 #include <asm/sgi/ip22.h>
30 #include <asm/sgi/hpc3.h>
31 #include <asm/sgi/mc.h>
37 #define DEBUG(x...) printk(x);
43 /* VINO ASIC registers */
44 struct sgi_vino
*vino
;
46 static const char *vinostr
= "VINO IndyCam/TV";
47 static int threshold_a
= 512;
48 static int threshold_b
= 512;
51 struct video_device vdev
;
58 struct i2c_client
*driver
;
63 struct vino_device chA
;
64 struct vino_device chB
;
66 struct vino_client decoder
;
67 struct vino_client camera
;
69 struct semaphore input_lock
;
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)));
77 static struct vino_video
*Vino
;
79 unsigned i2c_vino_getctrl(void *data
)
81 return vino
->i2c_control
;
84 void i2c_vino_setctrl(void *data
, unsigned val
)
86 vino
->i2c_control
= val
;
89 unsigned i2c_vino_rdata(void *data
)
91 return vino
->i2c_data
;
94 void i2c_vino_wdata(void *data
, unsigned val
)
99 static struct i2c_algo_sgi_data i2c_sgi_vino_data
=
101 .getctrl
= &i2c_vino_getctrl
,
102 .setctrl
= &i2c_vino_setctrl
,
103 .rdata
= &i2c_vino_rdata
,
104 .wdata
= &i2c_vino_wdata
,
110 * There are two possible clients on VINO I2C bus, so we limit usage only
113 static int i2c_vino_client_reg(struct i2c_client
*client
)
117 down(&Vino
->input_lock
);
118 switch (client
->driver
->id
) {
119 case I2C_DRIVERID_SAA7191
:
120 if (Vino
->decoder
.driver
)
123 Vino
->decoder
.driver
= client
;
125 case I2C_DRIVERID_INDYCAM
:
126 if (Vino
->camera
.driver
)
129 Vino
->camera
.driver
= client
;
134 up(&Vino
->input_lock
);
139 static int i2c_vino_client_unreg(struct i2c_client
*client
)
143 down(&Vino
->input_lock
);
144 if (client
== Vino
->decoder
.driver
) {
145 if (Vino
->decoder
.owner
)
148 Vino
->decoder
.driver
= NULL
;
149 } else if (client
== Vino
->camera
.driver
) {
150 if (Vino
->camera
.owner
)
153 Vino
->camera
.driver
= NULL
;
155 up(&Vino
->input_lock
);
160 static struct i2c_adapter vino_i2c_adapter
=
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
,
169 static int vino_i2c_add_bus(void)
171 return i2c_sgi_add_bus(&vino_i2c_adapter
);
174 static int vino_i2c_del_bus(void)
176 return i2c_sgi_del_bus(&vino_i2c_adapter
);
180 static void vino_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
184 static int vino_open(struct video_device
*dev
, int flags
)
186 struct vino_device
*videv
= (struct vino_device
*)dev
;
191 static void vino_close(struct video_device
*dev
)
193 struct vino_device
*videv
= (struct vino_device
*)dev
;
196 static int vino_mmap(struct video_device
*dev
, const char *adr
,
199 struct vino_device
*videv
= (struct vino_device
*)dev
;
204 static int vino_ioctl(struct video_device
*dev
, unsigned int cmd
, void *arg
)
206 struct vino_device
*videv
= (struct vino_device
*)dev
;
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
,
222 static int __init
vino_init(void)
227 /* VINO is Indy specific beast */
228 if (ip22_is_fullhouse())
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.
235 * If EISA_PRESENT is not set we definitely don't have a VINO equiped
238 if (!(sgimc
->systemid
& SGIMC_SYSID_EPRESENT
)) {
239 printk(KERN_ERR
"VINO not found\n");
243 vino
= (struct sgi_vino
*)ioremap(VINO_BASE
, sizeof(struct sgi_vino
));
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");
254 if (VINO_ID_VALUE(rev
) != VINO_CHIP_ID
) {
255 printk(KERN_ERR
"VINO is not VINO (Rev/ID: 0x%04lx)\n", rev
);
259 printk(KERN_INFO
"VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev
));
261 Vino
= (struct vino_video
*)
262 kmalloc(sizeof(struct vino_video
), GFP_KERNEL
);
268 Vino
->dummy_page
= get_zeroed_page(GFP_KERNEL
| GFP_DMA
);
269 if (!Vino
->dummy_page
) {
273 for (i
= 0; i
< 4; i
++)
274 Vino
->dummy_buf
[i
] = PHYSADDR(Vino
->dummy_page
);
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
);
281 vino
->intr_status
= 0;
282 /* set threshold level */
283 vino
->a
.fifo_thres
= threshold_a
;
284 vino
->b
.fifo_thres
= threshold_b
;
286 init_MUTEX(&Vino
->input_lock
);
288 if (request_irq(SGI_VINO_IRQ
, vino_interrupt
, 0, vinostr
, NULL
)) {
289 printk(KERN_ERR
"VINO: irq%02d registration failed\n",
295 ret
= vino_i2c_add_bus();
297 printk(KERN_ERR
"VINO: I2C bus registration failed\n");
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
);
305 goto out_i2c_del_bus
;
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
);
311 goto out_unregister_vdev
;
317 video_unregister_device(&Vino
->chA
.vdev
);
321 free_irq(SGI_VINO_IRQ
, NULL
);
323 free_page(Vino
->dummy_page
);
332 static void __exit
vino_exit(void)
334 video_unregister_device(&Vino
->chA
.vdev
);
335 video_unregister_device(&Vino
->chB
.vdev
);
337 free_irq(SGI_VINO_IRQ
, NULL
);
338 free_page(Vino
->dummy_page
);
343 module_init(vino_init
);
344 module_exit(vino_exit
);
346 MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)");
347 MODULE_LICENSE("GPL");