2 Winbond w9966cf Webcam parport driver.
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.
24 *Lifeview FlyCam Supra (using the Philips saa7111a chip)
26 Does any other model using the w9966 interface chip exist ?
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!
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/videodev2.h>
61 #include <linux/slab.h>
62 #include <media/v4l2-common.h>
63 #include <media/v4l2-ioctl.h>
64 #include <media/v4l2-device.h>
65 #include <linux/parport.h>
67 /*#define DEBUG*/ /* Undef me for production */
70 #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
76 * Defines, simple typedefs etc.
79 #define W9966_DRIVERNAME "W9966CF Webcam"
80 #define W9966_MAXCAMS 4 /* Maximum number of cameras */
81 #define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */
82 #define W9966_SRAMSIZE 131072 /* 128kb */
83 #define W9966_SRAMID 0x02 /* check w9966cf.pdf */
85 /* Empirically determined window limits */
86 #define W9966_WND_MIN_X 16
87 #define W9966_WND_MIN_Y 14
88 #define W9966_WND_MAX_X 705
89 #define W9966_WND_MAX_Y 253
90 #define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X)
91 #define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y)
93 /* Keep track of our current state */
94 #define W9966_STATE_PDEV 0x01
95 #define W9966_STATE_CLAIMED 0x02
96 #define W9966_STATE_VDEV 0x04
98 #define W9966_I2C_W_ID 0x48
99 #define W9966_I2C_R_ID 0x49
100 #define W9966_I2C_R_DATA 0x08
101 #define W9966_I2C_R_CLOCK 0x04
102 #define W9966_I2C_W_DATA 0x02
103 #define W9966_I2C_W_CLOCK 0x01
106 struct v4l2_device v4l2_dev
;
107 unsigned char dev_state
;
108 unsigned char i2c_state
;
109 unsigned short ppmode
;
110 struct parport
*pport
;
111 struct pardevice
*pdev
;
112 struct video_device vdev
;
113 unsigned short width
;
114 unsigned short height
;
115 unsigned char brightness
;
116 signed char contrast
;
123 * Module specific properties
126 MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
127 MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
128 MODULE_LICENSE("GPL");
129 MODULE_VERSION("0.33.1");
132 static const char *pardev
[] = {[0 ... W9966_MAXCAMS
] = ""};
134 static const char *pardev
[] = {[0 ... W9966_MAXCAMS
] = "aggressive"};
136 module_param_array(pardev
, charp
, NULL
, 0);
137 MODULE_PARM_DESC(pardev
, "pardev: where to search for\n"
138 "\teach camera. 'aggressive' means brute-force search.\n"
139 "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
140 "\tcam 1 to parport3 and search every parport for cam 2 etc...");
143 module_param(parmode
, int, 0);
144 MODULE_PARM_DESC(parmode
, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
146 static int video_nr
= -1;
147 module_param(video_nr
, int, 0);
149 static struct w9966 w9966_cams
[W9966_MAXCAMS
];
152 * Private function defines
156 /* Set camera phase flags, so we know what to uninit when terminating */
157 static inline void w9966_set_state(struct w9966
*cam
, int mask
, int val
)
159 cam
->dev_state
= (cam
->dev_state
& ~mask
) ^ val
;
162 /* Get camera phase flags */
163 static inline int w9966_get_state(struct w9966
*cam
, int mask
, int val
)
165 return ((cam
->dev_state
& mask
) == val
);
168 /* Claim parport for ourself */
169 static void w9966_pdev_claim(struct w9966
*cam
)
171 if (w9966_get_state(cam
, W9966_STATE_CLAIMED
, W9966_STATE_CLAIMED
))
173 parport_claim_or_block(cam
->pdev
);
174 w9966_set_state(cam
, W9966_STATE_CLAIMED
, W9966_STATE_CLAIMED
);
177 /* Release parport for others to use */
178 static void w9966_pdev_release(struct w9966
*cam
)
180 if (w9966_get_state(cam
, W9966_STATE_CLAIMED
, 0))
182 parport_release(cam
->pdev
);
183 w9966_set_state(cam
, W9966_STATE_CLAIMED
, 0);
186 /* Read register from W9966 interface-chip
187 Expects a claimed pdev
188 -1 on error, else register data (byte) */
189 static int w9966_read_reg(struct w9966
*cam
, int reg
)
191 /* ECP, read, regtransfer, REG, REG, REG, REG, REG */
192 const unsigned char addr
= 0x80 | (reg
& 0x1f);
195 if (parport_negotiate(cam
->pport
, cam
->ppmode
| IEEE1284_ADDR
) != 0)
197 if (parport_write(cam
->pport
, &addr
, 1) != 1)
199 if (parport_negotiate(cam
->pport
, cam
->ppmode
| IEEE1284_DATA
) != 0)
201 if (parport_read(cam
->pport
, &val
, 1) != 1)
207 /* Write register to W9966 interface-chip
208 Expects a claimed pdev
210 static int w9966_write_reg(struct w9966
*cam
, int reg
, int data
)
212 /* ECP, write, regtransfer, REG, REG, REG, REG, REG */
213 const unsigned char addr
= 0xc0 | (reg
& 0x1f);
214 const unsigned char val
= data
;
216 if (parport_negotiate(cam
->pport
, cam
->ppmode
| IEEE1284_ADDR
) != 0)
218 if (parport_write(cam
->pport
, &addr
, 1) != 1)
220 if (parport_negotiate(cam
->pport
, cam
->ppmode
| IEEE1284_DATA
) != 0)
222 if (parport_write(cam
->pport
, &val
, 1) != 1)
229 * Ugly and primitive i2c protocol functions
232 /* Sets the data line on the i2c bus.
233 Expects a claimed pdev. */
234 static void w9966_i2c_setsda(struct w9966
*cam
, int state
)
237 cam
->i2c_state
|= W9966_I2C_W_DATA
;
239 cam
->i2c_state
&= ~W9966_I2C_W_DATA
;
241 w9966_write_reg(cam
, 0x18, cam
->i2c_state
);
245 /* Get peripheral clock line
246 Expects a claimed pdev. */
247 static int w9966_i2c_getscl(struct w9966
*cam
)
249 const unsigned char state
= w9966_read_reg(cam
, 0x18);
250 return ((state
& W9966_I2C_R_CLOCK
) > 0);
253 /* Sets the clock line on the i2c bus.
254 Expects a claimed pdev. -1 on error */
255 static int w9966_i2c_setscl(struct w9966
*cam
, int state
)
257 unsigned long timeout
;
260 cam
->i2c_state
|= W9966_I2C_W_CLOCK
;
262 cam
->i2c_state
&= ~W9966_I2C_W_CLOCK
;
264 w9966_write_reg(cam
, 0x18, cam
->i2c_state
);
267 /* we go to high, we also expect the peripheral to ack. */
269 timeout
= jiffies
+ 100;
270 while (!w9966_i2c_getscl(cam
)) {
271 if (time_after(jiffies
, timeout
))
279 /* Get peripheral data line
280 Expects a claimed pdev. */
281 static int w9966_i2c_getsda(struct w9966
*cam
)
283 const unsigned char state
= w9966_read_reg(cam
, 0x18);
284 return ((state
& W9966_I2C_R_DATA
) > 0);
288 /* Write a byte with ack to the i2c bus.
289 Expects a claimed pdev. -1 on error */
290 static int w9966_i2c_wbyte(struct w9966
*cam
, int data
)
294 for (i
= 7; i
>= 0; i
--) {
295 w9966_i2c_setsda(cam
, (data
>> i
) & 0x01);
297 if (w9966_i2c_setscl(cam
, 1) == -1)
299 w9966_i2c_setscl(cam
, 0);
302 w9966_i2c_setsda(cam
, 1);
304 if (w9966_i2c_setscl(cam
, 1) == -1)
306 w9966_i2c_setscl(cam
, 0);
311 /* Read a data byte with ack from the i2c-bus
312 Expects a claimed pdev. -1 on error */
314 static int w9966_i2c_rbyte(struct w9966
*cam
)
316 unsigned char data
= 0x00;
319 w9966_i2c_setsda(cam
, 1);
321 for (i
= 0; i
< 8; i
++) {
322 if (w9966_i2c_setscl(cam
, 1) == -1)
325 if (w9966_i2c_getsda(cam
))
328 w9966_i2c_setscl(cam
, 0);
334 /* Read a register from the i2c device.
335 Expects claimed pdev. -1 on error */
337 static int w9966_read_reg_i2c(struct w9966
*cam
, int reg
)
341 w9966_i2c_setsda(cam
, 0);
342 w9966_i2c_setscl(cam
, 0);
344 if (w9966_i2c_wbyte(cam
, W9966_I2C_W_ID
) == -1 ||
345 w9966_i2c_wbyte(cam
, reg
) == -1)
348 w9966_i2c_setsda(cam
, 1);
349 if (w9966_i2c_setscl(cam
, 1) == -1)
351 w9966_i2c_setsda(cam
, 0);
352 w9966_i2c_setscl(cam
, 0);
354 if (w9966_i2c_wbyte(cam
, W9966_I2C_R_ID
) == -1)
356 data
= w9966_i2c_rbyte(cam
);
360 w9966_i2c_setsda(cam
, 0);
362 if (w9966_i2c_setscl(cam
, 1) == -1)
364 w9966_i2c_setsda(cam
, 1);
370 /* Write a register to the i2c device.
371 Expects claimed pdev. -1 on error */
372 static int w9966_write_reg_i2c(struct w9966
*cam
, int reg
, int data
)
374 w9966_i2c_setsda(cam
, 0);
375 w9966_i2c_setscl(cam
, 0);
377 if (w9966_i2c_wbyte(cam
, W9966_I2C_W_ID
) == -1 ||
378 w9966_i2c_wbyte(cam
, reg
) == -1 ||
379 w9966_i2c_wbyte(cam
, data
) == -1)
382 w9966_i2c_setsda(cam
, 0);
383 if (w9966_i2c_setscl(cam
, 1) == -1)
386 w9966_i2c_setsda(cam
, 1);
391 /* Find a good length for capture window (used both for W and H)
392 A bit ugly but pretty functional. The capture length
393 have to match the downscale */
394 static int w9966_findlen(int near
, int size
, int maxlen
)
397 int besterr
= abs(near
- bestlen
);
400 for (len
= size
+ 1; len
< maxlen
; len
++) {
402 if (((64 * size
) % len
) != 0)
405 err
= abs(near
- len
);
407 /* Only continue as long as we keep getting better values */
418 /* Modify capture window (if necessary)
419 and calculate downscaling
420 Return -1 on error */
421 static int w9966_calcscale(int size
, int min
, int max
, int *beg
, int *end
, unsigned char *factor
)
423 int maxlen
= max
- min
;
424 int len
= *end
- *beg
+ 1;
425 int newlen
= w9966_findlen(len
, size
, maxlen
);
426 int err
= newlen
- len
;
428 /* Check for bad format */
429 if (newlen
> maxlen
|| newlen
< size
)
432 /* Set factor (6 bit fixed) */
433 *factor
= (64 * size
) / newlen
;
435 *factor
= 0x00; /* downscale is disabled */
437 *factor
|= 0x80; /* set downscale-enable bit */
439 /* Modify old beginning and end */
441 *end
+= err
- (err
/ 2);
443 /* Move window if outside borders */
456 /* Setup the cameras capture window etc.
457 Expects a claimed pdev
458 return -1 on error */
459 static int w9966_setup(struct w9966
*cam
, int x1
, int y1
, int x2
, int y2
, int w
, int h
)
462 unsigned int enh_s
, enh_e
;
463 unsigned char scale_x
, scale_y
;
464 unsigned char regs
[0x1c];
465 unsigned char saa7111_regs
[] = {
466 0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
467 0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
468 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
473 if (w
* h
* 2 > W9966_SRAMSIZE
) {
474 DPRINTF("capture window exceeds SRAM size!.\n");
475 w
= 200; h
= 160; /* Pick default values */
483 if (w
> W9966_WND_MAX_W
)
485 if (h
> W9966_WND_MAX_H
)
494 /* Modify capture window if necessary and calculate downscaling */
495 if (w9966_calcscale(w
, W9966_WND_MIN_X
, W9966_WND_MAX_X
, &x1
, &x2
, &scale_x
) != 0 ||
496 w9966_calcscale(h
, W9966_WND_MIN_Y
, W9966_WND_MAX_Y
, &y1
, &y2
, &scale_y
) != 0)
499 DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
500 w
, h
, x1
, x2
, y1
, y2
, scale_x
& ~0x80, scale_y
& ~0x80);
502 /* Setup registers */
503 regs
[0x00] = 0x00; /* Set normal operation */
504 regs
[0x01] = 0x18; /* Capture mode */
505 regs
[0x02] = scale_y
; /* V-scaling */
506 regs
[0x03] = scale_x
; /* H-scaling */
509 regs
[0x04] = (x1
& 0x0ff); /* X-start (8 low bits) */
510 regs
[0x05] = (x1
& 0x300)>>8; /* X-start (2 high bits) */
511 regs
[0x06] = (y1
& 0x0ff); /* Y-start (8 low bits) */
512 regs
[0x07] = (y1
& 0x300)>>8; /* Y-start (2 high bits) */
513 regs
[0x08] = (x2
& 0x0ff); /* X-end (8 low bits) */
514 regs
[0x09] = (x2
& 0x300)>>8; /* X-end (2 high bits) */
515 regs
[0x0a] = (y2
& 0x0ff); /* Y-end (8 low bits) */
517 regs
[0x0c] = W9966_SRAMID
; /* SRAM-banks (1x 128kb) */
519 /* Enhancement layer */
520 regs
[0x0d] = (enh_s
& 0x000ff); /* Enh. start (0-7) */
521 regs
[0x0e] = (enh_s
& 0x0ff00) >> 8; /* Enh. start (8-15) */
522 regs
[0x0f] = (enh_s
& 0x70000) >> 16; /* Enh. start (16-17/18??) */
523 regs
[0x10] = (enh_e
& 0x000ff); /* Enh. end (0-7) */
524 regs
[0x11] = (enh_e
& 0x0ff00) >> 8; /* Enh. end (8-15) */
525 regs
[0x12] = (enh_e
& 0x70000) >> 16; /* Enh. end (16-17/18??) */
528 regs
[0x13] = 0x40; /* VEE control (raw 4:2:2) */
529 regs
[0x17] = 0x00; /* ??? */
530 regs
[0x18] = cam
->i2c_state
= 0x00; /* Serial bus */
531 regs
[0x19] = 0xff; /* I/O port direction control */
532 regs
[0x1a] = 0xff; /* I/O port data register */
533 regs
[0x1b] = 0x10; /* ??? */
535 /* SAA7111 chip settings */
536 saa7111_regs
[0x0a] = cam
->brightness
;
537 saa7111_regs
[0x0b] = cam
->contrast
;
538 saa7111_regs
[0x0c] = cam
->color
;
539 saa7111_regs
[0x0d] = cam
->hue
;
541 /* Reset (ECP-fifo & serial-bus) */
542 if (w9966_write_reg(cam
, 0x00, 0x03) == -1)
545 /* Write regs to w9966cf chip */
546 for (i
= 0; i
< 0x1c; i
++)
547 if (w9966_write_reg(cam
, i
, regs
[i
]) == -1)
550 /* Write regs to saa7111 chip */
551 for (i
= 0; i
< 0x20; i
++)
552 if (w9966_write_reg_i2c(cam
, i
, saa7111_regs
[i
]) == -1)
559 * Video4linux interfacing
562 static int cam_querycap(struct file
*file
, void *priv
,
563 struct v4l2_capability
*vcap
)
565 struct w9966
*cam
= video_drvdata(file
);
567 strlcpy(vcap
->driver
, cam
->v4l2_dev
.name
, sizeof(vcap
->driver
));
568 strlcpy(vcap
->card
, W9966_DRIVERNAME
, sizeof(vcap
->card
));
569 strlcpy(vcap
->bus_info
, "parport", sizeof(vcap
->bus_info
));
570 vcap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_READWRITE
;
574 static int cam_enum_input(struct file
*file
, void *fh
, struct v4l2_input
*vin
)
578 strlcpy(vin
->name
, "Camera", sizeof(vin
->name
));
579 vin
->type
= V4L2_INPUT_TYPE_CAMERA
;
587 static int cam_g_input(struct file
*file
, void *fh
, unsigned int *inp
)
593 static int cam_s_input(struct file
*file
, void *fh
, unsigned int inp
)
595 return (inp
> 0) ? -EINVAL
: 0;
598 static int cam_queryctrl(struct file
*file
, void *priv
,
599 struct v4l2_queryctrl
*qc
)
602 case V4L2_CID_BRIGHTNESS
:
603 return v4l2_ctrl_query_fill(qc
, 0, 255, 1, 128);
604 case V4L2_CID_CONTRAST
:
605 return v4l2_ctrl_query_fill(qc
, -64, 64, 1, 64);
606 case V4L2_CID_SATURATION
:
607 return v4l2_ctrl_query_fill(qc
, -64, 64, 1, 64);
609 return v4l2_ctrl_query_fill(qc
, -128, 127, 1, 0);
614 static int cam_g_ctrl(struct file
*file
, void *priv
,
615 struct v4l2_control
*ctrl
)
617 struct w9966
*cam
= video_drvdata(file
);
621 case V4L2_CID_BRIGHTNESS
:
622 ctrl
->value
= cam
->brightness
;
624 case V4L2_CID_CONTRAST
:
625 ctrl
->value
= cam
->contrast
;
627 case V4L2_CID_SATURATION
:
628 ctrl
->value
= cam
->color
;
631 ctrl
->value
= cam
->hue
;
640 static int cam_s_ctrl(struct file
*file
, void *priv
,
641 struct v4l2_control
*ctrl
)
643 struct w9966
*cam
= video_drvdata(file
);
646 mutex_lock(&cam
->lock
);
648 case V4L2_CID_BRIGHTNESS
:
649 cam
->brightness
= ctrl
->value
;
651 case V4L2_CID_CONTRAST
:
652 cam
->contrast
= ctrl
->value
;
654 case V4L2_CID_SATURATION
:
655 cam
->color
= ctrl
->value
;
658 cam
->hue
= ctrl
->value
;
666 w9966_pdev_claim(cam
);
668 if (w9966_write_reg_i2c(cam
, 0x0a, cam
->brightness
) == -1 ||
669 w9966_write_reg_i2c(cam
, 0x0b, cam
->contrast
) == -1 ||
670 w9966_write_reg_i2c(cam
, 0x0c, cam
->color
) == -1 ||
671 w9966_write_reg_i2c(cam
, 0x0d, cam
->hue
) == -1) {
675 w9966_pdev_release(cam
);
677 mutex_unlock(&cam
->lock
);
681 static int cam_g_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
683 struct w9966
*cam
= video_drvdata(file
);
684 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
686 pix
->width
= cam
->width
;
687 pix
->height
= cam
->height
;
688 pix
->pixelformat
= V4L2_PIX_FMT_YUYV
;
689 pix
->field
= V4L2_FIELD_NONE
;
690 pix
->bytesperline
= 2 * cam
->width
;
691 pix
->sizeimage
= 2 * cam
->width
* cam
->height
;
693 pix
->colorspace
= V4L2_COLORSPACE_SMPTE170M
;
697 static int cam_try_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
699 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
705 if (pix
->width
> W9966_WND_MAX_W
)
706 pix
->width
= W9966_WND_MAX_W
;
707 if (pix
->height
> W9966_WND_MAX_H
)
708 pix
->height
= W9966_WND_MAX_H
;
709 pix
->pixelformat
= V4L2_PIX_FMT_YUYV
;
710 pix
->field
= V4L2_FIELD_NONE
;
711 pix
->bytesperline
= 2 * pix
->width
;
712 pix
->sizeimage
= 2 * pix
->width
* pix
->height
;
714 pix
->colorspace
= V4L2_COLORSPACE_SMPTE170M
;
718 static int cam_s_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
720 struct w9966
*cam
= video_drvdata(file
);
721 struct v4l2_pix_format
*pix
= &fmt
->fmt
.pix
;
722 int ret
= cam_try_fmt_vid_cap(file
, fh
, fmt
);
727 mutex_lock(&cam
->lock
);
728 /* Update camera regs */
729 w9966_pdev_claim(cam
);
730 ret
= w9966_setup(cam
, 0, 0, 1023, 1023, pix
->width
, pix
->height
);
731 w9966_pdev_release(cam
);
732 mutex_unlock(&cam
->lock
);
736 static int cam_enum_fmt_vid_cap(struct file
*file
, void *fh
, struct v4l2_fmtdesc
*fmt
)
738 static struct v4l2_fmtdesc formats
[] = {
740 "YUV 4:2:2", V4L2_PIX_FMT_YUYV
,
744 enum v4l2_buf_type type
= fmt
->type
;
749 *fmt
= formats
[fmt
->index
];
755 static ssize_t
w9966_v4l_read(struct file
*file
, char __user
*buf
,
756 size_t count
, loff_t
*ppos
)
758 struct w9966
*cam
= video_drvdata(file
);
759 unsigned char addr
= 0xa0; /* ECP, read, CCD-transfer, 00000 */
760 unsigned char __user
*dest
= (unsigned char __user
*)buf
;
761 unsigned long dleft
= count
;
764 /* Why would anyone want more than this?? */
765 if (count
> cam
->width
* cam
->height
* 2)
768 mutex_lock(&cam
->lock
);
769 w9966_pdev_claim(cam
);
770 w9966_write_reg(cam
, 0x00, 0x02); /* Reset ECP-FIFO buffer */
771 w9966_write_reg(cam
, 0x00, 0x00); /* Return to normal operation */
772 w9966_write_reg(cam
, 0x01, 0x98); /* Enable capture */
774 /* write special capture-addr and negotiate into data transfer */
775 if ((parport_negotiate(cam
->pport
, cam
->ppmode
|IEEE1284_ADDR
) != 0) ||
776 (parport_write(cam
->pport
, &addr
, 1) != 1) ||
777 (parport_negotiate(cam
->pport
, cam
->ppmode
|IEEE1284_DATA
) != 0)) {
778 w9966_pdev_release(cam
);
779 mutex_unlock(&cam
->lock
);
783 tbuf
= kmalloc(W9966_RBUFFER
, GFP_KERNEL
);
790 unsigned long tsize
= (dleft
> W9966_RBUFFER
) ? W9966_RBUFFER
: dleft
;
792 if (parport_read(cam
->pport
, tbuf
, tsize
) < tsize
) {
796 if (copy_to_user(dest
, tbuf
, tsize
) != 0) {
804 w9966_write_reg(cam
, 0x01, 0x18); /* Disable capture */
808 w9966_pdev_release(cam
);
809 mutex_unlock(&cam
->lock
);
814 static const struct v4l2_file_operations w9966_fops
= {
815 .owner
= THIS_MODULE
,
816 .unlocked_ioctl
= video_ioctl2
,
817 .read
= w9966_v4l_read
,
820 static const struct v4l2_ioctl_ops w9966_ioctl_ops
= {
821 .vidioc_querycap
= cam_querycap
,
822 .vidioc_g_input
= cam_g_input
,
823 .vidioc_s_input
= cam_s_input
,
824 .vidioc_enum_input
= cam_enum_input
,
825 .vidioc_queryctrl
= cam_queryctrl
,
826 .vidioc_g_ctrl
= cam_g_ctrl
,
827 .vidioc_s_ctrl
= cam_s_ctrl
,
828 .vidioc_enum_fmt_vid_cap
= cam_enum_fmt_vid_cap
,
829 .vidioc_g_fmt_vid_cap
= cam_g_fmt_vid_cap
,
830 .vidioc_s_fmt_vid_cap
= cam_s_fmt_vid_cap
,
831 .vidioc_try_fmt_vid_cap
= cam_try_fmt_vid_cap
,
835 /* Initialize camera device. Setup all internal flags, set a
836 default video mode, setup ccd-chip, register v4l device etc..
837 Also used for 'probing' of hardware.
839 static int w9966_init(struct w9966
*cam
, struct parport
*port
)
841 struct v4l2_device
*v4l2_dev
= &cam
->v4l2_dev
;
843 if (cam
->dev_state
!= 0)
846 strlcpy(v4l2_dev
->name
, "w9966", sizeof(v4l2_dev
->name
));
848 if (v4l2_device_register(NULL
, v4l2_dev
) < 0) {
849 v4l2_err(v4l2_dev
, "Could not register v4l2_device\n");
853 cam
->brightness
= 128;
858 /* Select requested transfer mode */
860 default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
862 if (port
->modes
& PARPORT_MODE_ECP
)
863 cam
->ppmode
= IEEE1284_MODE_ECP
;
864 else if (port
->modes
& PARPORT_MODE_EPP
)
865 cam
->ppmode
= IEEE1284_MODE_EPP
;
867 cam
->ppmode
= IEEE1284_MODE_ECP
;
869 case 1: /* hw- or sw-ecp */
870 cam
->ppmode
= IEEE1284_MODE_ECP
;
872 case 2: /* hw- or sw-epp */
873 cam
->ppmode
= IEEE1284_MODE_EPP
;
877 /* Tell the parport driver that we exists */
878 cam
->pdev
= parport_register_device(port
, "w9966", NULL
, NULL
, NULL
, 0, NULL
);
879 if (cam
->pdev
== NULL
) {
880 DPRINTF("parport_register_device() failed\n");
883 w9966_set_state(cam
, W9966_STATE_PDEV
, W9966_STATE_PDEV
);
885 w9966_pdev_claim(cam
);
887 /* Setup a default capture mode */
888 if (w9966_setup(cam
, 0, 0, 1023, 1023, 200, 160) != 0) {
889 DPRINTF("w9966_setup() failed.\n");
893 w9966_pdev_release(cam
);
895 /* Fill in the video_device struct and register us to v4l */
896 strlcpy(cam
->vdev
.name
, W9966_DRIVERNAME
, sizeof(cam
->vdev
.name
));
897 cam
->vdev
.v4l2_dev
= v4l2_dev
;
898 cam
->vdev
.fops
= &w9966_fops
;
899 cam
->vdev
.ioctl_ops
= &w9966_ioctl_ops
;
900 cam
->vdev
.release
= video_device_release_empty
;
901 video_set_drvdata(&cam
->vdev
, cam
);
903 mutex_init(&cam
->lock
);
905 if (video_register_device(&cam
->vdev
, VFL_TYPE_GRABBER
, video_nr
) < 0)
908 w9966_set_state(cam
, W9966_STATE_VDEV
, W9966_STATE_VDEV
);
911 v4l2_info(v4l2_dev
, "Found and initialized a webcam on %s.\n",
917 /* Terminate everything gracefully */
918 static void w9966_term(struct w9966
*cam
)
920 /* Unregister from v4l */
921 if (w9966_get_state(cam
, W9966_STATE_VDEV
, W9966_STATE_VDEV
)) {
922 video_unregister_device(&cam
->vdev
);
923 w9966_set_state(cam
, W9966_STATE_VDEV
, 0);
926 /* Terminate from IEEE1284 mode and release pdev block */
927 if (w9966_get_state(cam
, W9966_STATE_PDEV
, W9966_STATE_PDEV
)) {
928 w9966_pdev_claim(cam
);
929 parport_negotiate(cam
->pport
, IEEE1284_MODE_COMPAT
);
930 w9966_pdev_release(cam
);
933 /* Unregister from parport */
934 if (w9966_get_state(cam
, W9966_STATE_PDEV
, W9966_STATE_PDEV
)) {
935 parport_unregister_device(cam
->pdev
);
936 w9966_set_state(cam
, W9966_STATE_PDEV
, 0);
938 memset(cam
, 0, sizeof(*cam
));
942 /* Called once for every parport on init */
943 static void w9966_attach(struct parport
*port
)
947 for (i
= 0; i
< W9966_MAXCAMS
; i
++) {
948 if (w9966_cams
[i
].dev_state
!= 0) /* Cam is already assigned */
950 if (strcmp(pardev
[i
], "aggressive") == 0 || strcmp(pardev
[i
], port
->name
) == 0) {
951 if (w9966_init(&w9966_cams
[i
], port
) != 0)
952 w9966_term(&w9966_cams
[i
]);
958 /* Called once for every parport on termination */
959 static void w9966_detach(struct parport
*port
)
963 for (i
= 0; i
< W9966_MAXCAMS
; i
++)
964 if (w9966_cams
[i
].dev_state
!= 0 && w9966_cams
[i
].pport
== port
)
965 w9966_term(&w9966_cams
[i
]);
969 static struct parport_driver w9966_ppd
= {
970 .name
= W9966_DRIVERNAME
,
971 .attach
= w9966_attach
,
972 .detach
= w9966_detach
,
975 /* Module entry point */
976 static int __init
w9966_mod_init(void)
980 for (i
= 0; i
< W9966_MAXCAMS
; i
++)
981 w9966_cams
[i
].dev_state
= 0;
983 return parport_register_driver(&w9966_ppd
);
987 static void __exit
w9966_mod_term(void)
989 parport_unregister_driver(&w9966_ppd
);
992 module_init(w9966_mod_init
);
993 module_exit(w9966_mod_term
);