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