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
105struct 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
126MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
127MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
128MODULE_LICENSE("GPL");
129MODULE_VERSION("0.33.1");
130
131#ifdef MODULE
132static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
133#else
134static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
135#endif
136module_param_array(pardev, charp, NULL, 0);
137MODULE_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
142static int parmode;
143module_param(parmode, int, 0);
144MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
145
146static int video_nr = -1;
147module_param(video_nr, int, 0);
148
149static 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 */
157static 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 */
163static 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 */
169static 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 */
178static 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) */
189static 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 */
210static 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. */
234static 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. */
247static 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 */
255static 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. */
281static 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 */
290static 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
314static 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
337static 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 */
372static 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 */
394static 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 */
421static 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 */
459static 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
562static 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
574static 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
587static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
588{
589	*inp = 0;
590	return 0;
591}
592
593static int cam_s_input(struct file *file, void *fh, unsigned int inp)
594{
595	return (inp > 0) ? -EINVAL : 0;
596}
597
598static 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
614static 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
640static 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
681static 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
697static 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
718static 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
736static 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 */
755static 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
806out:
807	kfree(tbuf);
808	w9966_pdev_release(cam);
809	mutex_unlock(&cam->lock);
810
811	return count;
812}
813
814static const struct v4l2_file_operations w9966_fops = {
815	.owner		= THIS_MODULE,
816	.unlocked_ioctl = video_ioctl2,
817	.read           = w9966_v4l_read,
818};
819
820static 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 */
839static 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 */
918static 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 */
943static 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 */
959static 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
969static struct parport_driver w9966_ppd = {
970	.name = W9966_DRIVERNAME,
971	.attach = w9966_attach,
972	.detach = w9966_detach,
973};
974
975/* Module entry point */
976static 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 */
987static void __exit w9966_mod_term(void)
988{
989	parport_unregister_driver(&w9966_ppd);
990}
991
992module_init(w9966_mod_init);
993module_exit(w9966_mod_term);
994