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