File: /usr/src/linux/drivers/media/video/vino.c

1     /* $Id: vino.c,v 1.5 1999/10/09 00:01:14 ralf Exp $
2      * drivers/char/vino.c
3      *
4      * (incomplete) Driver for the Vino Video input system found in SGI Indys.
5      *
6      * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
7      *
8      * This isn't complete yet, please don't expect any video until I've written
9      * some more code.
10      */
11     
12     #include <linux/module.h>
13     #include <linux/init.h>
14     #include <linux/types.h>
15     #include <linux/mm.h>
16     #include <linux/errno.h>
17     #include <linux/videodev.h>
18     
19     #include <asm/addrspace.h>
20     #include <asm/system.h>
21     
22     #include "vino.h"
23     
24     struct vino_device {
25     	struct video_device vdev;
26     
27     	unsigned long chan;
28     #define VINO_CHAN_A		0
29     #define VINO_CHAN_B		1
30     
31     	unsigned long flags;
32     #define VINO_DMA_ACTIVE		(1<<0)
33     };
34     
35     /* We can actually receive TV and IndyCam input at the same time. Believe it or
36      * not..
37      */
38     static struct vino_device vino[2];
39     
40     /* Those registers have to be accessed by either *one* 64 bit write or *one* 64
41      * bit read. We need some asm to fix this. We can't use mips3 as standard
42      * because we just save 32 bits at context switch.
43      */
44     
45     static __inline__ unsigned long long vino_reg_read(unsigned long addr)
46     {
47     	unsigned long long ret __attribute__ ((aligned (64)));
48     	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
49     	unsigned long flags;
50     
51     	save_and_cli(flags);
52     	__asm__ __volatile__(
53     		".set\tmips3\n\t"
54     		".set\tnoat\n\t"
55     		"ld\t$1,(%0)\n\t"
56     		"sd\t$1,(%1)\n\t"
57     		".set\tat\n\t"
58     		".set\tmips0"
59     		:
60     		:"r" (virt_addr),
61     		 "r" (&ret)
62     		:"$1");
63     	restore_flags(flags);
64     
65     	return ret;
66     }
67     
68     static __inline__ void vino_reg_write(unsigned long long value,
69     				      unsigned long addr)
70     {
71     	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
72     	unsigned long flags;
73     
74     	/* we might lose the upper parts of the registers which are not saved
75     	 * if there comes an interrupt in our way, play safe */
76     
77     	save_and_cli(flags);
78     	__asm__ __volatile__(
79     		".set\tmips3\n\t"
80     		".set\tnoat\n\t"
81     		"ld\t$1,(%0)\n\t"
82     		"sd\t$1,(%1)\n\t"
83     		".set\tat\n\t"
84     		".set\tmips0"
85     		:
86     		:"r" (&value),
87     		 "r" (virt_addr)
88     		:"$1");
89     	restore_flags(flags);
90     }
91     
92     static __inline__ void vino_reg_and(unsigned long long value,
93     				    unsigned long addr)
94     {
95     	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
96     	unsigned long flags;
97     
98     	save_and_cli(flags);
99     	__asm__ __volatile__(
100     		".set\tmips3\n\t"
101     		".set\tnoat\n\t"
102     		"ld\t$1,(%0)\n\t"
103     		"ld\t$2,(%1)\n\t"
104     		"and\t$1,$1,$2\n\t"
105     		"sd\t$1,(%0)\n\t"
106     		".set\tat\n\t"
107     		".set\tmips0"
108     		:
109     		:"r" (virt_addr),
110     		 "r" (&value)
111     		:"$1","$2");
112     	restore_flags(flags);
113     }
114     
115     static __inline__ void vino_reg_or(unsigned long long value,
116     				   unsigned long addr)
117     {
118     	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
119     	unsigned long flags;
120     
121     	save_and_cli(flags);
122     	__asm__ __volatile__(
123     		".set\tmips3\n\t"
124     		".set\tnoat\n\t"
125     		"ld\t$1,(%0)\n\t"
126     		"ld\t$2,(%1)\n\t"
127     		"or\t$1,$1,$2\n\t"
128     		"sd\t$1,(%0)\n\t"
129     		".set\tat\n\t"
130     		".set\tmips0"
131     		:
132     		:"r" (virt_addr),
133     		 "r" (&value)
134     		:"$1","$2");
135     	restore_flags(flags);
136     }
137     
138     static int vino_dma_setup(void)
139     {
140     	return 0;
141     }
142     
143     static void vino_dma_stop(void)
144     {
145     
146     }
147     
148     static int vino_init(void)
149     {
150     	unsigned long ret;
151     	unsigned short rev, id;
152     	unsigned long long foo;
153     	unsigned long *bar;
154     
155     	bar = (unsigned long *) &foo;
156     
157     	ret = vino_reg_read(VINO_REVID);
158     
159     	rev = (ret & VINO_REVID_REV_MASK);
160     	id = (ret & VINO_REVID_ID_MASK) >> 4;
161     
162     	printk("Vino: ID:%02hx Rev:%02hx\n", id, rev);
163     
164     	foo = vino_reg_read(VINO_A_DESC_DATA0);
165     	printk("0x%lx", bar[0]);
166     	printk("%lx ", bar[1]);
167     	foo = vino_reg_read(VINO_A_DESC_DATA1);
168     	printk("0x%lx", bar[0]);
169     	printk("%lx ", bar[1]);
170     	foo = vino_reg_read(VINO_A_DESC_DATA2);
171     	printk("0x%lx", bar[0]);
172     	printk("%lx ", bar[1]);
173     	foo = vino_reg_read(VINO_A_DESC_DATA3);
174     	printk("0x%lx", bar[0]);
175     	printk("%lx\n", bar[1]);
176     	foo = vino_reg_read(VINO_B_DESC_DATA0);
177     	printk("0x%lx", bar[0]);
178     	printk("%lx ", bar[1]);
179     	foo = vino_reg_read(VINO_B_DESC_DATA1);
180     	printk("0x%lx", bar[0]);
181     	printk("%lx ", bar[1]);
182     	foo = vino_reg_read(VINO_B_DESC_DATA2);
183     	printk("0x%lx", bar[0]);
184     	printk("%lx ", bar[1]);
185     	foo = vino_reg_read(VINO_B_DESC_DATA3);
186     	printk("0x%lx", bar[0]);
187     	printk("%lx\n", bar[1]);
188     
189     	return 0;
190     }
191     
192     static void vino_dma_go(struct vino_device *v)
193     {
194     	
195     }
196     
197     /* Reset the vino back to default state */
198     
199     static void vino_setup(struct vino_device *v)
200     {
201     	
202     }
203     
204     static int vino_open(struct video_device *dev, int flags)
205     {
206     	return 0;
207     }
208     
209     static void vino_close(struct video_device *dev)
210     {
211     }
212     
213     static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
214     {
215     	return 0;
216     }
217     
218     static int vino_mmap(struct video_device *dev, const char *adr,
219     		     unsigned long size)
220     {
221     	return 0;
222     }
223     
224     static struct video_device vino_dev = {
225     	owner:		THIS_MODULE,
226     	name:		"Vino IndyCam/TV",
227     	type:		VID_TYPE_CAPTURE,
228     	hardware:	VID_HARDWARE_VINO,
229     	open:		vino_open,
230     	close:		vino_close,
231     	ioctl:		vino_ioctl,
232     	mmap:		vino_mmap,
233     };
234     
235     int __init init_vino(struct video_device *dev)
236     {
237     	int err;
238     
239     	err = vino_init();
240     	if (err)
241     		return err;
242     
243     #if 0
244     	if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) {
245     		return -ENODEV;
246     	}
247     #endif
248     
249     	return 0;
250     }
251     
252     #ifdef MODULE
253     int init_module(void)
254     {
255     	int err;
256     
257     	err = vino_init();
258     	if (err)
259     		return err;
260     
261     	return 0;
262     }
263     
264     void cleanup_module(void)
265     {
266     }
267     #endif
268