1/*
2 * drivers/sbus/char/vfc_dev.c
3 *
4 * Driver for the Videopix Frame Grabber.
5 *
6 * In order to use the VFC you need to program the video controller
7 * chip. This chip is the Phillips SAA9051.  You need to call their
8 * documentation ordering line to get the docs.
9 *
10 * There is very little documentation on the VFC itself.  There is
11 * some useful info that can be found in the manuals that come with
12 * the card.  I will hopefully write some better docs at a later date.
13 *
14 * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
15 * */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/slab.h>
21#include <linux/errno.h>
22#include <linux/fs.h>
23#include <linux/delay.h>
24#include <linux/spinlock.h>
25#include <linux/mm.h>
26
27#include <asm/openprom.h>
28#include <asm/oplib.h>
29#include <asm/io.h>
30#include <asm/system.h>
31#include <asm/sbus.h>
32#include <asm/page.h>
33#include <asm/pgtable.h>
34#include <asm/uaccess.h>
35
36#define VFC_MAJOR (60)
37
38
39#include "vfc.h"
40#include <asm/vfc_ioctls.h>
41
42static const struct file_operations vfc_fops;
43struct vfc_dev **vfc_dev_lst;
44static char vfcstr[]="vfc";
45static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
46	0x00, 0x64, 0x72, 0x52,
47	0x36, 0x18, 0xff, 0x20,
48	0xfc, 0x77, 0xe3, 0x50,
49	0x3e
50};
51
52void vfc_lock_device(struct vfc_dev *dev)
53{
54	down(&dev->device_lock_sem);
55}
56
57void vfc_unlock_device(struct vfc_dev *dev)
58{
59	up(&dev->device_lock_sem);
60}
61
62
63void vfc_captstat_reset(struct vfc_dev *dev)
64{
65	dev->control_reg |= VFC_CONTROL_CAPTRESET;
66	sbus_writel(dev->control_reg, &dev->regs->control);
67	dev->control_reg &= ~VFC_CONTROL_CAPTRESET;
68	sbus_writel(dev->control_reg, &dev->regs->control);
69	dev->control_reg |= VFC_CONTROL_CAPTRESET;
70	sbus_writel(dev->control_reg, &dev->regs->control);
71}
72
73void vfc_memptr_reset(struct vfc_dev *dev)
74{
75	dev->control_reg |= VFC_CONTROL_MEMPTR;
76	sbus_writel(dev->control_reg, &dev->regs->control);
77	dev->control_reg &= ~VFC_CONTROL_MEMPTR;
78	sbus_writel(dev->control_reg, &dev->regs->control);
79	dev->control_reg |= VFC_CONTROL_MEMPTR;
80	sbus_writel(dev->control_reg, &dev->regs->control);
81}
82
83int vfc_csr_init(struct vfc_dev *dev)
84{
85	dev->control_reg = 0x80000000;
86	sbus_writel(dev->control_reg, &dev->regs->control);
87	udelay(200);
88	dev->control_reg &= ~0x80000000;
89	sbus_writel(dev->control_reg, &dev->regs->control);
90	udelay(100);
91	sbus_writel(0x0f000000, &dev->regs->i2c_magic2);
92
93	vfc_memptr_reset(dev);
94
95	dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
96	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
97	dev->control_reg |= 0x40000000;
98	sbus_writel(dev->control_reg, &dev->regs->control);
99
100	vfc_captstat_reset(dev);
101
102	return 0;
103}
104
105int vfc_saa9051_init(struct vfc_dev *dev)
106{
107	int i;
108
109	for (i = 0; i < VFC_SAA9051_NR; i++)
110		dev->saa9051_state_array[i] = saa9051_init_array[i];
111
112	vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR,
113			dev->saa9051_state_array, VFC_SAA9051_NR);
114	return 0;
115}
116
117int init_vfc_hw(struct vfc_dev *dev)
118{
119	vfc_lock_device(dev);
120	vfc_csr_init(dev);
121
122	vfc_pcf8584_init(dev);
123	vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic
124				  sun code above*/
125	vfc_saa9051_init(dev);
126	vfc_unlock_device(dev);
127	return 0;
128}
129
130int init_vfc_devstruct(struct vfc_dev *dev, int instance)
131{
132	dev->instance=instance;
133	init_MUTEX(&dev->device_lock_sem);
134	dev->control_reg=0;
135	dev->busy=0;
136	return 0;
137}
138
139int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
140{
141	if(dev == NULL) {
142		printk(KERN_ERR "VFC: Bogus pointer passed\n");
143		return -ENOMEM;
144	}
145	printk("Initializing vfc%d\n",instance);
146	dev->regs = NULL;
147	dev->regs = (volatile struct vfc_regs __iomem *)
148		sbus_ioremap(&sdev->resource[0], 0,
149			     sizeof(struct vfc_regs), vfcstr);
150	dev->which_io = sdev->reg_addrs[0].which_io;
151	dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr;
152	if (dev->regs == NULL)
153		return -EIO;
154
155	printk("vfc%d: registers mapped at phys_addr: 0x%lx\n    virt_addr: 0x%lx\n",
156	       instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);
157
158	if (init_vfc_devstruct(dev, instance))
159		return -EINVAL;
160	if (init_vfc_hw(dev))
161		return -EIO;
162	return 0;
163}
164
165
166struct vfc_dev *vfc_get_dev_ptr(int instance)
167{
168	return vfc_dev_lst[instance];
169}
170
171static DEFINE_SPINLOCK(vfc_dev_lock);
172
173static int vfc_open(struct inode *inode, struct file *file)
174{
175	struct vfc_dev *dev;
176
177	spin_lock(&vfc_dev_lock);
178	dev = vfc_get_dev_ptr(iminor(inode));
179	if (dev == NULL) {
180		spin_unlock(&vfc_dev_lock);
181		return -ENODEV;
182	}
183	if (dev->busy) {
184		spin_unlock(&vfc_dev_lock);
185		return -EBUSY;
186	}
187
188	dev->busy = 1;
189	spin_unlock(&vfc_dev_lock);
190
191	vfc_lock_device(dev);
192
193	vfc_csr_init(dev);
194	vfc_pcf8584_init(dev);
195	vfc_init_i2c_bus(dev);
196	vfc_saa9051_init(dev);
197	vfc_memptr_reset(dev);
198	vfc_captstat_reset(dev);
199
200	vfc_unlock_device(dev);
201	return 0;
202}
203
204static int vfc_release(struct inode *inode,struct file *file)
205{
206	struct vfc_dev *dev;
207
208	spin_lock(&vfc_dev_lock);
209	dev = vfc_get_dev_ptr(iminor(inode));
210	if (!dev || !dev->busy) {
211		spin_unlock(&vfc_dev_lock);
212		return -EINVAL;
213	}
214	dev->busy = 0;
215	spin_unlock(&vfc_dev_lock);
216	return 0;
217}
218
219static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp)
220{
221	struct vfc_debug_inout inout;
222	unsigned char *buffer;
223
224	if (!capable(CAP_SYS_ADMIN))
225		return -EPERM;
226
227	switch(cmd) {
228	case VFC_I2C_SEND:
229		if(copy_from_user(&inout, argp, sizeof(inout)))
230			return -EFAULT;
231
232		buffer = kmalloc(inout.len, GFP_KERNEL);
233		if (buffer == NULL)
234			return -ENOMEM;
235
236		if(copy_from_user(buffer, inout.buffer, inout.len)) {
237			kfree(buffer);
238			return -EFAULT;
239		}
240
241
242		vfc_lock_device(dev);
243		inout.ret=
244			vfc_i2c_sendbuf(dev,inout.addr & 0xff,
245					buffer,inout.len);
246
247		if (copy_to_user(argp,&inout,sizeof(inout))) {
248			kfree(buffer);
249			return -EFAULT;
250		}
251		vfc_unlock_device(dev);
252
253		break;
254	case VFC_I2C_RECV:
255		if (copy_from_user(&inout, argp, sizeof(inout)))
256			return -EFAULT;
257
258		buffer = kzalloc(inout.len, GFP_KERNEL);
259		if (buffer == NULL)
260			return -ENOMEM;
261
262		vfc_lock_device(dev);
263		inout.ret=
264			vfc_i2c_recvbuf(dev,inout.addr & 0xff
265					,buffer,inout.len);
266		vfc_unlock_device(dev);
267
268		if (copy_to_user(inout.buffer, buffer, inout.len)) {
269			kfree(buffer);
270			return -EFAULT;
271		}
272		if (copy_to_user(argp,&inout,sizeof(inout))) {
273			kfree(buffer);
274			return -EFAULT;
275		}
276		kfree(buffer);
277		break;
278	default:
279		return -EINVAL;
280	};
281
282	return 0;
283}
284
285int vfc_capture_start(struct vfc_dev *dev)
286{
287	vfc_captstat_reset(dev);
288	dev->control_reg = sbus_readl(&dev->regs->control);
289	if((dev->control_reg & VFC_STATUS_CAPTURE)) {
290		printk(KERN_ERR "vfc%d: vfc capture status not reset\n",
291		       dev->instance);
292		return -EIO;
293	}
294
295	vfc_lock_device(dev);
296	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
297	sbus_writel(dev->control_reg, &dev->regs->control);
298	dev->control_reg |= VFC_CONTROL_CAPTURE;
299	sbus_writel(dev->control_reg, &dev->regs->control);
300	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
301	sbus_writel(dev->control_reg, &dev->regs->control);
302	vfc_unlock_device(dev);
303
304	return 0;
305}
306
307int vfc_capture_poll(struct vfc_dev *dev)
308{
309	int timeout = 1000;
310
311	while (!timeout--) {
312		if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE)
313			break;
314		vfc_i2c_delay_no_busy(dev, 100);
315	}
316	if(!timeout) {
317		printk(KERN_WARNING "vfc%d: capture timed out\n",
318		       dev->instance);
319		return -ETIMEDOUT;
320	}
321	return 0;
322}
323
324
325
326static int vfc_set_control_ioctl(struct inode *inode, struct file *file,
327			  struct vfc_dev *dev, unsigned long arg)
328{
329	int setcmd, ret = 0;
330
331	if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int)))
332		return -EFAULT;
333
334	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n",
335				dev->instance,setcmd));
336
337	switch(setcmd) {
338	case MEMPRST:
339		vfc_lock_device(dev);
340		vfc_memptr_reset(dev);
341		vfc_unlock_device(dev);
342		ret=0;
343		break;
344	case CAPTRCMD:
345		vfc_capture_start(dev);
346		vfc_capture_poll(dev);
347		break;
348	case DIAGMODE:
349		if(capable(CAP_SYS_ADMIN)) {
350			vfc_lock_device(dev);
351			dev->control_reg |= VFC_CONTROL_DIAGMODE;
352			sbus_writel(dev->control_reg, &dev->regs->control);
353			vfc_unlock_device(dev);
354			ret = 0;
355		} else {
356			ret = -EPERM;
357		}
358		break;
359	case NORMMODE:
360		vfc_lock_device(dev);
361		dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
362		sbus_writel(dev->control_reg, &dev->regs->control);
363		vfc_unlock_device(dev);
364		ret = 0;
365		break;
366	case CAPTRSTR:
367		vfc_capture_start(dev);
368		ret = 0;
369		break;
370	case CAPTRWAIT:
371		vfc_capture_poll(dev);
372		ret = 0;
373		break;
374	default:
375		ret = -EINVAL;
376		break;
377	};
378
379	return ret;
380}
381
382
383int vfc_port_change_ioctl(struct inode *inode, struct file *file,
384			  struct vfc_dev *dev, unsigned long arg)
385{
386	int ret = 0;
387	int cmd;
388
389	if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) {
390		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
391					"vfc_port_change_ioctl\n",
392					dev->instance));
393		return -EFAULT;
394	}
395
396	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n",
397				dev->instance, cmd));
398
399	switch(cmd) {
400	case 1:
401	case 2:
402		VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72;
403		VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52;
404		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36;
405		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18;
406		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2;
407		VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3;
408		VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e;
409		break;
410	case 3:
411		VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a;
412		VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17;
413		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa;
414		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde;
415		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) =
416			VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2;
417		VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC;
418		VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0;
419		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
420			~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
421		break;
422	default:
423		ret = -EINVAL;
424		return ret;
425		break;
426	}
427
428	switch(cmd) {
429	case 1:
430		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |=
431			(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
432		break;
433	case 2:
434		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
435			~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
436		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0;
437		break;
438	case 3:
439		break;
440	default:
441		ret = -EINVAL;
442		return ret;
443		break;
444	}
445	VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2);
446	ret=vfc_update_saa9051(dev);
447	udelay(500);
448	VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2);
449	ret=vfc_update_saa9051(dev);
450	return ret;
451}
452
453int vfc_set_video_ioctl(struct inode *inode, struct file *file,
454			struct vfc_dev *dev, unsigned long arg)
455{
456	int ret = 0;
457	int cmd;
458
459	if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) {
460		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
461					"vfc_set_video_ioctl\n",
462					dev->instance));
463		return ret;
464	}
465
466	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n",
467				dev->instance, cmd));
468	switch(cmd) {
469	case STD_NTSC:
470		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT;
471		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN |
472			VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS;
473		ret = vfc_update_saa9051(dev);
474		break;
475	case STD_PAL:
476		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN |
477							VFC_SAA9051_CCFR1 |
478							VFC_SAA9051_CCFR0 |
479							VFC_SAA9051_FS);
480		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT;
481		ret = vfc_update_saa9051(dev);
482		break;
483
484	case COLOR_ON:
485		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO;
486		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &=
487			~(VFC_SAA9051_BY | VFC_SAA9051_PF);
488		ret = vfc_update_saa9051(dev);
489		break;
490	case MONO:
491		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO);
492		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |=
493			(VFC_SAA9051_BY | VFC_SAA9051_PF);
494		ret = vfc_update_saa9051(dev);
495		break;
496	default:
497		ret = -EINVAL;
498		break;
499	};
500
501	return ret;
502}
503
504int vfc_get_video_ioctl(struct inode *inode, struct file *file,
505			struct vfc_dev *dev, unsigned long arg)
506{
507	int ret = 0;
508	unsigned int status = NO_LOCK;
509	unsigned char buf[1];
510
511	if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) {
512		printk(KERN_ERR "vfc%d: Unable to get status\n",
513		       dev->instance);
514		return -EIO;
515	}
516
517	if(buf[0] & VFC_SAA9051_HLOCK) {
518		status = NO_LOCK;
519	} else if(buf[0] & VFC_SAA9051_FD) {
520		if(buf[0] & VFC_SAA9051_CD)
521			status = NTSC_COLOR;
522		else
523			status = NTSC_NOCOLOR;
524	} else {
525		if(buf[0] & VFC_SAA9051_CD)
526			status = PAL_COLOR;
527		else
528			status = PAL_NOCOLOR;
529	}
530	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; "
531				"buf[0]=%x\n", dev->instance, status, buf[0]));
532
533	if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) {
534		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
535					"vfc_get_video_ioctl\n",
536					dev->instance));
537		return ret;
538	}
539	return ret;
540}
541
542static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
543	      unsigned long arg)
544{
545	int ret = 0;
546	unsigned int tmp;
547	struct vfc_dev *dev;
548	void __user *argp = (void __user *)arg;
549
550	dev = vfc_get_dev_ptr(iminor(inode));
551	if(dev == NULL)
552		return -ENODEV;
553
554	switch(cmd & 0x0000ffff) {
555	case VFCGCTRL:
556		tmp = sbus_readl(&dev->regs->control);
557		if(copy_to_user(argp, &tmp, sizeof(unsigned int))) {
558			ret = -EFAULT;
559			break;
560		}
561		ret = 0;
562		break;
563	case VFCSCTRL:
564		ret = vfc_set_control_ioctl(inode, file, dev, arg);
565		break;
566	case VFCGVID:
567		ret = vfc_get_video_ioctl(inode, file, dev, arg);
568		break;
569	case VFCSVID:
570		ret = vfc_set_video_ioctl(inode, file, dev, arg);
571		break;
572	case VFCHUE:
573		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance));
574		if(copy_from_user(&tmp,argp,sizeof(unsigned int))) {
575			VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer "
576						"to IOCTL(VFCHUE)", dev->instance));
577			ret = -EFAULT;
578		} else {
579			VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp;
580			vfc_update_saa9051(dev);
581			ret = 0;
582		}
583		break;
584	case VFCPORTCHG:
585		ret = vfc_port_change_ioctl(inode, file, dev, arg);
586		break;
587	case VFCRDINFO:
588		ret = -EINVAL;
589		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance));
590		break;
591	default:
592		ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp);
593		break;
594	};
595
596	return ret;
597}
598
599static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
600{
601	unsigned int map_size, ret, map_offset;
602	struct vfc_dev *dev;
603
604	dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode));
605	if(dev == NULL)
606		return -ENODEV;
607
608	map_size = vma->vm_end - vma->vm_start;
609	if(map_size > sizeof(struct vfc_regs))
610		map_size = sizeof(struct vfc_regs);
611
612	vma->vm_flags |=
613		(VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
614	map_offset = (unsigned int) (long)dev->phys_regs;
615	ret = io_remap_pfn_range(vma, vma->vm_start,
616				  MK_IOSPACE_PFN(dev->which_io,
617					map_offset >> PAGE_SHIFT),
618				  map_size, vma->vm_page_prot);
619
620	if(ret)
621		return -EAGAIN;
622
623	return 0;
624}
625
626
627static const struct file_operations vfc_fops = {
628	.owner =	THIS_MODULE,
629	.llseek =	no_llseek,
630	.ioctl =	vfc_ioctl,
631	.mmap =		vfc_mmap,
632	.open =		vfc_open,
633	.release =	vfc_release,
634};
635
636static int vfc_probe(void)
637{
638	struct sbus_bus *sbus;
639	struct sbus_dev *sdev = NULL;
640	int ret;
641	int instance = 0, cards = 0;
642
643	for_all_sbusdev(sdev, sbus) {
644		if (strcmp(sdev->prom_name, "vfc") == 0) {
645			cards++;
646			continue;
647		}
648	}
649
650	if (!cards)
651		return -ENODEV;
652
653	vfc_dev_lst = kmalloc(sizeof(struct vfc_dev *) *
654						 (cards+1),
655						 GFP_KERNEL);
656	if (vfc_dev_lst == NULL)
657		return -ENOMEM;
658	memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1));
659	vfc_dev_lst[cards] = NULL;
660
661	ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
662	if(ret) {
663		printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR);
664		kfree(vfc_dev_lst);
665		return -EIO;
666	}
667	instance = 0;
668	for_all_sbusdev(sdev, sbus) {
669		if (strcmp(sdev->prom_name, "vfc") == 0) {
670			vfc_dev_lst[instance]=(struct vfc_dev *)
671				kmalloc(sizeof(struct vfc_dev), GFP_KERNEL);
672			if (vfc_dev_lst[instance] == NULL)
673				return -ENOMEM;
674			ret = init_vfc_device(sdev,
675					      vfc_dev_lst[instance],
676					      instance);
677			if(ret) {
678				printk(KERN_ERR "Unable to initialize"
679				       " vfc%d device\n",
680				       instance);
681			} else {
682			}
683
684			instance++;
685			continue;
686		}
687	}
688
689	return 0;
690}
691
692#ifdef MODULE
693int init_module(void)
694#else
695int vfc_init(void)
696#endif
697{
698	return vfc_probe();
699}
700
701#ifdef MODULE
702static void deinit_vfc_device(struct vfc_dev *dev)
703{
704	if(dev == NULL)
705		return;
706	sbus_iounmap(dev->regs, sizeof(struct vfc_regs));
707	kfree(dev);
708}
709
710void cleanup_module(void)
711{
712	struct vfc_dev **devp;
713
714	unregister_chrdev(VFC_MAJOR,vfcstr);
715
716	for (devp = vfc_dev_lst; *devp; devp++)
717		deinit_vfc_device(*devp);
718
719	kfree(vfc_dev_lst);
720	return;
721}
722#endif
723
724MODULE_LICENSE("GPL");
725