Linux Audio

Check our new training course

Loading...
  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 <media/v4l2-fh.h>
 66#include <media/v4l2-ctrls.h>
 67#include <media/v4l2-event.h>
 68#include <linux/parport.h>
 69
 70/*#define DEBUG*/				/* Undef me for production */
 71
 72#ifdef DEBUG
 73#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
 74#else
 75#define DPRINTF(x...)
 76#endif
 77
 78/*
 79 *	Defines, simple typedefs etc.
 80 */
 81
 82#define W9966_DRIVERNAME	"W9966CF Webcam"
 83#define W9966_MAXCAMS		4	/* Maximum number of cameras */
 84#define W9966_RBUFFER		2048	/* Read buffer (must be an even number) */
 85#define W9966_SRAMSIZE		131072	/* 128kb */
 86#define W9966_SRAMID		0x02	/* check w9966cf.pdf */
 87
 88/* Empirically determined window limits */
 89#define W9966_WND_MIN_X		16
 90#define W9966_WND_MIN_Y		14
 91#define W9966_WND_MAX_X		705
 92#define W9966_WND_MAX_Y		253
 93#define W9966_WND_MAX_W		(W9966_WND_MAX_X - W9966_WND_MIN_X)
 94#define W9966_WND_MAX_H		(W9966_WND_MAX_Y - W9966_WND_MIN_Y)
 95
 96/* Keep track of our current state */
 97#define W9966_STATE_PDEV	0x01
 98#define W9966_STATE_CLAIMED	0x02
 99#define W9966_STATE_VDEV	0x04
100
101#define W9966_I2C_W_ID		0x48
102#define W9966_I2C_R_ID		0x49
103#define W9966_I2C_R_DATA	0x08
104#define W9966_I2C_R_CLOCK	0x04
105#define W9966_I2C_W_DATA	0x02
106#define W9966_I2C_W_CLOCK	0x01
107
108struct w9966 {
109	struct v4l2_device v4l2_dev;
110	struct v4l2_ctrl_handler hdl;
111	unsigned char dev_state;
112	unsigned char i2c_state;
113	unsigned short ppmode;
114	struct parport *pport;
115	struct pardevice *pdev;
116	struct video_device vdev;
117	unsigned short width;
118	unsigned short height;
119	unsigned char brightness;
120	signed char contrast;
121	signed char color;
122	signed char hue;
123	struct mutex lock;
124};
125
126/*
127 *	Module specific properties
128 */
129
130MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
131MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
132MODULE_LICENSE("GPL");
133MODULE_VERSION("0.33.1");
134
135#ifdef MODULE
136static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
137#else
138static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
139#endif
140module_param_array(pardev, charp, NULL, 0);
141MODULE_PARM_DESC(pardev, "pardev: where to search for\n"
142		"\teach camera. 'aggressive' means brute-force search.\n"
143		"\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
144		"\tcam 1 to parport3 and search every parport for cam 2 etc...");
145
146static int parmode;
147module_param(parmode, int, 0);
148MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
149
150static int video_nr = -1;
151module_param(video_nr, int, 0);
152
153static struct w9966 w9966_cams[W9966_MAXCAMS];
154
155/*
156 *	Private function defines
157 */
158
159
160/* Set camera phase flags, so we know what to uninit when terminating */
161static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
162{
163	cam->dev_state = (cam->dev_state & ~mask) ^ val;
164}
165
166/* Get camera phase flags */
167static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
168{
169	return ((cam->dev_state & mask) == val);
170}
171
172/* Claim parport for ourself */
173static void w9966_pdev_claim(struct w9966 *cam)
174{
175	if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
176		return;
177	parport_claim_or_block(cam->pdev);
178	w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
179}
180
181/* Release parport for others to use */
182static void w9966_pdev_release(struct w9966 *cam)
183{
184	if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
185		return;
186	parport_release(cam->pdev);
187	w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
188}
189
190/* Read register from W9966 interface-chip
191   Expects a claimed pdev
192   -1 on error, else register data (byte) */
193static int w9966_read_reg(struct w9966 *cam, int reg)
194{
195	/* ECP, read, regtransfer, REG, REG, REG, REG, REG */
196	const unsigned char addr = 0x80 | (reg & 0x1f);
197	unsigned char val;
198
199	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
200		return -1;
201	if (parport_write(cam->pport, &addr, 1) != 1)
202		return -1;
203	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
204		return -1;
205	if (parport_read(cam->pport, &val, 1) != 1)
206		return -1;
207
208	return val;
209}
210
211/* Write register to W9966 interface-chip
212   Expects a claimed pdev
213   -1 on error */
214static int w9966_write_reg(struct w9966 *cam, int reg, int data)
215{
216	/* ECP, write, regtransfer, REG, REG, REG, REG, REG */
217	const unsigned char addr = 0xc0 | (reg & 0x1f);
218	const unsigned char val = data;
219
220	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
221		return -1;
222	if (parport_write(cam->pport, &addr, 1) != 1)
223		return -1;
224	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
225		return -1;
226	if (parport_write(cam->pport, &val, 1) != 1)
227		return -1;
228
229	return 0;
230}
231
232/*
233 *	Ugly and primitive i2c protocol functions
234 */
235
236/* Sets the data line on the i2c bus.
237   Expects a claimed pdev. */
238static void w9966_i2c_setsda(struct w9966 *cam, int state)
239{
240	if (state)
241		cam->i2c_state |= W9966_I2C_W_DATA;
242	else
243		cam->i2c_state &= ~W9966_I2C_W_DATA;
244
245	w9966_write_reg(cam, 0x18, cam->i2c_state);
246	udelay(5);
247}
248
249/* Get peripheral clock line
250   Expects a claimed pdev. */
251static int w9966_i2c_getscl(struct w9966 *cam)
252{
253	const unsigned char state = w9966_read_reg(cam, 0x18);
254	return ((state & W9966_I2C_R_CLOCK) > 0);
255}
256
257/* Sets the clock line on the i2c bus.
258   Expects a claimed pdev. -1 on error */
259static int w9966_i2c_setscl(struct w9966 *cam, int state)
260{
261	unsigned long timeout;
262
263	if (state)
264		cam->i2c_state |= W9966_I2C_W_CLOCK;
265	else
266		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
267
268	w9966_write_reg(cam, 0x18, cam->i2c_state);
269	udelay(5);
270
271	/* we go to high, we also expect the peripheral to ack. */
272	if (state) {
273		timeout = jiffies + 100;
274		while (!w9966_i2c_getscl(cam)) {
275			if (time_after(jiffies, timeout))
276				return -1;
277		}
278	}
279	return 0;
280}
281
282#if 0
283/* Get peripheral data line
284   Expects a claimed pdev. */
285static int w9966_i2c_getsda(struct w9966 *cam)
286{
287	const unsigned char state = w9966_read_reg(cam, 0x18);
288	return ((state & W9966_I2C_R_DATA) > 0);
289}
290#endif
291
292/* Write a byte with ack to the i2c bus.
293   Expects a claimed pdev. -1 on error */
294static int w9966_i2c_wbyte(struct w9966 *cam, int data)
295{
296	int i;
297
298	for (i = 7; i >= 0; i--) {
299		w9966_i2c_setsda(cam, (data >> i) & 0x01);
300
301		if (w9966_i2c_setscl(cam, 1) == -1)
302			return -1;
303		w9966_i2c_setscl(cam, 0);
304	}
305
306	w9966_i2c_setsda(cam, 1);
307
308	if (w9966_i2c_setscl(cam, 1) == -1)
309		return -1;
310	w9966_i2c_setscl(cam, 0);
311
312	return 0;
313}
314
315/* Read a data byte with ack from the i2c-bus
316   Expects a claimed pdev. -1 on error */
317#if 0
318static int w9966_i2c_rbyte(struct w9966 *cam)
319{
320	unsigned char data = 0x00;
321	int i;
322
323	w9966_i2c_setsda(cam, 1);
324
325	for (i = 0; i < 8; i++) {
326		if (w9966_i2c_setscl(cam, 1) == -1)
327			return -1;
328		data = data << 1;
329		if (w9966_i2c_getsda(cam))
330			data |= 0x01;
331
332		w9966_i2c_setscl(cam, 0);
333	}
334	return data;
335}
336#endif
337
338/* Read a register from the i2c device.
339   Expects claimed pdev. -1 on error */
340#if 0
341static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
342{
343	int data;
344
345	w9966_i2c_setsda(cam, 0);
346	w9966_i2c_setscl(cam, 0);
347
348	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
349	    w9966_i2c_wbyte(cam, reg) == -1)
350		return -1;
351
352	w9966_i2c_setsda(cam, 1);
353	if (w9966_i2c_setscl(cam, 1) == -1)
354		return -1;
355	w9966_i2c_setsda(cam, 0);
356	w9966_i2c_setscl(cam, 0);
357
358	if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
359		return -1;
360	data = w9966_i2c_rbyte(cam);
361	if (data == -1)
362		return -1;
363
364	w9966_i2c_setsda(cam, 0);
365
366	if (w9966_i2c_setscl(cam, 1) == -1)
367		return -1;
368	w9966_i2c_setsda(cam, 1);
369
370	return data;
371}
372#endif
373
374/* Write a register to the i2c device.
375   Expects claimed pdev. -1 on error */
376static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
377{
378	w9966_i2c_setsda(cam, 0);
379	w9966_i2c_setscl(cam, 0);
380
381	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
382			w9966_i2c_wbyte(cam, reg) == -1 ||
383			w9966_i2c_wbyte(cam, data) == -1)
384		return -1;
385
386	w9966_i2c_setsda(cam, 0);
387	if (w9966_i2c_setscl(cam, 1) == -1)
388		return -1;
389
390	w9966_i2c_setsda(cam, 1);
391
392	return 0;
393}
394
395/* Find a good length for capture window (used both for W and H)
396   A bit ugly but pretty functional. The capture length
397   have to match the downscale */
398static int w9966_findlen(int near, int size, int maxlen)
399{
400	int bestlen = size;
401	int besterr = abs(near - bestlen);
402	int len;
403
404	for (len = size + 1; len < maxlen; len++) {
405		int err;
406		if (((64 * size) % len) != 0)
407			continue;
408
409		err = abs(near - len);
410
411		/* Only continue as long as we keep getting better values */
412		if (err > besterr)
413			break;
414
415		besterr = err;
416		bestlen = len;
417	}
418
419	return bestlen;
420}
421
422/* Modify capture window (if necessary)
423   and calculate downscaling
424   Return -1 on error */
425static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
426{
427	int maxlen = max - min;
428	int len = *end - *beg + 1;
429	int newlen = w9966_findlen(len, size, maxlen);
430	int err = newlen - len;
431
432	/* Check for bad format */
433	if (newlen > maxlen || newlen < size)
434		return -1;
435
436	/* Set factor (6 bit fixed) */
437	*factor = (64 * size) / newlen;
438	if (*factor == 64)
439		*factor = 0x00;	/* downscale is disabled */
440	else
441		*factor |= 0x80; /* set downscale-enable bit */
442
443	/* Modify old beginning and end */
444	*beg -= err / 2;
445	*end += err - (err / 2);
446
447	/* Move window if outside borders */
448	if (*beg < min) {
449		*end += min - *beg;
450		*beg += min - *beg;
451	}
452	if (*end > max) {
453		*beg -= *end - max;
454		*end -= *end - max;
455	}
456
457	return 0;
458}
459
460/* Setup the cameras capture window etc.
461   Expects a claimed pdev
462   return -1 on error */
463static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
464{
465	unsigned int i;
466	unsigned int enh_s, enh_e;
467	unsigned char scale_x, scale_y;
468	unsigned char regs[0x1c];
469	unsigned char saa7111_regs[] = {
470		0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
471		0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
472		0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473		0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
474	};
475
476
477	if (w * h * 2 > W9966_SRAMSIZE) {
478		DPRINTF("capture window exceeds SRAM size!.\n");
479		w = 200; h = 160;	/* Pick default values */
480	}
481
482	w &= ~0x1;
483	if (w < 2)
484		w = 2;
485	if (h < 1)
486		h = 1;
487	if (w > W9966_WND_MAX_W)
488		w = W9966_WND_MAX_W;
489	if (h > W9966_WND_MAX_H)
490		h = W9966_WND_MAX_H;
491
492	cam->width = w;
493	cam->height = h;
494
495	enh_s = 0;
496	enh_e = w * h * 2;
497
498	/* Modify capture window if necessary and calculate downscaling */
499	if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
500			w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
501		return -1;
502
503	DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
504			w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
505
506	/* Setup registers */
507	regs[0x00] = 0x00;			/* Set normal operation */
508	regs[0x01] = 0x18;			/* Capture mode */
509	regs[0x02] = scale_y;			/* V-scaling */
510	regs[0x03] = scale_x;			/* H-scaling */
511
512	/* Capture window */
513	regs[0x04] = (x1 & 0x0ff);		/* X-start (8 low bits) */
514	regs[0x05] = (x1 & 0x300)>>8;		/* X-start (2 high bits) */
515	regs[0x06] = (y1 & 0x0ff);		/* Y-start (8 low bits) */
516	regs[0x07] = (y1 & 0x300)>>8;		/* Y-start (2 high bits) */
517	regs[0x08] = (x2 & 0x0ff);		/* X-end (8 low bits) */
518	regs[0x09] = (x2 & 0x300)>>8;		/* X-end (2 high bits) */
519	regs[0x0a] = (y2 & 0x0ff);		/* Y-end (8 low bits) */
520
521	regs[0x0c] = W9966_SRAMID;		/* SRAM-banks (1x 128kb) */
522
523	/* Enhancement layer */
524	regs[0x0d] = (enh_s & 0x000ff);		/* Enh. start (0-7) */
525	regs[0x0e] = (enh_s & 0x0ff00) >> 8;	/* Enh. start (8-15) */
526	regs[0x0f] = (enh_s & 0x70000) >> 16;	/* Enh. start (16-17/18??) */
527	regs[0x10] = (enh_e & 0x000ff);		/* Enh. end (0-7) */
528	regs[0x11] = (enh_e & 0x0ff00) >> 8;	/* Enh. end (8-15) */
529	regs[0x12] = (enh_e & 0x70000) >> 16;	/* Enh. end (16-17/18??) */
530
531	/* Misc */
532	regs[0x13] = 0x40;			/* VEE control (raw 4:2:2) */
533	regs[0x17] = 0x00;			/* ??? */
534	regs[0x18] = cam->i2c_state = 0x00;	/* Serial bus */
535	regs[0x19] = 0xff;			/* I/O port direction control */
536	regs[0x1a] = 0xff;			/* I/O port data register */
537	regs[0x1b] = 0x10;			/* ??? */
538
539	/* SAA7111 chip settings */
540	saa7111_regs[0x0a] = cam->brightness;
541	saa7111_regs[0x0b] = cam->contrast;
542	saa7111_regs[0x0c] = cam->color;
543	saa7111_regs[0x0d] = cam->hue;
544
545	/* Reset (ECP-fifo & serial-bus) */
546	if (w9966_write_reg(cam, 0x00, 0x03) == -1)
547		return -1;
548
549	/* Write regs to w9966cf chip */
550	for (i = 0; i < 0x1c; i++)
551		if (w9966_write_reg(cam, i, regs[i]) == -1)
552			return -1;
553
554	/* Write regs to saa7111 chip */
555	for (i = 0; i < 0x20; i++)
556		if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
557			return -1;
558
559	return 0;
560}
561
562/*
563 *	Video4linux interfacing
564 */
565
566static int cam_querycap(struct file *file, void  *priv,
567					struct v4l2_capability *vcap)
568{
569	struct w9966 *cam = video_drvdata(file);
570
571	strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
572	strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
573	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
574	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
575	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
576	return 0;
577}
578
579static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
580{
581	if (vin->index > 0)
582		return -EINVAL;
583	strlcpy(vin->name, "Camera", sizeof(vin->name));
584	vin->type = V4L2_INPUT_TYPE_CAMERA;
585	vin->audioset = 0;
586	vin->tuner = 0;
587	vin->std = 0;
588	vin->status = 0;
589	return 0;
590}
591
592static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
593{
594	*inp = 0;
595	return 0;
596}
597
598static int cam_s_input(struct file *file, void *fh, unsigned int inp)
599{
600	return (inp > 0) ? -EINVAL : 0;
601}
602
603static int cam_s_ctrl(struct v4l2_ctrl *ctrl)
604{
605	struct w9966 *cam =
606		container_of(ctrl->handler, struct w9966, hdl);
607	int ret = 0;
608
609	mutex_lock(&cam->lock);
610	switch (ctrl->id) {
611	case V4L2_CID_BRIGHTNESS:
612		cam->brightness = ctrl->val;
613		break;
614	case V4L2_CID_CONTRAST:
615		cam->contrast = ctrl->val;
616		break;
617	case V4L2_CID_SATURATION:
618		cam->color = ctrl->val;
619		break;
620	case V4L2_CID_HUE:
621		cam->hue = ctrl->val;
622		break;
623	default:
624		ret = -EINVAL;
625		break;
626	}
627
628	if (ret == 0) {
629		w9966_pdev_claim(cam);
630
631		if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
632		    w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
633		    w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
634		    w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) {
635			ret = -EIO;
636		}
637
638		w9966_pdev_release(cam);
639	}
640	mutex_unlock(&cam->lock);
641	return ret;
642}
643
644static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
645{
646	struct w9966 *cam = video_drvdata(file);
647	struct v4l2_pix_format *pix = &fmt->fmt.pix;
648
649	pix->width = cam->width;
650	pix->height = cam->height;
651	pix->pixelformat = V4L2_PIX_FMT_YUYV;
652	pix->field = V4L2_FIELD_NONE;
653	pix->bytesperline = 2 * cam->width;
654	pix->sizeimage = 2 * cam->width * cam->height;
655	/* Just a guess */
656	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
657	return 0;
658}
659
660static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
661{
662	struct v4l2_pix_format *pix = &fmt->fmt.pix;
663
664	if (pix->width < 2)
665		pix->width = 2;
666	if (pix->height < 1)
667		pix->height = 1;
668	if (pix->width > W9966_WND_MAX_W)
669		pix->width = W9966_WND_MAX_W;
670	if (pix->height > W9966_WND_MAX_H)
671		pix->height = W9966_WND_MAX_H;
672	pix->pixelformat = V4L2_PIX_FMT_YUYV;
673	pix->field = V4L2_FIELD_NONE;
674	pix->bytesperline = 2 * pix->width;
675	pix->sizeimage = 2 * pix->width * pix->height;
676	/* Just a guess */
677	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
678	return 0;
679}
680
681static int cam_s_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	int ret = cam_try_fmt_vid_cap(file, fh, fmt);
686
687	if (ret)
688		return ret;
689
690	mutex_lock(&cam->lock);
691	/* Update camera regs */
692	w9966_pdev_claim(cam);
693	ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height);
694	w9966_pdev_release(cam);
695	mutex_unlock(&cam->lock);
696	return ret;
697}
698
699static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
700{
701	static struct v4l2_fmtdesc formats[] = {
702		{ 0, 0, 0,
703		  "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
704		  { 0, 0, 0, 0 }
705		},
706	};
707	enum v4l2_buf_type type = fmt->type;
708
709	if (fmt->index > 0)
710		return -EINVAL;
711
712	*fmt = formats[fmt->index];
713	fmt->type = type;
714	return 0;
715}
716
717/* Capture data */
718static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
719		size_t count, loff_t *ppos)
720{
721	struct w9966 *cam = video_drvdata(file);
722	unsigned char addr = 0xa0;	/* ECP, read, CCD-transfer, 00000 */
723	unsigned char __user *dest = (unsigned char __user *)buf;
724	unsigned long dleft = count;
725	unsigned char *tbuf;
726
727	/* Why would anyone want more than this?? */
728	if (count > cam->width * cam->height * 2)
729		return -EINVAL;
730
731	mutex_lock(&cam->lock);
732	w9966_pdev_claim(cam);
733	w9966_write_reg(cam, 0x00, 0x02);	/* Reset ECP-FIFO buffer */
734	w9966_write_reg(cam, 0x00, 0x00);	/* Return to normal operation */
735	w9966_write_reg(cam, 0x01, 0x98);	/* Enable capture */
736
737	/* write special capture-addr and negotiate into data transfer */
738	if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
739			(parport_write(cam->pport, &addr, 1) != 1) ||
740			(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
741		w9966_pdev_release(cam);
742		mutex_unlock(&cam->lock);
743		return -EFAULT;
744	}
745
746	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
747	if (tbuf == NULL) {
748		count = -ENOMEM;
749		goto out;
750	}
751
752	while (dleft > 0) {
753		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
754
755		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
756			count = -EFAULT;
757			goto out;
758		}
759		if (copy_to_user(dest, tbuf, tsize) != 0) {
760			count = -EFAULT;
761			goto out;
762		}
763		dest += tsize;
764		dleft -= tsize;
765	}
766
767	w9966_write_reg(cam, 0x01, 0x18);	/* Disable capture */
768
769out:
770	kfree(tbuf);
771	w9966_pdev_release(cam);
772	mutex_unlock(&cam->lock);
773
774	return count;
775}
776
777static const struct v4l2_file_operations w9966_fops = {
778	.owner		= THIS_MODULE,
779	.open		= v4l2_fh_open,
780	.release	= v4l2_fh_release,
781	.poll		= v4l2_ctrl_poll,
782	.unlocked_ioctl = video_ioctl2,
783	.read           = w9966_v4l_read,
784};
785
786static const struct v4l2_ioctl_ops w9966_ioctl_ops = {
787	.vidioc_querycap    		    = cam_querycap,
788	.vidioc_g_input      		    = cam_g_input,
789	.vidioc_s_input      		    = cam_s_input,
790	.vidioc_enum_input   		    = cam_enum_input,
791	.vidioc_enum_fmt_vid_cap 	    = cam_enum_fmt_vid_cap,
792	.vidioc_g_fmt_vid_cap 		    = cam_g_fmt_vid_cap,
793	.vidioc_s_fmt_vid_cap  		    = cam_s_fmt_vid_cap,
794	.vidioc_try_fmt_vid_cap  	    = cam_try_fmt_vid_cap,
795	.vidioc_log_status		    = v4l2_ctrl_log_status,
796	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
797	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
798};
799
800static const struct v4l2_ctrl_ops cam_ctrl_ops = {
801	.s_ctrl = cam_s_ctrl,
802};
803
804
805/* Initialize camera device. Setup all internal flags, set a
806   default video mode, setup ccd-chip, register v4l device etc..
807   Also used for 'probing' of hardware.
808   -1 on error */
809static int w9966_init(struct w9966 *cam, struct parport *port)
810{
811	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
812
813	if (cam->dev_state != 0)
814		return -1;
815
816	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
817
818	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
819		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
820		return -1;
821	}
822
823	v4l2_ctrl_handler_init(&cam->hdl, 4);
824	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
825			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
826	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
827			  V4L2_CID_CONTRAST, -64, 64, 1, 64);
828	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
829			  V4L2_CID_SATURATION, -64, 64, 1, 64);
830	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
831			  V4L2_CID_HUE, -128, 127, 1, 0);
832	if (cam->hdl.error) {
833		v4l2_err(v4l2_dev, "couldn't register controls\n");
834		return -1;
835	}
836	cam->pport = port;
837	cam->brightness = 128;
838	cam->contrast = 64;
839	cam->color = 64;
840	cam->hue = 0;
841
842	/* Select requested transfer mode */
843	switch (parmode) {
844	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
845	case 0:
846		if (port->modes & PARPORT_MODE_ECP)
847			cam->ppmode = IEEE1284_MODE_ECP;
848		else if (port->modes & PARPORT_MODE_EPP)
849			cam->ppmode = IEEE1284_MODE_EPP;
850		else
851			cam->ppmode = IEEE1284_MODE_ECP;
852		break;
853	case 1:		/* hw- or sw-ecp */
854		cam->ppmode = IEEE1284_MODE_ECP;
855		break;
856	case 2:		/* hw- or sw-epp */
857		cam->ppmode = IEEE1284_MODE_EPP;
858		break;
859	}
860
861	/* Tell the parport driver that we exists */
862	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
863	if (cam->pdev == NULL) {
864		DPRINTF("parport_register_device() failed\n");
865		return -1;
866	}
867	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
868
869	w9966_pdev_claim(cam);
870
871	/* Setup a default capture mode */
872	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
873		DPRINTF("w9966_setup() failed.\n");
874		return -1;
875	}
876
877	w9966_pdev_release(cam);
878
879	/* Fill in the video_device struct and register us to v4l */
880	strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
881	cam->vdev.v4l2_dev = v4l2_dev;
882	cam->vdev.fops = &w9966_fops;
883	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
884	cam->vdev.release = video_device_release_empty;
885	cam->vdev.ctrl_handler = &cam->hdl;
886	set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
887	video_set_drvdata(&cam->vdev, cam);
888
889	mutex_init(&cam->lock);
890
891	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
892		return -1;
893
894	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
895
896	/* All ok */
897	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
898			cam->pport->name);
899	return 0;
900}
901
902
903/* Terminate everything gracefully */
904static void w9966_term(struct w9966 *cam)
905{
906	/* Unregister from v4l */
907	if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
908		video_unregister_device(&cam->vdev);
909		w9966_set_state(cam, W9966_STATE_VDEV, 0);
910	}
911
912	v4l2_ctrl_handler_free(&cam->hdl);
913
914	/* Terminate from IEEE1284 mode and release pdev block */
915	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
916		w9966_pdev_claim(cam);
917		parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
918		w9966_pdev_release(cam);
919	}
920
921	/* Unregister from parport */
922	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
923		parport_unregister_device(cam->pdev);
924		w9966_set_state(cam, W9966_STATE_PDEV, 0);
925	}
926	memset(cam, 0, sizeof(*cam));
927}
928
929
930/* Called once for every parport on init */
931static void w9966_attach(struct parport *port)
932{
933	int i;
934
935	for (i = 0; i < W9966_MAXCAMS; i++) {
936		if (w9966_cams[i].dev_state != 0)	/* Cam is already assigned */
937			continue;
938		if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
939			if (w9966_init(&w9966_cams[i], port) != 0)
940				w9966_term(&w9966_cams[i]);
941			break;	/* return */
942		}
943	}
944}
945
946/* Called once for every parport on termination */
947static void w9966_detach(struct parport *port)
948{
949	int i;
950
951	for (i = 0; i < W9966_MAXCAMS; i++)
952		if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
953			w9966_term(&w9966_cams[i]);
954}
955
956
957static struct parport_driver w9966_ppd = {
958	.name = W9966_DRIVERNAME,
959	.attach = w9966_attach,
960	.detach = w9966_detach,
961};
962
963/* Module entry point */
964static int __init w9966_mod_init(void)
965{
966	int i;
967
968	for (i = 0; i < W9966_MAXCAMS; i++)
969		w9966_cams[i].dev_state = 0;
970
971	return parport_register_driver(&w9966_ppd);
972}
973
974/* Module cleanup */
975static void __exit w9966_mod_term(void)
976{
977	parport_unregister_driver(&w9966_ppd);
978}
979
980module_init(w9966_mod_init);
981module_exit(w9966_mod_term);