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);