1 /*
2 	Winbond w9966cf Webcam parport driver.
3 
4 	Version 0.33
5 
6 	Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
7 
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.
12 
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.
17 
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.
21 */
22 /*
23 	Supported devices:
24 	*Lifeview FlyCam Supra (using the Philips saa7111a chip)
25 
26 	Does any other model using the w9966 interface chip exist ?
27 
28 	Todo:
29 
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)
32 
33 	*Add support for other ccd-control chips than the saa7111
34 	please send me feedback on what kind of chips you have.
35 
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.
39 
40 	*Add probing for onboard SRAM, port directions etc. (if possible)
41 
42 	*Add support for the hardware compressed modes (maybe using v4l2)
43 
44 	*Fix better support for the capture window (no skewed images, v4l
45 	interface to capt. window)
46 
47 	*Probably some bugs that I don't know of
48 
49 	Please support me by sending feedback!
50 
51 	Changes:
52 
53 	Alan Cox:	Removed RGB mode for kernel merge, added THIS_MODULE
54 			and owner support for newer module locks
55 */
56 
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>
66 
67 /*#define DEBUG*/				/* Undef me for production */
68 
69 #ifdef DEBUG
70 #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
71 #else
72 #define DPRINTF(x...)
73 #endif
74 
75 /*
76  *	Defines, simple typedefs etc.
77  */
78 
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 */
84 
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)
92 
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
97 
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
104 
105 struct w9966 {
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;
117 	signed char color;
118 	signed char hue;
119 	struct mutex lock;
120 };
121 
122 /*
123  *	Module specific properties
124  */
125 
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");
130 
131 #ifdef MODULE
132 static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
133 #else
134 static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
135 #endif
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...");
141 
142 static int parmode;
143 module_param(parmode, int, 0);
144 MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
145 
146 static int video_nr = -1;
147 module_param(video_nr, int, 0);
148 
149 static struct w9966 w9966_cams[W9966_MAXCAMS];
150 
151 /*
152  *	Private function defines
153  */
154 
155 
156 /* Set camera phase flags, so we know what to uninit when terminating */
w9966_set_state(struct w9966 * cam,int mask,int val)157 static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
158 {
159 	cam->dev_state = (cam->dev_state & ~mask) ^ val;
160 }
161 
162 /* Get camera phase flags */
w9966_get_state(struct w9966 * cam,int mask,int val)163 static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
164 {
165 	return ((cam->dev_state & mask) == val);
166 }
167 
168 /* Claim parport for ourself */
w9966_pdev_claim(struct w9966 * cam)169 static void w9966_pdev_claim(struct w9966 *cam)
170 {
171 	if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
172 		return;
173 	parport_claim_or_block(cam->pdev);
174 	w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
175 }
176 
177 /* Release parport for others to use */
w9966_pdev_release(struct w9966 * cam)178 static void w9966_pdev_release(struct w9966 *cam)
179 {
180 	if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
181 		return;
182 	parport_release(cam->pdev);
183 	w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
184 }
185 
186 /* Read register from W9966 interface-chip
187    Expects a claimed pdev
188    -1 on error, else register data (byte) */
w9966_read_reg(struct w9966 * cam,int reg)189 static int w9966_read_reg(struct w9966 *cam, int reg)
190 {
191 	/* ECP, read, regtransfer, REG, REG, REG, REG, REG */
192 	const unsigned char addr = 0x80 | (reg & 0x1f);
193 	unsigned char val;
194 
195 	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
196 		return -1;
197 	if (parport_write(cam->pport, &addr, 1) != 1)
198 		return -1;
199 	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
200 		return -1;
201 	if (parport_read(cam->pport, &val, 1) != 1)
202 		return -1;
203 
204 	return val;
205 }
206 
207 /* Write register to W9966 interface-chip
208    Expects a claimed pdev
209    -1 on error */
w9966_write_reg(struct w9966 * cam,int reg,int data)210 static int w9966_write_reg(struct w9966 *cam, int reg, int data)
211 {
212 	/* ECP, write, regtransfer, REG, REG, REG, REG, REG */
213 	const unsigned char addr = 0xc0 | (reg & 0x1f);
214 	const unsigned char val = data;
215 
216 	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
217 		return -1;
218 	if (parport_write(cam->pport, &addr, 1) != 1)
219 		return -1;
220 	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
221 		return -1;
222 	if (parport_write(cam->pport, &val, 1) != 1)
223 		return -1;
224 
225 	return 0;
226 }
227 
228 /*
229  *	Ugly and primitive i2c protocol functions
230  */
231 
232 /* Sets the data line on the i2c bus.
233    Expects a claimed pdev. */
w9966_i2c_setsda(struct w9966 * cam,int state)234 static void w9966_i2c_setsda(struct w9966 *cam, int state)
235 {
236 	if (state)
237 		cam->i2c_state |= W9966_I2C_W_DATA;
238 	else
239 		cam->i2c_state &= ~W9966_I2C_W_DATA;
240 
241 	w9966_write_reg(cam, 0x18, cam->i2c_state);
242 	udelay(5);
243 }
244 
245 /* Get peripheral clock line
246    Expects a claimed pdev. */
w9966_i2c_getscl(struct w9966 * cam)247 static int w9966_i2c_getscl(struct w9966 *cam)
248 {
249 	const unsigned char state = w9966_read_reg(cam, 0x18);
250 	return ((state & W9966_I2C_R_CLOCK) > 0);
251 }
252 
253 /* Sets the clock line on the i2c bus.
254    Expects a claimed pdev. -1 on error */
w9966_i2c_setscl(struct w9966 * cam,int state)255 static int w9966_i2c_setscl(struct w9966 *cam, int state)
256 {
257 	unsigned long timeout;
258 
259 	if (state)
260 		cam->i2c_state |= W9966_I2C_W_CLOCK;
261 	else
262 		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
263 
264 	w9966_write_reg(cam, 0x18, cam->i2c_state);
265 	udelay(5);
266 
267 	/* we go to high, we also expect the peripheral to ack. */
268 	if (state) {
269 		timeout = jiffies + 100;
270 		while (!w9966_i2c_getscl(cam)) {
271 			if (time_after(jiffies, timeout))
272 				return -1;
273 		}
274 	}
275 	return 0;
276 }
277 
278 #if 0
279 /* Get peripheral data line
280    Expects a claimed pdev. */
281 static int w9966_i2c_getsda(struct w9966 *cam)
282 {
283 	const unsigned char state = w9966_read_reg(cam, 0x18);
284 	return ((state & W9966_I2C_R_DATA) > 0);
285 }
286 #endif
287 
288 /* Write a byte with ack to the i2c bus.
289    Expects a claimed pdev. -1 on error */
w9966_i2c_wbyte(struct w9966 * cam,int data)290 static int w9966_i2c_wbyte(struct w9966 *cam, int data)
291 {
292 	int i;
293 
294 	for (i = 7; i >= 0; i--) {
295 		w9966_i2c_setsda(cam, (data >> i) & 0x01);
296 
297 		if (w9966_i2c_setscl(cam, 1) == -1)
298 			return -1;
299 		w9966_i2c_setscl(cam, 0);
300 	}
301 
302 	w9966_i2c_setsda(cam, 1);
303 
304 	if (w9966_i2c_setscl(cam, 1) == -1)
305 		return -1;
306 	w9966_i2c_setscl(cam, 0);
307 
308 	return 0;
309 }
310 
311 /* Read a data byte with ack from the i2c-bus
312    Expects a claimed pdev. -1 on error */
313 #if 0
314 static int w9966_i2c_rbyte(struct w9966 *cam)
315 {
316 	unsigned char data = 0x00;
317 	int i;
318 
319 	w9966_i2c_setsda(cam, 1);
320 
321 	for (i = 0; i < 8; i++) {
322 		if (w9966_i2c_setscl(cam, 1) == -1)
323 			return -1;
324 		data = data << 1;
325 		if (w9966_i2c_getsda(cam))
326 			data |= 0x01;
327 
328 		w9966_i2c_setscl(cam, 0);
329 	}
330 	return data;
331 }
332 #endif
333 
334 /* Read a register from the i2c device.
335    Expects claimed pdev. -1 on error */
336 #if 0
337 static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
338 {
339 	int data;
340 
341 	w9966_i2c_setsda(cam, 0);
342 	w9966_i2c_setscl(cam, 0);
343 
344 	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
345 	    w9966_i2c_wbyte(cam, reg) == -1)
346 		return -1;
347 
348 	w9966_i2c_setsda(cam, 1);
349 	if (w9966_i2c_setscl(cam, 1) == -1)
350 		return -1;
351 	w9966_i2c_setsda(cam, 0);
352 	w9966_i2c_setscl(cam, 0);
353 
354 	if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
355 		return -1;
356 	data = w9966_i2c_rbyte(cam);
357 	if (data == -1)
358 		return -1;
359 
360 	w9966_i2c_setsda(cam, 0);
361 
362 	if (w9966_i2c_setscl(cam, 1) == -1)
363 		return -1;
364 	w9966_i2c_setsda(cam, 1);
365 
366 	return data;
367 }
368 #endif
369 
370 /* Write a register to the i2c device.
371    Expects claimed pdev. -1 on error */
w9966_write_reg_i2c(struct w9966 * cam,int reg,int data)372 static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
373 {
374 	w9966_i2c_setsda(cam, 0);
375 	w9966_i2c_setscl(cam, 0);
376 
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)
380 		return -1;
381 
382 	w9966_i2c_setsda(cam, 0);
383 	if (w9966_i2c_setscl(cam, 1) == -1)
384 		return -1;
385 
386 	w9966_i2c_setsda(cam, 1);
387 
388 	return 0;
389 }
390 
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 */
w9966_findlen(int near,int size,int maxlen)394 static int w9966_findlen(int near, int size, int maxlen)
395 {
396 	int bestlen = size;
397 	int besterr = abs(near - bestlen);
398 	int len;
399 
400 	for (len = size + 1; len < maxlen; len++) {
401 		int err;
402 		if (((64 * size) % len) != 0)
403 			continue;
404 
405 		err = abs(near - len);
406 
407 		/* Only continue as long as we keep getting better values */
408 		if (err > besterr)
409 			break;
410 
411 		besterr = err;
412 		bestlen = len;
413 	}
414 
415 	return bestlen;
416 }
417 
418 /* Modify capture window (if necessary)
419    and calculate downscaling
420    Return -1 on error */
w9966_calcscale(int size,int min,int max,int * beg,int * end,unsigned char * factor)421 static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
422 {
423 	int maxlen = max - min;
424 	int len = *end - *beg + 1;
425 	int newlen = w9966_findlen(len, size, maxlen);
426 	int err = newlen - len;
427 
428 	/* Check for bad format */
429 	if (newlen > maxlen || newlen < size)
430 		return -1;
431 
432 	/* Set factor (6 bit fixed) */
433 	*factor = (64 * size) / newlen;
434 	if (*factor == 64)
435 		*factor = 0x00;	/* downscale is disabled */
436 	else
437 		*factor |= 0x80; /* set downscale-enable bit */
438 
439 	/* Modify old beginning and end */
440 	*beg -= err / 2;
441 	*end += err - (err / 2);
442 
443 	/* Move window if outside borders */
444 	if (*beg < min) {
445 		*end += min - *beg;
446 		*beg += min - *beg;
447 	}
448 	if (*end > max) {
449 		*beg -= *end - max;
450 		*end -= *end - max;
451 	}
452 
453 	return 0;
454 }
455 
456 /* Setup the cameras capture window etc.
457    Expects a claimed pdev
458    return -1 on error */
w9966_setup(struct w9966 * cam,int x1,int y1,int x2,int y2,int w,int h)459 static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
460 {
461 	unsigned int i;
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
470 	};
471 
472 
473 	if (w * h * 2 > W9966_SRAMSIZE) {
474 		DPRINTF("capture window exceeds SRAM size!.\n");
475 		w = 200; h = 160;	/* Pick default values */
476 	}
477 
478 	w &= ~0x1;
479 	if (w < 2)
480 		w = 2;
481 	if (h < 1)
482 		h = 1;
483 	if (w > W9966_WND_MAX_W)
484 		w = W9966_WND_MAX_W;
485 	if (h > W9966_WND_MAX_H)
486 		h = W9966_WND_MAX_H;
487 
488 	cam->width = w;
489 	cam->height = h;
490 
491 	enh_s = 0;
492 	enh_e = w * h * 2;
493 
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)
497 		return -1;
498 
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);
501 
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 */
507 
508 	/* Capture window */
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) */
516 
517 	regs[0x0c] = W9966_SRAMID;		/* SRAM-banks (1x 128kb) */
518 
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??) */
526 
527 	/* Misc */
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;			/* ??? */
534 
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;
540 
541 	/* Reset (ECP-fifo & serial-bus) */
542 	if (w9966_write_reg(cam, 0x00, 0x03) == -1)
543 		return -1;
544 
545 	/* Write regs to w9966cf chip */
546 	for (i = 0; i < 0x1c; i++)
547 		if (w9966_write_reg(cam, i, regs[i]) == -1)
548 			return -1;
549 
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)
553 			return -1;
554 
555 	return 0;
556 }
557 
558 /*
559  *	Video4linux interfacing
560  */
561 
cam_querycap(struct file * file,void * priv,struct v4l2_capability * vcap)562 static int cam_querycap(struct file *file, void  *priv,
563 					struct v4l2_capability *vcap)
564 {
565 	struct w9966 *cam = video_drvdata(file);
566 
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;
571 	return 0;
572 }
573 
cam_enum_input(struct file * file,void * fh,struct v4l2_input * vin)574 static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
575 {
576 	if (vin->index > 0)
577 		return -EINVAL;
578 	strlcpy(vin->name, "Camera", sizeof(vin->name));
579 	vin->type = V4L2_INPUT_TYPE_CAMERA;
580 	vin->audioset = 0;
581 	vin->tuner = 0;
582 	vin->std = 0;
583 	vin->status = 0;
584 	return 0;
585 }
586 
cam_g_input(struct file * file,void * fh,unsigned int * inp)587 static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
588 {
589 	*inp = 0;
590 	return 0;
591 }
592 
cam_s_input(struct file * file,void * fh,unsigned int inp)593 static int cam_s_input(struct file *file, void *fh, unsigned int inp)
594 {
595 	return (inp > 0) ? -EINVAL : 0;
596 }
597 
cam_queryctrl(struct file * file,void * priv,struct v4l2_queryctrl * qc)598 static int cam_queryctrl(struct file *file, void *priv,
599 					struct v4l2_queryctrl *qc)
600 {
601 	switch (qc->id) {
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);
608 	case V4L2_CID_HUE:
609 		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
610 	}
611 	return -EINVAL;
612 }
613 
cam_g_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)614 static int cam_g_ctrl(struct file *file, void *priv,
615 					struct v4l2_control *ctrl)
616 {
617 	struct w9966 *cam = video_drvdata(file);
618 	int ret = 0;
619 
620 	switch (ctrl->id) {
621 	case V4L2_CID_BRIGHTNESS:
622 		ctrl->value = cam->brightness;
623 		break;
624 	case V4L2_CID_CONTRAST:
625 		ctrl->value = cam->contrast;
626 		break;
627 	case V4L2_CID_SATURATION:
628 		ctrl->value = cam->color;
629 		break;
630 	case V4L2_CID_HUE:
631 		ctrl->value = cam->hue;
632 		break;
633 	default:
634 		ret = -EINVAL;
635 		break;
636 	}
637 	return ret;
638 }
639 
cam_s_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)640 static int cam_s_ctrl(struct file *file, void *priv,
641 					struct v4l2_control *ctrl)
642 {
643 	struct w9966 *cam = video_drvdata(file);
644 	int ret = 0;
645 
646 	mutex_lock(&cam->lock);
647 	switch (ctrl->id) {
648 	case V4L2_CID_BRIGHTNESS:
649 		cam->brightness = ctrl->value;
650 		break;
651 	case V4L2_CID_CONTRAST:
652 		cam->contrast = ctrl->value;
653 		break;
654 	case V4L2_CID_SATURATION:
655 		cam->color = ctrl->value;
656 		break;
657 	case V4L2_CID_HUE:
658 		cam->hue = ctrl->value;
659 		break;
660 	default:
661 		ret = -EINVAL;
662 		break;
663 	}
664 
665 	if (ret == 0) {
666 		w9966_pdev_claim(cam);
667 
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) {
672 			ret = -EIO;
673 		}
674 
675 		w9966_pdev_release(cam);
676 	}
677 	mutex_unlock(&cam->lock);
678 	return ret;
679 }
680 
cam_g_fmt_vid_cap(struct file * file,void * fh,struct v4l2_format * fmt)681 static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
682 {
683 	struct w9966 *cam = video_drvdata(file);
684 	struct v4l2_pix_format *pix = &fmt->fmt.pix;
685 
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;
692 	/* Just a guess */
693 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
694 	return 0;
695 }
696 
cam_try_fmt_vid_cap(struct file * file,void * fh,struct v4l2_format * fmt)697 static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
698 {
699 	struct v4l2_pix_format *pix = &fmt->fmt.pix;
700 
701 	if (pix->width < 2)
702 		pix->width = 2;
703 	if (pix->height < 1)
704 		pix->height = 1;
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;
713 	/* Just a guess */
714 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
715 	return 0;
716 }
717 
cam_s_fmt_vid_cap(struct file * file,void * fh,struct v4l2_format * fmt)718 static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
719 {
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);
723 
724 	if (ret)
725 		return ret;
726 
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);
733 	return ret;
734 }
735 
cam_enum_fmt_vid_cap(struct file * file,void * fh,struct v4l2_fmtdesc * fmt)736 static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
737 {
738 	static struct v4l2_fmtdesc formats[] = {
739 		{ 0, 0, 0,
740 		  "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
741 		  { 0, 0, 0, 0 }
742 		},
743 	};
744 	enum v4l2_buf_type type = fmt->type;
745 
746 	if (fmt->index > 0)
747 		return -EINVAL;
748 
749 	*fmt = formats[fmt->index];
750 	fmt->type = type;
751 	return 0;
752 }
753 
754 /* Capture data */
w9966_v4l_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)755 static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
756 		size_t count, loff_t *ppos)
757 {
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;
762 	unsigned char *tbuf;
763 
764 	/* Why would anyone want more than this?? */
765 	if (count > cam->width * cam->height * 2)
766 		return -EINVAL;
767 
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 */
773 
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);
780 		return -EFAULT;
781 	}
782 
783 	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
784 	if (tbuf == NULL) {
785 		count = -ENOMEM;
786 		goto out;
787 	}
788 
789 	while (dleft > 0) {
790 		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
791 
792 		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
793 			count = -EFAULT;
794 			goto out;
795 		}
796 		if (copy_to_user(dest, tbuf, tsize) != 0) {
797 			count = -EFAULT;
798 			goto out;
799 		}
800 		dest += tsize;
801 		dleft -= tsize;
802 	}
803 
804 	w9966_write_reg(cam, 0x01, 0x18);	/* Disable capture */
805 
806 out:
807 	kfree(tbuf);
808 	w9966_pdev_release(cam);
809 	mutex_unlock(&cam->lock);
810 
811 	return count;
812 }
813 
814 static const struct v4l2_file_operations w9966_fops = {
815 	.owner		= THIS_MODULE,
816 	.unlocked_ioctl = video_ioctl2,
817 	.read           = w9966_v4l_read,
818 };
819 
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,
832 };
833 
834 
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.
838    -1 on error */
w9966_init(struct w9966 * cam,struct parport * port)839 static int w9966_init(struct w9966 *cam, struct parport *port)
840 {
841 	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
842 
843 	if (cam->dev_state != 0)
844 		return -1;
845 
846 	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
847 
848 	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
849 		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
850 		return -1;
851 	}
852 	cam->pport = port;
853 	cam->brightness = 128;
854 	cam->contrast = 64;
855 	cam->color = 64;
856 	cam->hue = 0;
857 
858 	/* Select requested transfer mode */
859 	switch (parmode) {
860 	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
861 	case 0:
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;
866 		else
867 			cam->ppmode = IEEE1284_MODE_ECP;
868 		break;
869 	case 1:		/* hw- or sw-ecp */
870 		cam->ppmode = IEEE1284_MODE_ECP;
871 		break;
872 	case 2:		/* hw- or sw-epp */
873 		cam->ppmode = IEEE1284_MODE_EPP;
874 		break;
875 	}
876 
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");
881 		return -1;
882 	}
883 	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
884 
885 	w9966_pdev_claim(cam);
886 
887 	/* Setup a default capture mode */
888 	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
889 		DPRINTF("w9966_setup() failed.\n");
890 		return -1;
891 	}
892 
893 	w9966_pdev_release(cam);
894 
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);
902 
903 	mutex_init(&cam->lock);
904 
905 	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
906 		return -1;
907 
908 	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
909 
910 	/* All ok */
911 	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
912 			cam->pport->name);
913 	return 0;
914 }
915 
916 
917 /* Terminate everything gracefully */
w9966_term(struct w9966 * cam)918 static void w9966_term(struct w9966 *cam)
919 {
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);
924 	}
925 
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);
931 	}
932 
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);
937 	}
938 	memset(cam, 0, sizeof(*cam));
939 }
940 
941 
942 /* Called once for every parport on init */
w9966_attach(struct parport * port)943 static void w9966_attach(struct parport *port)
944 {
945 	int i;
946 
947 	for (i = 0; i < W9966_MAXCAMS; i++) {
948 		if (w9966_cams[i].dev_state != 0)	/* Cam is already assigned */
949 			continue;
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]);
953 			break;	/* return */
954 		}
955 	}
956 }
957 
958 /* Called once for every parport on termination */
w9966_detach(struct parport * port)959 static void w9966_detach(struct parport *port)
960 {
961 	int i;
962 
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]);
966 }
967 
968 
969 static struct parport_driver w9966_ppd = {
970 	.name = W9966_DRIVERNAME,
971 	.attach = w9966_attach,
972 	.detach = w9966_detach,
973 };
974 
975 /* Module entry point */
w9966_mod_init(void)976 static int __init w9966_mod_init(void)
977 {
978 	int i;
979 
980 	for (i = 0; i < W9966_MAXCAMS; i++)
981 		w9966_cams[i].dev_state = 0;
982 
983 	return parport_register_driver(&w9966_ppd);
984 }
985 
986 /* Module cleanup */
w9966_mod_term(void)987 static void __exit w9966_mod_term(void)
988 {
989 	parport_unregister_driver(&w9966_ppd);
990 }
991 
992 module_init(w9966_mod_init);
993 module_exit(w9966_mod_term);
994