ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / video / c-qcam.c
1 /*
2  *      Video4Linux Colour QuickCam driver
3  *      Copyright 1997-2000 Philip Blundell <philb@gnu.org>
4  *
5  *    Module parameters:
6  *
7  *      parport=auto      -- probe all parports (default)
8  *      parport=0         -- parport0 becomes qcam1
9  *      parport=2,0,1     -- parports 2,0,1 are tried in that order
10  *
11  *      probe=0           -- do no probing, assume camera is present
12  *      probe=1           -- use IEEE-1284 autoprobe data only (default)
13  *      probe=2           -- probe aggressively for cameras
14  *
15  *      force_rgb=1       -- force data format to RGB (default is BGR)
16  *
17  * The parport parameter controls which parports will be scanned.
18  * Scanning all parports causes some printers to print a garbage page.
19  *       -- March 14, 1999  Billy Donahue <billy@escape.com> 
20  *
21  * Fixed data format to BGR, added force_rgb parameter. Added missing
22  * parport_unregister_driver() on module removal.
23  *       -- May 28, 2000  Claudio Matsuoka <claudio@conectiva.com>
24  */
25
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/errno.h>
29 #include <linux/fs.h>
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
33 #include <linux/mm.h>
34 #include <linux/parport.h>
35 #include <linux/sched.h>
36 #include <linux/videodev.h>
37 #include <asm/semaphore.h>
38 #include <asm/uaccess.h>
39
40 struct qcam_device {
41         struct video_device vdev;
42         struct pardevice *pdev;
43         struct parport *pport;
44         int width, height;
45         int ccd_width, ccd_height;
46         int mode;
47         int contrast, brightness, whitebal;
48         int top, left;
49         unsigned int bidirectional;
50         struct semaphore lock;
51 };
52
53 /* cameras maximum */
54 #define MAX_CAMS 4
55
56 /* The three possible QuickCam modes */
57 #define QC_MILLIONS     0x18
58 #define QC_BILLIONS     0x10
59 #define QC_THOUSANDS    0x08    /* with VIDEC compression (not supported) */
60
61 /* The three possible decimations */
62 #define QC_DECIMATION_1         0
63 #define QC_DECIMATION_2         2
64 #define QC_DECIMATION_4         4
65
66 #define BANNER "Colour QuickCam for Video4Linux v0.05"
67
68 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
69 static int probe = 2;
70 static int force_rgb = 0;
71 static int video_nr = -1;
72
73 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
74 {
75         /* note: the QC specs refer to the PCAck pin by voltage, not
76            software level.  PC ports have builtin inverters. */
77         parport_frob_control(qcam->pport, 8, i?8:0);
78 }
79
80 static inline unsigned int qcam_ready1(struct qcam_device *qcam)
81 {
82         return (parport_read_status(qcam->pport) & 0x8)?1:0;
83 }
84
85 static inline unsigned int qcam_ready2(struct qcam_device *qcam)
86 {
87         return (parport_read_data(qcam->pport) & 0x1)?1:0;
88 }
89
90 static unsigned int qcam_await_ready1(struct qcam_device *qcam, 
91                                              int value)
92 {
93         unsigned long oldjiffies = jiffies;
94         unsigned int i;
95
96         for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
97                 if (qcam_ready1(qcam) == value)
98                         return 0;
99
100         /* If the camera didn't respond within 1/25 second, poll slowly 
101            for a while. */
102         for (i = 0; i < 50; i++)
103         {
104                 if (qcam_ready1(qcam) == value)
105                         return 0;
106                 current->state=TASK_INTERRUPTIBLE;
107                 schedule_timeout(HZ/10);
108         }
109
110         /* Probably somebody pulled the plug out.  Not much we can do. */
111         printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value,
112                parport_read_status(qcam->pport),
113                parport_read_control(qcam->pport));
114         return 1;
115 }
116
117 static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
118 {
119         unsigned long oldjiffies = jiffies;
120         unsigned int i;
121
122         for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
123                 if (qcam_ready2(qcam) == value)
124                         return 0;
125
126         /* If the camera didn't respond within 1/25 second, poll slowly 
127            for a while. */
128         for (i = 0; i < 50; i++)
129         {
130                 if (qcam_ready2(qcam) == value)
131                         return 0;
132                 current->state=TASK_INTERRUPTIBLE;
133                 schedule_timeout(HZ/10);
134         }
135
136         /* Probably somebody pulled the plug out.  Not much we can do. */
137         printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value,
138                parport_read_status(qcam->pport),
139                parport_read_control(qcam->pport),
140                parport_read_data(qcam->pport));
141         return 1;
142 }
143
144 static int qcam_read_data(struct qcam_device *qcam)
145 {
146         unsigned int idata;
147         qcam_set_ack(qcam, 0);
148         if (qcam_await_ready1(qcam, 1)) return -1;
149         idata = parport_read_status(qcam->pport) & 0xf0;
150         qcam_set_ack(qcam, 1);
151         if (qcam_await_ready1(qcam, 0)) return -1;
152         idata |= (parport_read_status(qcam->pport) >> 4);
153         return idata;
154 }
155
156 static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
157 {
158         unsigned int idata;
159         parport_write_data(qcam->pport, data);
160         idata = qcam_read_data(qcam);
161         if (data != idata) 
162         {
163                 printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, 
164                        idata);
165                 return 1;
166         } 
167         return 0;
168 }
169
170 static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data)
171 {
172         if (qcam_write_data(qcam, cmd))
173                 return -1;
174         if (qcam_write_data(qcam, data))
175                 return -1;
176         return 0;
177 }
178
179 static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd)
180 {
181         if (qcam_write_data(qcam, cmd))
182                 return -1;
183         return qcam_read_data(qcam);
184 }
185
186 static int qc_detect(struct qcam_device *qcam)
187 {
188         unsigned int stat, ostat, i, count = 0;
189
190         /* The probe routine below is not very reliable.  The IEEE-1284
191            probe takes precedence. */
192         /* XXX Currently parport provides no way to distinguish between
193            "the IEEE probe was not done" and "the probe was done, but
194            no device was found".  Fix this one day. */
195         if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
196             && qcam->pport->probe_info[0].model
197             && !strcmp(qcam->pdev->port->probe_info[0].model, 
198                        "Color QuickCam 2.0")) {
199                 printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
200                 return 1;
201         }
202         
203         if (probe < 2)
204                 return 0;
205
206         parport_write_control(qcam->pport, 0xc);
207
208         /* look for a heartbeat */
209         ostat = stat = parport_read_status(qcam->pport);
210         for (i=0; i<250; i++) 
211         {
212                 mdelay(1);
213                 stat = parport_read_status(qcam->pport);
214                 if (ostat != stat) 
215                 {
216                         if (++count >= 3) return 1;
217                         ostat = stat;
218                 }
219         }
220
221         /* Reset the camera and try again */
222         parport_write_control(qcam->pport, 0xc);
223         parport_write_control(qcam->pport, 0x8);
224         mdelay(1);
225         parport_write_control(qcam->pport, 0xc);
226         mdelay(1);
227         count = 0;
228
229         ostat = stat = parport_read_status(qcam->pport);
230         for (i=0; i<250; i++) 
231         {
232                 mdelay(1);
233                 stat = parport_read_status(qcam->pport);
234                 if (ostat != stat) 
235                 {
236                         if (++count >= 3) return 1;
237                         ostat = stat;
238                 }
239         }
240
241         /* no (or flatline) camera, give up */
242         return 0;
243 }
244
245 static void qc_reset(struct qcam_device *qcam)
246 {
247         parport_write_control(qcam->pport, 0xc);
248         parport_write_control(qcam->pport, 0x8);
249         mdelay(1);
250         parport_write_control(qcam->pport, 0xc);
251         mdelay(1);          
252 }
253
254 /* Reset the QuickCam and program for brightness, contrast,
255  * white-balance, and resolution. */
256
257 static void qc_setup(struct qcam_device *q)
258 {
259         qc_reset(q);
260
261         /* Set the brightness.  */
262         qcam_set(q, 11, q->brightness);
263
264         /* Set the height and width.  These refer to the actual
265            CCD area *before* applying the selected decimation.  */
266         qcam_set(q, 17, q->ccd_height);
267         qcam_set(q, 19, q->ccd_width / 2);
268
269         /* Set top and left.  */
270         qcam_set(q, 0xd, q->top);
271         qcam_set(q, 0xf, q->left);
272
273         /* Set contrast and white balance.  */
274         qcam_set(q, 0x19, q->contrast);
275         qcam_set(q, 0x1f, q->whitebal);
276         
277         /* Set the speed.  */
278         qcam_set(q, 45, 2);
279 }
280
281 /* Read some bytes from the camera and put them in the buffer. 
282    nbytes should be a multiple of 3, because bidirectional mode gives
283    us three bytes at a time.  */
284
285 static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes)
286 {
287         unsigned int bytes = 0;
288
289         qcam_set_ack(q, 0);
290         if (q->bidirectional)
291         {
292                 /* It's a bidirectional port */
293                 while (bytes < nbytes)
294                 {
295                         unsigned int lo1, hi1, lo2, hi2;
296                         unsigned char r, g, b;
297
298                         if (qcam_await_ready2(q, 1)) return bytes;
299                         lo1 = parport_read_data(q->pport) >> 1;
300                         hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
301                         qcam_set_ack(q, 1);
302                         if (qcam_await_ready2(q, 0)) return bytes;
303                         lo2 = parport_read_data(q->pport) >> 1;
304                         hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
305                         qcam_set_ack(q, 0);
306                         r = (lo1 | ((hi1 & 1)<<7));
307                         g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1);
308                         b = (lo2 | ((hi2 & 1)<<7));
309                         if (force_rgb) {
310                                 buf[bytes++] = r;
311                                 buf[bytes++] = g;
312                                 buf[bytes++] = b;
313                         } else {
314                                 buf[bytes++] = b;
315                                 buf[bytes++] = g;
316                                 buf[bytes++] = r;
317                         }
318                 }
319         }
320         else
321         {
322                 /* It's a unidirectional port */
323                 int i = 0, n = bytes;
324                 unsigned char rgb[3];
325
326                 while (bytes < nbytes)
327                 {
328                         unsigned int hi, lo;
329
330                         if (qcam_await_ready1(q, 1)) return bytes;
331                         hi = (parport_read_status(q->pport) & 0xf0);
332                         qcam_set_ack(q, 1);
333                         if (qcam_await_ready1(q, 0)) return bytes;
334                         lo = (parport_read_status(q->pport) & 0xf0);
335                         qcam_set_ack(q, 0);
336                         /* flip some bits */
337                         rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
338                         if (i >= 2) {
339 get_fragment:
340                                 if (force_rgb) {
341                                         buf[n++] = rgb[0];
342                                         buf[n++] = rgb[1];
343                                         buf[n++] = rgb[2];
344                                 } else {
345                                         buf[n++] = rgb[2];
346                                         buf[n++] = rgb[1];
347                                         buf[n++] = rgb[0];
348                                 }
349                         }
350                 }
351                 if (i) {
352                         i = 0;
353                         goto get_fragment;
354                 }
355         }
356         return bytes;
357 }
358
359 #define BUFSZ   150
360
361 static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
362 {
363         unsigned lines, pixelsperline, bitsperxfer;
364         unsigned int is_bi_dir = q->bidirectional;
365         size_t wantlen, outptr = 0;
366         char tmpbuf[BUFSZ];
367
368         if (verify_area(VERIFY_WRITE, buf, len))
369                 return -EFAULT;
370
371         /* Wait for camera to become ready */
372         for (;;)
373         {
374                 int i = qcam_get(q, 41);
375                 if (i == -1) {
376                         qc_setup(q);
377                         return -EIO;
378                 }
379                 if ((i & 0x80) == 0)
380                         break;
381                 else
382                         schedule();
383         }
384
385         if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
386                 return -EIO;
387         
388         lines = q->height;
389         pixelsperline = q->width;
390         bitsperxfer = (is_bi_dir) ? 24 : 8;
391
392         if (is_bi_dir)
393         {
394                 /* Turn the port around */
395                 parport_data_reverse(q->pport);
396                 mdelay(3);
397                 qcam_set_ack(q, 0);
398                 if (qcam_await_ready1(q, 1)) {
399                         qc_setup(q);
400                         return -EIO;
401                 }
402                 qcam_set_ack(q, 1);
403                 if (qcam_await_ready1(q, 0)) {
404                         qc_setup(q);
405                         return -EIO;
406                 }
407         }
408
409         wantlen = lines * pixelsperline * 24 / 8;
410
411         while (wantlen)
412         {
413                 size_t t, s;
414                 s = (wantlen > BUFSZ)?BUFSZ:wantlen;
415                 t = qcam_read_bytes(q, tmpbuf, s);
416                 if (outptr < len)
417                 {
418                         size_t sz = len - outptr;
419                         if (sz > t) sz = t;
420                         if (__copy_to_user(buf+outptr, tmpbuf, sz))
421                                 break;
422                         outptr += sz;
423                 }
424                 wantlen -= t;
425                 if (t < s)
426                         break;
427                 cond_resched();
428         }
429
430         len = outptr;
431
432         if (wantlen)
433         {
434                 printk("qcam: short read.\n");
435                 if (is_bi_dir)
436                         parport_data_forward(q->pport);
437                 qc_setup(q);
438                 return len;
439         }
440
441         if (is_bi_dir)
442         {
443                 int l;
444                 do {
445                         l = qcam_read_bytes(q, tmpbuf, 3);
446                         cond_resched();
447                 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
448                 if (force_rgb) {
449                         if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
450                                 printk("qcam: bad EOF\n");
451                 } else {
452                         if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
453                                 printk("qcam: bad EOF\n");
454                 }
455                 qcam_set_ack(q, 0);
456                 if (qcam_await_ready1(q, 1))
457                 {
458                         printk("qcam: no ack after EOF\n");
459                         parport_data_forward(q->pport);
460                         qc_setup(q);
461                         return len;
462                 }
463                 parport_data_forward(q->pport);
464                 mdelay(3);
465                 qcam_set_ack(q, 1);
466                 if (qcam_await_ready1(q, 0))
467                 {
468                         printk("qcam: no ack to port turnaround\n");
469                         qc_setup(q);
470                         return len;
471                 }
472         }
473         else
474         {
475                 int l;
476                 do {
477                         l = qcam_read_bytes(q, tmpbuf, 1);
478                         cond_resched();
479                 } while (l && tmpbuf[0] == 0x7e);
480                 l = qcam_read_bytes(q, tmpbuf+1, 2);
481                 if (force_rgb) {
482                         if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
483                                 printk("qcam: bad EOF\n");
484                 } else {
485                         if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
486                                 printk("qcam: bad EOF\n");
487                 }
488         }
489
490         qcam_write_data(q, 0);
491         return len;
492 }
493
494 /*
495  *      Video4linux interfacing
496  */
497
498 static int qcam_do_ioctl(struct inode *inode, struct file *file,
499                          unsigned int cmd, void *arg)
500 {
501         struct video_device *dev = video_devdata(file);
502         struct qcam_device *qcam=(struct qcam_device *)dev;
503         
504         switch(cmd)
505         {
506                 case VIDIOCGCAP:
507                 {
508                         struct video_capability *b = arg;
509                         strcpy(b->name, "Quickcam");
510                         b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
511                         b->channels = 1;
512                         b->audios = 0;
513                         b->maxwidth = 320;
514                         b->maxheight = 240;
515                         b->minwidth = 80;
516                         b->minheight = 60;
517                         return 0;
518                 }
519                 case VIDIOCGCHAN:
520                 {
521                         struct video_channel *v = arg;
522                         if(v->channel!=0)
523                                 return -EINVAL;
524                         v->flags=0;
525                         v->tuners=0;
526                         /* Good question.. its composite or SVHS so.. */
527                         v->type = VIDEO_TYPE_CAMERA;
528                         strcpy(v->name, "Camera");
529                         return 0;
530                 }
531                 case VIDIOCSCHAN:
532                 {
533                         struct video_channel *v = arg;
534                         if(v->channel!=0)
535                                 return -EINVAL;
536                         return 0;
537                 }
538                 case VIDIOCGTUNER:
539                 {
540                         struct video_tuner *v = arg;
541                         if(v->tuner)
542                                 return -EINVAL;
543                         memset(v,0,sizeof(*v));
544                         strcpy(v->name, "Format");
545                         v->mode = VIDEO_MODE_AUTO;
546                         return 0;
547                 }
548                 case VIDIOCSTUNER:
549                 {
550                         struct video_tuner *v = arg;
551                         if(v->tuner)
552                                 return -EINVAL;
553                         if(v->mode!=VIDEO_MODE_AUTO)
554                                 return -EINVAL;
555                         return 0;
556                 }
557                 case VIDIOCGPICT:
558                 {
559                         struct video_picture *p = arg;
560                         p->colour=0x8000;
561                         p->hue=0x8000;
562                         p->brightness=qcam->brightness<<8;
563                         p->contrast=qcam->contrast<<8;
564                         p->whiteness=qcam->whitebal<<8;
565                         p->depth=24;
566                         p->palette=VIDEO_PALETTE_RGB24;
567                         return 0;
568                 }
569                 case VIDIOCSPICT:
570                 {
571                         struct video_picture *p = arg;
572
573                         /*
574                          *      Sanity check args
575                          */
576                         if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
577                                 return -EINVAL;
578                         
579                         /*
580                          *      Now load the camera.
581                          */
582                         qcam->brightness = p->brightness>>8;
583                         qcam->contrast = p->contrast>>8;
584                         qcam->whitebal = p->whiteness>>8;
585
586                         down(&qcam->lock);                      
587                         parport_claim_or_block(qcam->pdev);
588                         qc_setup(qcam); 
589                         parport_release(qcam->pdev);
590                         up(&qcam->lock);
591                         return 0;
592                 }
593                 case VIDIOCSWIN:
594                 {
595                         struct video_window *vw = arg;
596
597                         if(vw->flags)
598                                 return -EINVAL;
599                         if(vw->clipcount)
600                                 return -EINVAL;
601                         if(vw->height<60||vw->height>240)
602                                 return -EINVAL;
603                         if(vw->width<80||vw->width>320)
604                                 return -EINVAL;
605                                 
606                         qcam->width = 80;
607                         qcam->height = 60;
608                         qcam->mode = QC_DECIMATION_4;
609                         
610                         if(vw->width>=160 && vw->height>=120)
611                         {
612                                 qcam->width = 160;
613                                 qcam->height = 120;
614                                 qcam->mode = QC_DECIMATION_2;
615                         }
616                         if(vw->width>=320 && vw->height>=240)
617                         {
618                                 qcam->width = 320;
619                                 qcam->height = 240;
620                                 qcam->mode = QC_DECIMATION_1;
621                         }
622                         qcam->mode |= QC_MILLIONS;
623 #if 0
624                         if(vw->width>=640 && vw->height>=480)
625                         {
626                                 qcam->width = 640;
627                                 qcam->height = 480;
628                                 qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
629                         }
630 #endif
631                         /* Ok we figured out what to use from our 
632                            wide choice */
633                         down(&qcam->lock);
634                         parport_claim_or_block(qcam->pdev);
635                         qc_setup(qcam);
636                         parport_release(qcam->pdev);
637                         up(&qcam->lock);
638                         return 0;
639                 }
640                 case VIDIOCGWIN:
641                 {
642                         struct video_window *vw = arg;
643                         memset(vw, 0, sizeof(*vw));
644                         vw->width=qcam->width;
645                         vw->height=qcam->height;
646                         return 0;
647                 }
648                 case VIDIOCKEY:
649                         return 0;
650                 case VIDIOCCAPTURE:
651                 case VIDIOCGFBUF:
652                 case VIDIOCSFBUF:
653                 case VIDIOCGFREQ:
654                 case VIDIOCSFREQ:
655                 case VIDIOCGAUDIO:
656                 case VIDIOCSAUDIO:
657                         return -EINVAL;
658                 default:
659                         return -ENOIOCTLCMD;
660         }
661         return 0;
662 }
663
664 static int qcam_ioctl(struct inode *inode, struct file *file,
665                      unsigned int cmd, unsigned long arg)
666 {
667         return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
668 }
669
670 static ssize_t qcam_read(struct file *file, char *buf,
671                          size_t count, loff_t *ppos)
672 {
673         struct video_device *v = video_devdata(file);
674         struct qcam_device *qcam=(struct qcam_device *)v;
675         int len;
676
677         down(&qcam->lock);
678         parport_claim_or_block(qcam->pdev);
679         /* Probably should have a semaphore against multiple users */
680         len = qc_capture(qcam, buf,count); 
681         parport_release(qcam->pdev);
682         up(&qcam->lock);
683         return len;
684 }
685
686 /* video device template */
687 static struct file_operations qcam_fops = {
688         .owner          = THIS_MODULE,
689         .open           = video_exclusive_open,
690         .release        = video_exclusive_release,
691         .ioctl          = qcam_ioctl,
692         .read           = qcam_read,
693         .llseek         = no_llseek,
694 };
695
696 static struct video_device qcam_template=
697 {
698         .owner          = THIS_MODULE,
699         .name           = "Colour QuickCam",
700         .type           = VID_TYPE_CAPTURE,
701         .hardware       = VID_HARDWARE_QCAM_C,
702         .fops           = &qcam_fops,
703 };
704
705 /* Initialize the QuickCam driver control structure. */
706
707 static struct qcam_device *qcam_init(struct parport *port)
708 {
709         struct qcam_device *q;
710         
711         q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
712         if(q==NULL)
713                 return NULL;
714
715         q->pport = port;
716         q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
717                                           NULL, 0, NULL);
718
719         q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
720
721         if (q->pdev == NULL) 
722         {
723                 printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
724                        port->name);
725                 kfree(q);
726                 return NULL;
727         }
728         
729         memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
730
731         init_MUTEX(&q->lock);
732         q->width = q->ccd_width = 320;
733         q->height = q->ccd_height = 240;
734         q->mode = QC_MILLIONS | QC_DECIMATION_1;
735         q->contrast = 192;
736         q->brightness = 240;
737         q->whitebal = 128;
738         q->top = 1;
739         q->left = 14;
740         return q;
741 }
742
743 static struct qcam_device *qcams[MAX_CAMS];
744 static unsigned int num_cams = 0;
745
746 int init_cqcam(struct parport *port)
747 {
748         struct qcam_device *qcam;
749
750         if (parport[0] != -1)
751         {
752                 /* The user gave specific instructions */
753                 int i, found = 0;
754                 for (i = 0; i < MAX_CAMS && parport[i] != -1; i++)
755                 {
756                         if (parport[0] == port->number)
757                                 found = 1;
758                 }
759                 if (!found)
760                         return -ENODEV;
761         }
762
763         if (num_cams == MAX_CAMS)
764                 return -ENOSPC;
765
766         qcam = qcam_init(port);
767         if (qcam==NULL)
768                 return -ENODEV;
769                 
770         parport_claim_or_block(qcam->pdev);
771
772         qc_reset(qcam);
773         
774         if (probe && qc_detect(qcam)==0)
775         {
776                 parport_release(qcam->pdev);
777                 parport_unregister_device(qcam->pdev);
778                 kfree(qcam);
779                 return -ENODEV;
780         }
781
782         qc_setup(qcam);
783
784         parport_release(qcam->pdev);
785         
786         if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
787         {
788                 printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
789                        qcam->pport->name);
790                 parport_unregister_device(qcam->pdev);
791                 kfree(qcam);
792                 return -ENODEV;
793         }
794
795         printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", 
796                qcam->vdev.minor, qcam->pport->name);
797         
798         qcams[num_cams++] = qcam;
799
800         return 0;
801 }
802
803 void close_cqcam(struct qcam_device *qcam)
804 {
805         video_unregister_device(&qcam->vdev);
806         parport_unregister_device(qcam->pdev);
807         kfree(qcam);
808 }
809
810 static void cq_attach(struct parport *port)
811 {
812         init_cqcam(port);
813 }
814
815 static void cq_detach(struct parport *port)
816 {
817         /* Write this some day. */
818 }
819
820 static struct parport_driver cqcam_driver = {
821         .name = "cqcam",
822         .attach = cq_attach,
823         .detach = cq_detach,
824 };
825
826 static int __init cqcam_init (void)
827 {
828         printk(BANNER "\n");
829
830         return parport_register_driver(&cqcam_driver);
831 }
832
833 static void __exit cqcam_cleanup (void)
834 {
835         unsigned int i;
836
837         for (i = 0; i < num_cams; i++)
838                 close_cqcam(qcams[i]);
839
840         parport_unregister_driver(&cqcam_driver);
841 }
842
843 MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
844 MODULE_DESCRIPTION(BANNER);
845 MODULE_LICENSE("GPL");
846
847 MODULE_PARM_DESC(parport ,"parport=<auto|n[,n]...> for port detection method\n\
848 probe=<0|1|2> for camera detection method\n\
849 force_rgb=<0|1> for RGB data format (default BGR)");
850 MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i");
851 MODULE_PARM(probe, "i");
852 MODULE_PARM(force_rgb, "i");
853 MODULE_PARM(video_nr,"i");
854
855 module_init(cqcam_init);
856 module_exit(cqcam_cleanup);