V4L/DVB: w9966: remove camelCase
[linux-2.6/btrfs-unstable.git] / drivers / media / video / w9966.c
blobb0719976845e56373d119c464e85f2853ab2a5b1
1 /*
2 Winbond w9966cf Webcam parport driver.
4 Version 0.32
6 Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 Supported devices:
24 *Lifeview FlyCam Supra (using the Philips saa7111a chip)
26 Does any other model using the w9966 interface chip exist ?
28 Todo:
30 *Add a working EPP mode, since DMA ECP read isn't implemented
31 in the parport drivers. (That's why it's so sloow)
33 *Add support for other ccd-control chips than the saa7111
34 please send me feedback on what kind of chips you have.
36 *Add proper probing. I don't know what's wrong with the IEEE1284
37 parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
38 and nibble read seems to be broken for some peripherals.
40 *Add probing for onboard SRAM, port directions etc. (if possible)
42 *Add support for the hardware compressed modes (maybe using v4l2)
44 *Fix better support for the capture window (no skewed images, v4l
45 interface to capt. window)
47 *Probably some bugs that I don't know of
49 Please support me by sending feedback!
51 Changes:
53 Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE
54 and owner support for newer module locks
57 #include <linux/module.h>
58 #include <linux/init.h>
59 #include <linux/delay.h>
60 #include <linux/videodev.h>
61 #include <linux/slab.h>
62 #include <media/v4l2-common.h>
63 #include <media/v4l2-ioctl.h>
64 #include <linux/parport.h>
66 /*#define DEBUG*/ /* Undef me for production */
68 #ifdef DEBUG
69 #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
70 #else
71 #define DPRINTF(x...)
72 #endif
75 * Defines, simple typedefs etc.
78 #define W9966_DRIVERNAME "W9966CF Webcam"
79 #define W9966_MAXCAMS 4 /* Maximum number of cameras */
80 #define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */
81 #define W9966_SRAMSIZE 131072 /* 128kb */
82 #define W9966_SRAMID 0x02 /* check w9966cf.pdf */
84 /* Empirically determined window limits */
85 #define W9966_WND_MIN_X 16
86 #define W9966_WND_MIN_Y 14
87 #define W9966_WND_MAX_X 705
88 #define W9966_WND_MAX_Y 253
89 #define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X)
90 #define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y)
92 /* Keep track of our current state */
93 #define W9966_STATE_PDEV 0x01
94 #define W9966_STATE_CLAIMED 0x02
95 #define W9966_STATE_VDEV 0x04
97 #define W9966_I2C_W_ID 0x48
98 #define W9966_I2C_R_ID 0x49
99 #define W9966_I2C_R_DATA 0x08
100 #define W9966_I2C_R_CLOCK 0x04
101 #define W9966_I2C_W_DATA 0x02
102 #define W9966_I2C_W_CLOCK 0x01
104 struct w9966_dev {
105 unsigned char dev_state;
106 unsigned char i2c_state;
107 unsigned short ppmode;
108 struct parport *pport;
109 struct pardevice *pdev;
110 struct video_device vdev;
111 unsigned short width;
112 unsigned short height;
113 unsigned char brightness;
114 signed char contrast;
115 signed char color;
116 signed char hue;
117 unsigned long in_use;
121 * Module specific properties
124 MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
125 MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
126 MODULE_LICENSE("GPL");
129 #ifdef MODULE
130 static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
131 #else
132 static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
133 #endif
134 module_param_array(pardev, charp, NULL, 0);
135 MODULE_PARM_DESC(pardev, "pardev: where to search for\n"
136 "\teach camera. 'aggressive' means brute-force search.\n"
137 "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
138 "\tcam 1 to parport3 and search every parport for cam 2 etc...");
140 static int parmode;
141 module_param(parmode, int, 0);
142 MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
144 static int video_nr = -1;
145 module_param(video_nr, int, 0);
147 static struct w9966_dev w9966_cams[W9966_MAXCAMS];
150 * Private function defines
154 /* Set camera phase flags, so we know what to uninit when terminating */
155 static inline void w9966_set_state(struct w9966_dev *cam, int mask, int val)
157 cam->dev_state = (cam->dev_state & ~mask) ^ val;
160 /* Get camera phase flags */
161 static inline int w9966_get_state(struct w9966_dev *cam, int mask, int val)
163 return ((cam->dev_state & mask) == val);
166 /* Claim parport for ourself */
167 static void w9966_pdev_claim(struct w9966_dev *cam)
169 if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
170 return;
171 parport_claim_or_block(cam->pdev);
172 w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
175 /* Release parport for others to use */
176 static void w9966_pdev_release(struct w9966_dev *cam)
178 if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
179 return;
180 parport_release(cam->pdev);
181 w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
184 /* Read register from W9966 interface-chip
185 Expects a claimed pdev
186 -1 on error, else register data (byte) */
187 static int w9966_read_reg(struct w9966_dev *cam, int reg)
189 /* ECP, read, regtransfer, REG, REG, REG, REG, REG */
190 const unsigned char addr = 0x80 | (reg & 0x1f);
191 unsigned char val;
193 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
194 return -1;
195 if (parport_write(cam->pport, &addr, 1) != 1)
196 return -1;
197 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
198 return -1;
199 if (parport_read(cam->pport, &val, 1) != 1)
200 return -1;
202 return val;
205 /* Write register to W9966 interface-chip
206 Expects a claimed pdev
207 -1 on error */
208 static int w9966_write_reg(struct w9966_dev *cam, int reg, int data)
210 /* ECP, write, regtransfer, REG, REG, REG, REG, REG */
211 const unsigned char addr = 0xc0 | (reg & 0x1f);
212 const unsigned char val = data;
214 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
215 return -1;
216 if (parport_write(cam->pport, &addr, 1) != 1)
217 return -1;
218 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
219 return -1;
220 if (parport_write(cam->pport, &val, 1) != 1)
221 return -1;
223 return 0;
227 * Ugly and primitive i2c protocol functions
230 /* Sets the data line on the i2c bus.
231 Expects a claimed pdev. */
232 static void w9966_i2c_setsda(struct w9966_dev *cam, int state)
234 if (state)
235 cam->i2c_state |= W9966_I2C_W_DATA;
236 else
237 cam->i2c_state &= ~W9966_I2C_W_DATA;
239 w9966_write_reg(cam, 0x18, cam->i2c_state);
240 udelay(5);
243 /* Get peripheral clock line
244 Expects a claimed pdev. */
245 static int w9966_i2c_getscl(struct w9966_dev *cam)
247 const unsigned char state = w9966_read_reg(cam, 0x18);
248 return ((state & W9966_I2C_R_CLOCK) > 0);
251 /* Sets the clock line on the i2c bus.
252 Expects a claimed pdev. -1 on error */
253 static int w9966_i2c_setscl(struct w9966_dev *cam, int state)
255 unsigned long timeout;
257 if (state)
258 cam->i2c_state |= W9966_I2C_W_CLOCK;
259 else
260 cam->i2c_state &= ~W9966_I2C_W_CLOCK;
262 w9966_write_reg(cam, 0x18, cam->i2c_state);
263 udelay(5);
265 /* we go to high, we also expect the peripheral to ack. */
266 if (state) {
267 timeout = jiffies + 100;
268 while (!w9966_i2c_getscl(cam)) {
269 if (time_after(jiffies, timeout))
270 return -1;
273 return 0;
276 #if 0
277 /* Get peripheral data line
278 Expects a claimed pdev. */
279 static int w9966_i2c_getsda(struct w9966_dev *cam)
281 const unsigned char state = w9966_read_reg(cam, 0x18);
282 return ((state & W9966_I2C_R_DATA) > 0);
284 #endif
286 /* Write a byte with ack to the i2c bus.
287 Expects a claimed pdev. -1 on error */
288 static int w9966_i2c_wbyte(struct w9966_dev *cam, int data)
290 int i;
292 for (i = 7; i >= 0; i--) {
293 w9966_i2c_setsda(cam, (data >> i) & 0x01);
295 if (w9966_i2c_setscl(cam, 1) == -1)
296 return -1;
297 w9966_i2c_setscl(cam, 0);
300 w9966_i2c_setsda(cam, 1);
302 if (w9966_i2c_setscl(cam, 1) == -1)
303 return -1;
304 w9966_i2c_setscl(cam, 0);
306 return 0;
309 /* Read a data byte with ack from the i2c-bus
310 Expects a claimed pdev. -1 on error */
311 #if 0
312 static int w9966_i2c_rbyte(struct w9966_dev *cam)
314 unsigned char data = 0x00;
315 int i;
317 w9966_i2c_setsda(cam, 1);
319 for (i = 0; i < 8; i++) {
320 if (w9966_i2c_setscl(cam, 1) == -1)
321 return -1;
322 data = data << 1;
323 if (w9966_i2c_getsda(cam))
324 data |= 0x01;
326 w9966_i2c_setscl(cam, 0);
328 return data;
330 #endif
332 /* Read a register from the i2c device.
333 Expects claimed pdev. -1 on error */
334 #if 0
335 static int w9966_read_reg_i2c(struct w9966_dev *cam, int reg)
337 int data;
339 w9966_i2c_setsda(cam, 0);
340 w9966_i2c_setscl(cam, 0);
342 if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
343 w9966_i2c_wbyte(cam, reg) == -1)
344 return -1;
346 w9966_i2c_setsda(cam, 1);
347 if (w9966_i2c_setscl(cam, 1) == -1)
348 return -1;
349 w9966_i2c_setsda(cam, 0);
350 w9966_i2c_setscl(cam, 0);
352 if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
353 return -1;
354 data = w9966_i2c_rbyte(cam);
355 if (data == -1)
356 return -1;
358 w9966_i2c_setsda(cam, 0);
360 if (w9966_i2c_setscl(cam, 1) == -1)
361 return -1;
362 w9966_i2c_setsda(cam, 1);
364 return data;
366 #endif
368 /* Write a register to the i2c device.
369 Expects claimed pdev. -1 on error */
370 static int w9966_write_reg_i2c(struct w9966_dev *cam, int reg, int data)
372 w9966_i2c_setsda(cam, 0);
373 w9966_i2c_setscl(cam, 0);
375 if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
376 w9966_i2c_wbyte(cam, reg) == -1 ||
377 w9966_i2c_wbyte(cam, data) == -1)
378 return -1;
380 w9966_i2c_setsda(cam, 0);
381 if (w9966_i2c_setscl(cam, 1) == -1)
382 return -1;
384 w9966_i2c_setsda(cam, 1);
386 return 0;
389 /* Find a good length for capture window (used both for W and H)
390 A bit ugly but pretty functional. The capture length
391 have to match the downscale */
392 static int w9966_findlen(int near, int size, int maxlen)
394 int bestlen = size;
395 int besterr = abs(near - bestlen);
396 int len;
398 for (len = size + 1; len < maxlen; len++) {
399 int err;
400 if (((64 * size) % len) != 0)
401 continue;
403 err = abs(near - len);
405 /* Only continue as long as we keep getting better values */
406 if (err > besterr)
407 break;
409 besterr = err;
410 bestlen = len;
413 return bestlen;
416 /* Modify capture window (if necessary)
417 and calculate downscaling
418 Return -1 on error */
419 static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
421 int maxlen = max - min;
422 int len = *end - *beg + 1;
423 int newlen = w9966_findlen(len, size, maxlen);
424 int err = newlen - len;
426 /* Check for bad format */
427 if (newlen > maxlen || newlen < size)
428 return -1;
430 /* Set factor (6 bit fixed) */
431 *factor = (64 * size) / newlen;
432 if (*factor == 64)
433 *factor = 0x00; /* downscale is disabled */
434 else
435 *factor |= 0x80; /* set downscale-enable bit */
437 /* Modify old beginning and end */
438 *beg -= err / 2;
439 *end += err - (err / 2);
441 /* Move window if outside borders */
442 if (*beg < min) {
443 *end += min - *beg;
444 *beg += min - *beg;
446 if (*end > max) {
447 *beg -= *end - max;
448 *end -= *end - max;
451 return 0;
454 /* Setup the cameras capture window etc.
455 Expects a claimed pdev
456 return -1 on error */
457 static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, int w, int h)
459 unsigned int i;
460 unsigned int enh_s, enh_e;
461 unsigned char scale_x, scale_y;
462 unsigned char regs[0x1c];
463 unsigned char saa7111_regs[] = {
464 0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
465 0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
466 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
471 if (w * h * 2 > W9966_SRAMSIZE) {
472 DPRINTF("capture window exceeds SRAM size!.\n");
473 w = 200; h = 160; /* Pick default values */
476 w &= ~0x1;
477 if (w < 2)
478 w = 2;
479 if (h < 1)
480 h = 1;
481 if (w > W9966_WND_MAX_W)
482 w = W9966_WND_MAX_W;
483 if (h > W9966_WND_MAX_H)
484 h = W9966_WND_MAX_H;
486 cam->width = w;
487 cam->height = h;
489 enh_s = 0;
490 enh_e = w * h * 2;
492 /* Modify capture window if necessary and calculate downscaling */
493 if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
494 w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
495 return -1;
497 DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
498 w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
500 /* Setup registers */
501 regs[0x00] = 0x00; /* Set normal operation */
502 regs[0x01] = 0x18; /* Capture mode */
503 regs[0x02] = scale_y; /* V-scaling */
504 regs[0x03] = scale_x; /* H-scaling */
506 /* Capture window */
507 regs[0x04] = (x1 & 0x0ff); /* X-start (8 low bits) */
508 regs[0x05] = (x1 & 0x300)>>8; /* X-start (2 high bits) */
509 regs[0x06] = (y1 & 0x0ff); /* Y-start (8 low bits) */
510 regs[0x07] = (y1 & 0x300)>>8; /* Y-start (2 high bits) */
511 regs[0x08] = (x2 & 0x0ff); /* X-end (8 low bits) */
512 regs[0x09] = (x2 & 0x300)>>8; /* X-end (2 high bits) */
513 regs[0x0a] = (y2 & 0x0ff); /* Y-end (8 low bits) */
515 regs[0x0c] = W9966_SRAMID; /* SRAM-banks (1x 128kb) */
517 /* Enhancement layer */
518 regs[0x0d] = (enh_s & 0x000ff); /* Enh. start (0-7) */
519 regs[0x0e] = (enh_s & 0x0ff00) >> 8; /* Enh. start (8-15) */
520 regs[0x0f] = (enh_s & 0x70000) >> 16; /* Enh. start (16-17/18??) */
521 regs[0x10] = (enh_e & 0x000ff); /* Enh. end (0-7) */
522 regs[0x11] = (enh_e & 0x0ff00) >> 8; /* Enh. end (8-15) */
523 regs[0x12] = (enh_e & 0x70000) >> 16; /* Enh. end (16-17/18??) */
525 /* Misc */
526 regs[0x13] = 0x40; /* VEE control (raw 4:2:2) */
527 regs[0x17] = 0x00; /* ??? */
528 regs[0x18] = cam->i2c_state = 0x00; /* Serial bus */
529 regs[0x19] = 0xff; /* I/O port direction control */
530 regs[0x1a] = 0xff; /* I/O port data register */
531 regs[0x1b] = 0x10; /* ??? */
533 /* SAA7111 chip settings */
534 saa7111_regs[0x0a] = cam->brightness;
535 saa7111_regs[0x0b] = cam->contrast;
536 saa7111_regs[0x0c] = cam->color;
537 saa7111_regs[0x0d] = cam->hue;
539 /* Reset (ECP-fifo & serial-bus) */
540 if (w9966_write_reg(cam, 0x00, 0x03) == -1)
541 return -1;
543 /* Write regs to w9966cf chip */
544 for (i = 0; i < 0x1c; i++)
545 if (w9966_write_reg(cam, i, regs[i]) == -1)
546 return -1;
548 /* Write regs to saa7111 chip */
549 for (i = 0; i < 0x20; i++)
550 if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
551 return -1;
553 return 0;
557 * Video4linux interfacing
560 static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
562 struct w9966_dev *cam = video_drvdata(file);
564 switch (cmd) {
565 case VIDIOCGCAP:
567 static struct video_capability vcap = {
568 .name = W9966_DRIVERNAME,
569 .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES,
570 .channels = 1,
571 .maxwidth = W9966_WND_MAX_W,
572 .maxheight = W9966_WND_MAX_H,
573 .minwidth = 2,
574 .minheight = 1,
576 struct video_capability *cap = arg;
577 *cap = vcap;
578 return 0;
580 case VIDIOCGCHAN:
582 struct video_channel *vch = arg;
583 if (vch->channel != 0) /* We only support one channel (#0) */
584 return -EINVAL;
585 memset(vch, 0, sizeof(*vch));
586 strcpy(vch->name, "CCD-input");
587 vch->type = VIDEO_TYPE_CAMERA;
588 return 0;
590 case VIDIOCSCHAN:
592 struct video_channel *vch = arg;
593 if (vch->channel != 0)
594 return -EINVAL;
595 return 0;
597 case VIDIOCGTUNER:
599 struct video_tuner *vtune = arg;
600 if (vtune->tuner != 0)
601 return -EINVAL;
602 strcpy(vtune->name, "no tuner");
603 vtune->rangelow = 0;
604 vtune->rangehigh = 0;
605 vtune->flags = VIDEO_TUNER_NORM;
606 vtune->mode = VIDEO_MODE_AUTO;
607 vtune->signal = 0xffff;
608 return 0;
610 case VIDIOCSTUNER:
612 struct video_tuner *vtune = arg;
613 if (vtune->tuner != 0)
614 return -EINVAL;
615 if (vtune->mode != VIDEO_MODE_AUTO)
616 return -EINVAL;
617 return 0;
619 case VIDIOCGPICT:
621 struct video_picture vpic = {
622 cam->brightness << 8, /* brightness */
623 (cam->hue + 128) << 8, /* hue */
624 cam->color << 9, /* color */
625 cam->contrast << 9, /* contrast */
626 0x8000, /* whiteness */
627 16, VIDEO_PALETTE_YUV422/* bpp, palette format */
629 struct video_picture *pic = arg;
630 *pic = vpic;
631 return 0;
633 case VIDIOCSPICT:
635 struct video_picture *vpic = arg;
636 if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV))
637 return -EINVAL;
639 cam->brightness = vpic->brightness >> 8;
640 cam->hue = (vpic->hue >> 8) - 128;
641 cam->color = vpic->colour >> 9;
642 cam->contrast = vpic->contrast >> 9;
644 w9966_pdev_claim(cam);
646 if (
647 w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
648 w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
649 w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
650 w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1
652 w9966_pdev_release(cam);
653 return -EIO;
656 w9966_pdev_release(cam);
657 return 0;
659 case VIDIOCSWIN:
661 int ret;
662 struct video_window *vwin = arg;
664 if (vwin->flags != 0)
665 return -EINVAL;
666 if (vwin->clipcount != 0)
667 return -EINVAL;
668 if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W)
669 return -EINVAL;
670 if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H)
671 return -EINVAL;
673 /* Update camera regs */
674 w9966_pdev_claim(cam);
675 ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height);
676 w9966_pdev_release(cam);
678 if (ret != 0) {
679 DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");
680 return -EIO;
683 return 0;
685 case VIDIOCGWIN:
687 struct video_window *vwin = arg;
688 memset(vwin, 0, sizeof(*vwin));
689 vwin->width = cam->width;
690 vwin->height = cam->height;
691 return 0;
693 /* Unimplemented */
694 case VIDIOCCAPTURE:
695 case VIDIOCGFBUF:
696 case VIDIOCSFBUF:
697 case VIDIOCKEY:
698 case VIDIOCGFREQ:
699 case VIDIOCSFREQ:
700 case VIDIOCGAUDIO:
701 case VIDIOCSAUDIO:
702 return -EINVAL;
703 default:
704 return -ENOIOCTLCMD;
706 return 0;
709 static long w9966_v4l_ioctl(struct file *file,
710 unsigned int cmd, unsigned long arg)
712 return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl);
715 /* Capture data */
716 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
717 size_t count, loff_t *ppos)
719 struct w9966_dev *cam = video_drvdata(file);
720 unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */
721 unsigned char __user *dest = (unsigned char __user *)buf;
722 unsigned long dleft = count;
723 unsigned char *tbuf;
725 /* Why would anyone want more than this?? */
726 if (count > cam->width * cam->height * 2)
727 return -EINVAL;
729 w9966_pdev_claim(cam);
730 w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */
731 w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */
732 w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */
734 /* write special capture-addr and negotiate into data transfer */
735 if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
736 (parport_write(cam->pport, &addr, 1) != 1) ||
737 (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
738 w9966_pdev_release(cam);
739 return -EFAULT;
742 tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
743 if (tbuf == NULL) {
744 count = -ENOMEM;
745 goto out;
748 while (dleft > 0) {
749 unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
751 if (parport_read(cam->pport, tbuf, tsize) < tsize) {
752 count = -EFAULT;
753 goto out;
755 if (copy_to_user(dest, tbuf, tsize) != 0) {
756 count = -EFAULT;
757 goto out;
759 dest += tsize;
760 dleft -= tsize;
763 w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */
765 out:
766 kfree(tbuf);
767 w9966_pdev_release(cam);
769 return count;
772 static int w9966_exclusive_open(struct file *file)
774 struct w9966_dev *cam = video_drvdata(file);
776 return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
779 static int w9966_exclusive_release(struct file *file)
781 struct w9966_dev *cam = video_drvdata(file);
783 clear_bit(0, &cam->in_use);
784 return 0;
787 static const struct v4l2_file_operations w9966_fops = {
788 .owner = THIS_MODULE,
789 .open = w9966_exclusive_open,
790 .release = w9966_exclusive_release,
791 .ioctl = w9966_v4l_ioctl,
792 .read = w9966_v4l_read,
795 static struct video_device w9966_template = {
796 .name = W9966_DRIVERNAME,
797 .fops = &w9966_fops,
798 .release = video_device_release_empty,
802 /* Initialize camera device. Setup all internal flags, set a
803 default video mode, setup ccd-chip, register v4l device etc..
804 Also used for 'probing' of hardware.
805 -1 on error */
806 static int w9966_init(struct w9966_dev *cam, struct parport* port)
808 if (cam->dev_state != 0)
809 return -1;
811 cam->pport = port;
812 cam->brightness = 128;
813 cam->contrast = 64;
814 cam->color = 64;
815 cam->hue = 0;
817 /* Select requested transfer mode */
818 switch (parmode) {
819 default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
820 case 0:
821 if (port->modes & PARPORT_MODE_ECP)
822 cam->ppmode = IEEE1284_MODE_ECP;
823 else if (port->modes & PARPORT_MODE_EPP)
824 cam->ppmode = IEEE1284_MODE_EPP;
825 else
826 cam->ppmode = IEEE1284_MODE_ECP;
827 break;
828 case 1: /* hw- or sw-ecp */
829 cam->ppmode = IEEE1284_MODE_ECP;
830 break;
831 case 2: /* hw- or sw-epp */
832 cam->ppmode = IEEE1284_MODE_EPP;
833 break;
836 /* Tell the parport driver that we exists */
837 cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
838 if (cam->pdev == NULL) {
839 DPRINTF("parport_register_device() failed\n");
840 return -1;
842 w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
844 w9966_pdev_claim(cam);
846 /* Setup a default capture mode */
847 if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
848 DPRINTF("w9966_setup() failed.\n");
849 return -1;
852 w9966_pdev_release(cam);
854 /* Fill in the video_device struct and register us to v4l */
855 memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
856 video_set_drvdata(&cam->vdev, cam);
858 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
859 return -1;
861 w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
863 /* All ok */
864 printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n",
865 cam->pport->name);
866 return 0;
870 /* Terminate everything gracefully */
871 static void w9966_term(struct w9966_dev *cam)
873 /* Unregister from v4l */
874 if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
875 video_unregister_device(&cam->vdev);
876 w9966_set_state(cam, W9966_STATE_VDEV, 0);
879 /* Terminate from IEEE1284 mode and release pdev block */
880 if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
881 w9966_pdev_claim(cam);
882 parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
883 w9966_pdev_release(cam);
886 /* Unregister from parport */
887 if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
888 parport_unregister_device(cam->pdev);
889 w9966_set_state(cam, W9966_STATE_PDEV, 0);
894 /* Called once for every parport on init */
895 static void w9966_attach(struct parport *port)
897 int i;
899 for (i = 0; i < W9966_MAXCAMS; i++) {
900 if (w9966_cams[i].dev_state != 0) /* Cam is already assigned */
901 continue;
902 if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
903 if (w9966_init(&w9966_cams[i], port) != 0)
904 w9966_term(&w9966_cams[i]);
905 break; /* return */
910 /* Called once for every parport on termination */
911 static void w9966_detach(struct parport *port)
913 int i;
915 for (i = 0; i < W9966_MAXCAMS; i++)
916 if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
917 w9966_term(&w9966_cams[i]);
921 static struct parport_driver w9966_ppd = {
922 .name = W9966_DRIVERNAME,
923 .attach = w9966_attach,
924 .detach = w9966_detach,
927 /* Module entry point */
928 static int __init w9966_mod_init(void)
930 int i;
932 for (i = 0; i < W9966_MAXCAMS; i++)
933 w9966_cams[i].dev_state = 0;
935 return parport_register_driver(&w9966_ppd);
938 /* Module cleanup */
939 static void __exit w9966_mod_term(void)
941 parport_unregister_driver(&w9966_ppd);
944 module_init(w9966_mod_init);
945 module_exit(w9966_mod_term);