• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/src/linux/linux-2.6/drivers/media/video/usbvideo/
1/*
2 * USB IBM C-It Video Camera driver
3 *
4 * Supports Xirlink C-It Video Camera, IBM PC Camera,
5 * IBM NetCamera and Veo Stingray.
6 *
7 * This driver is based on earlier work of:
8 *
9 * (C) Copyright 1999 Johannes Erdfelt
10 * (C) Copyright 1999 Randy Dunlap
11 *
12 * 5/24/00 Removed optional (and unnecessary) locking of the driver while
13 * the device remains plugged in. Corrected race conditions in ibmcam_open
14 * and ibmcam_probe() routines using this as a guideline:
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/init.h>
20
21#include "usbvideo.h"
22
23#define IBMCAM_VENDOR_ID	0x0545
24#define IBMCAM_PRODUCT_ID	0x8080
25#define NETCAM_PRODUCT_ID	0x8002	/* IBM NetCamera, close to model 2 */
26#define VEO_800C_PRODUCT_ID	0x800C	/* Veo Stingray, repackaged Model 2 */
27#define VEO_800D_PRODUCT_ID	0x800D	/* Veo Stingray, repackaged Model 4 */
28
29#define MAX_IBMCAM		4	/* How many devices we allow to connect */
30#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
31
32/* Header signatures */
33
34/* Model 1 header: 00 FF 00 xx */
35#define HDRSIG_MODEL1_128x96	0x06	/* U Y V Y ... */
36#define HDRSIG_MODEL1_176x144	0x0e	/* U Y V Y ... */
37#define HDRSIG_MODEL1_352x288	0x00	/* V Y U Y ... */
38
39#define	IBMCAM_MODEL_1	1	/* XVP-501, 3 interfaces, rev. 0.02 */
40#define IBMCAM_MODEL_2	2	/* KSX-X9903, 2 interfaces, rev. 3.0a */
41#define IBMCAM_MODEL_3	3	/* KSX-X9902, 2 interfaces, rev. 3.01 */
42#define	IBMCAM_MODEL_4	4	/* IBM NetCamera, 0545/8002/3.0a */
43
44/* Video sizes supported */
45#define	VIDEOSIZE_128x96	VIDEOSIZE(128, 96)
46#define	VIDEOSIZE_176x144	VIDEOSIZE(176,144)
47#define	VIDEOSIZE_352x288	VIDEOSIZE(352,288)
48#define	VIDEOSIZE_320x240	VIDEOSIZE(320,240)
49#define	VIDEOSIZE_352x240	VIDEOSIZE(352,240)
50#define	VIDEOSIZE_640x480	VIDEOSIZE(640,480)
51#define	VIDEOSIZE_160x120	VIDEOSIZE(160,120)
52
53/* Video sizes supported */
54enum {
55	SIZE_128x96 = 0,
56	SIZE_160x120,
57	SIZE_176x144,
58	SIZE_320x240,
59	SIZE_352x240,
60	SIZE_352x288,
61	SIZE_640x480,
62	/* Add/remove/rearrange items before this line */
63	SIZE_LastItem
64};
65
66/*
67 * This structure lives in uvd->user field.
68 */
69typedef struct {
70	int initialized;	/* Had we already sent init sequence? */
71	int camera_model;	/* What type of IBM camera we got? */
72	int has_hdr;
73} ibmcam_t;
74#define	IBMCAM_T(uvd)	((ibmcam_t *)((uvd)->user_data))
75
76static struct usbvideo *cams;
77
78static int debug;
79
80static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
81
82static const int min_canvasWidth  = 8;
83static const int min_canvasHeight = 4;
84
85static int lighting = 1; /* Medium */
86
87#define SHARPNESS_MIN	0
88#define SHARPNESS_MAX	6
89static int sharpness = 4; /* Low noise, good details */
90
91#define FRAMERATE_MIN	0
92#define FRAMERATE_MAX	6
93static int framerate = -1;
94
95static int size = SIZE_352x288;
96
97/*
98 * Here we define several initialization variables. They may
99 * be used to automatically set color, hue, brightness and
100 * contrast to desired values. This is particularly useful in
101 * case of webcams (which have no controls and no on-screen
102 * output) and also when a client V4L software is used that
103 * does not have some of those controls. In any case it's
104 * good to have startup values as options.
105 *
106 * These values are all in [0..255] range. This simplifies
107 * operation. Note that actual values of V4L variables may
108 * be scaled up (as much as << 8). User can see that only
109 * on overlay output, however, or through a V4L client.
110 */
111static int init_brightness = 128;
112static int init_contrast = 192;
113static int init_color = 128;
114static int init_hue = 128;
115static int hue_correction = 128;
116
117/* Settings for camera model 2 */
118static int init_model2_rg2 = -1;
119static int init_model2_sat = -1;
120static int init_model2_yb = -1;
121
122/* 01.01.08 - Added for RCA video in support -LO */
123/* Settings for camera model 3 */
124static int init_model3_input = 0;
125
126module_param(debug, int, 0);
127MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
128module_param(flags, int, 0);
129MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
130module_param(framerate, int, 0);
131MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
132module_param(lighting, int, 0);
133MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
134module_param(sharpness, int, 0);
135MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
136module_param(size, int, 0);
137MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
138module_param(init_brightness, int, 0);
139MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
140module_param(init_contrast, int, 0);
141MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
142module_param(init_color, int, 0);
143MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
144module_param(init_hue, int, 0);
145MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
146module_param(hue_correction, int, 0);
147MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
148
149module_param(init_model2_rg2, int, 0);
150MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
151module_param(init_model2_sat, int, 0);
152MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
153module_param(init_model2_yb, int, 0);
154MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
155
156/* 01.01.08 - Added for RCA video in support -LO */
157module_param(init_model3_input, int, 0);
158MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
159
160MODULE_AUTHOR ("Dmitri");
161MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
162MODULE_LICENSE("GPL");
163
164/* Still mysterious i2c commands */
165static const unsigned short unknown_88 = 0x0088;
166static const unsigned short unknown_89 = 0x0089;
167static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };
168static const unsigned short contrast_14 = 0x0014;
169static const unsigned short light_27 = 0x0027;
170static const unsigned short sharp_13 = 0x0013;
171
172/* i2c commands for Model 2 cameras */
173static const unsigned short mod2_brightness = 0x001a;		/* $5b .. $ee; default=$5a */
174static const unsigned short mod2_set_framerate = 0x001c;	/* 0 (fast).. $1F (slow) */
175static const unsigned short mod2_color_balance_rg2 = 0x001e;	/* 0 (red) .. $7F (green) */
176static const unsigned short mod2_saturation = 0x0020;		/* 0 (b/w) - $7F (full color) */
177static const unsigned short mod2_color_balance_yb = 0x0022;	/* 0..$7F, $50 is about right */
178static const unsigned short mod2_hue = 0x0024;			/* 0..$7F, $70 is about right */
179static const unsigned short mod2_sensitivity = 0x0028;		/* 0 (min) .. $1F (max) */
180
181struct struct_initData {
182	unsigned char req;
183	unsigned short value;
184	unsigned short index;
185};
186
187/*
188 * ibmcam_size_to_videosize()
189 *
190 * This procedure converts module option 'size' into the actual
191 * videosize_t that defines the image size in pixels. We need
192 * simplified 'size' because user wants a simple enumerated list
193 * of choices, not an infinite set of possibilities.
194 */
195static videosize_t ibmcam_size_to_videosize(int size)
196{
197	videosize_t vs = VIDEOSIZE_352x288;
198	RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1));
199	switch (size) {
200	case SIZE_128x96:
201		vs = VIDEOSIZE_128x96;
202		break;
203	case SIZE_160x120:
204		vs = VIDEOSIZE_160x120;
205		break;
206	case SIZE_176x144:
207		vs = VIDEOSIZE_176x144;
208		break;
209	case SIZE_320x240:
210		vs = VIDEOSIZE_320x240;
211		break;
212	case SIZE_352x240:
213		vs = VIDEOSIZE_352x240;
214		break;
215	case SIZE_352x288:
216		vs = VIDEOSIZE_352x288;
217		break;
218	case SIZE_640x480:
219		vs = VIDEOSIZE_640x480;
220		break;
221	default:
222		err("size=%d. is not valid", size);
223		break;
224	}
225	return vs;
226}
227
228/*
229 * ibmcam_find_header()
230 *
231 * Locate one of supported header markers in the queue.
232 * Once found, remove all preceding bytes AND the marker (4 bytes)
233 * from the data pump queue. Whatever follows must be video lines.
234 *
235 * History:
236 * 1/21/00  Created.
237 */
238static enum ParseState ibmcam_find_header(struct uvd *uvd)
239{
240	struct usbvideo_frame *frame;
241	ibmcam_t *icam;
242
243	if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
244		err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
245		return scan_EndParse;
246	}
247	icam = IBMCAM_T(uvd);
248	assert(icam != NULL);
249	frame = &uvd->frame[uvd->curframe];
250	icam->has_hdr = 0;
251	switch (icam->camera_model) {
252	case IBMCAM_MODEL_1:
253	{
254		const int marker_len = 4;
255		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
256			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
257			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
258			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
259			{
260				frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
261				if ((frame->header == HDRSIG_MODEL1_128x96) ||
262				    (frame->header == HDRSIG_MODEL1_176x144) ||
263				    (frame->header == HDRSIG_MODEL1_352x288))
264				{
265					RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
266					icam->has_hdr = 1;
267					break;
268				}
269			}
270			/* If we are still here then this doesn't look like a header */
271			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
272		}
273		break;
274	}
275	case IBMCAM_MODEL_2:
276case IBMCAM_MODEL_4:
277	{
278		int marker_len = 0;
279		switch (uvd->videosize) {
280		case VIDEOSIZE_176x144:
281			marker_len = 10;
282			break;
283		default:
284			marker_len = 2;
285			break;
286		}
287		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
288			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
289			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
290			{
291				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
292				icam->has_hdr = 1;
293				frame->header = HDRSIG_MODEL1_176x144;
294				break;
295			}
296			/* If we are still here then this doesn't look like a header */
297			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
298		}
299		break;
300	}
301	case IBMCAM_MODEL_3:
302	{	/*
303		 * Headers: (one precedes every frame). nc=no compression,
304		 * bq=best quality bf=best frame rate.
305		 *
306		 * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf }
307		 * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf }
308		 * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf }
309		 *
310		 * Bytes '00 FF' seem to indicate header. Other two bytes
311		 * encode the frame type. This is a set of bit fields that
312		 * encode image size, compression type etc. These fields
313		 * do NOT contain frame number because all frames carry
314		 * the same header.
315		 */
316		const int marker_len = 4;
317		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
318			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
319			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
320			    (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF))
321			{
322				/*
323				 * Combine 2 bytes of frame type into one
324				 * easy to use value
325				 */
326				unsigned long byte3, byte4;
327
328				byte3 = RING_QUEUE_PEEK(&uvd->dp, 2);
329				byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
330				frame->header = (byte3 << 8) | byte4;
331				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
332				icam->has_hdr = 1;
333				break;
334			}
335			/* If we are still here then this doesn't look like a header */
336			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
337		}
338		break;
339	}
340	default:
341		break;
342	}
343	if (!icam->has_hdr) {
344		if (uvd->debug > 2)
345			info("Skipping frame, no header");
346		return scan_EndParse;
347	}
348
349	/* Header found */
350	icam->has_hdr = 1;
351	uvd->stats.header_count++;
352	frame->scanstate = ScanState_Lines;
353	frame->curline = 0;
354
355	if (flags & FLAGS_FORCE_TESTPATTERN) {
356		usbvideo_TestPattern(uvd, 1, 1);
357		return scan_NextFrame;
358	}
359	return scan_Continue;
360}
361
362/*
363 * ibmcam_parse_lines()
364 *
365 * Parse one line (interlaced) from the buffer, put
366 * decoded RGB value into the current frame buffer
367 * and add the written number of bytes (RGB) to
368 * the *pcopylen.
369 *
370 * History:
371 * 21-Jan-2000 Created.
372 * 12-Oct-2000 Reworked to reflect interlaced nature of the data.
373 */
374static enum ParseState ibmcam_parse_lines(
375	struct uvd *uvd,
376	struct usbvideo_frame *frame,
377	long *pcopylen)
378{
379	unsigned char *f;
380	ibmcam_t *icam;
381	unsigned int len, scanLength, scanHeight, order_uv, order_yc;
382	int v4l_linesize; /* V4L line offset */
383	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
384	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
385	const int ccm = 128; /* Color correction median - see below */
386	int y, u, v, i, frame_done=0, color_corr;
387	static unsigned char lineBuffer[640*3];
388	unsigned const char *chromaLine, *lumaLine;
389
390	assert(uvd != NULL);
391	assert(frame != NULL);
392	icam = IBMCAM_T(uvd);
393	assert(icam != NULL);
394	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
395	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
396
397	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
398
399	if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) {
400		/* Model 4 frame markers do not carry image size identification */
401		switch (uvd->videosize) {
402		case VIDEOSIZE_128x96:
403		case VIDEOSIZE_160x120:
404		case VIDEOSIZE_176x144:
405			scanLength = VIDEOSIZE_X(uvd->videosize);
406			scanHeight = VIDEOSIZE_Y(uvd->videosize);
407			break;
408		default:
409			err("ibmcam_parse_lines: Wrong mode.");
410			return scan_Out;
411		}
412		order_yc = 1;	/* order_yc: true=Yc false=cY ('c'=either U or V) */
413		order_uv = 1;	/* Always true in this algorithm */
414	} else {
415		switch (frame->header) {
416		case HDRSIG_MODEL1_128x96:
417			scanLength = 128;
418			scanHeight = 96;
419			order_uv = 1;	/* U Y V Y ... */
420			break;
421		case HDRSIG_MODEL1_176x144:
422			scanLength = 176;
423			scanHeight = 144;
424			order_uv = 1;	/* U Y V Y ... */
425			break;
426		case HDRSIG_MODEL1_352x288:
427			scanLength = 352;
428			scanHeight = 288;
429			order_uv = 0;	/* Y V Y V ... */
430			break;
431		default:
432			err("Unknown header signature 00 FF 00 %02lX", frame->header);
433			return scan_NextFrame;
434		}
435		/* order_yc: true=Yc false=cY ('c'=either U or V) */
436		order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);
437	}
438
439	len = scanLength * 3;
440	assert(len <= sizeof(lineBuffer));
441
442	/*
443	 * Lines are organized this way:
444	 *
445	 * I420:
446	 * ~~~~
447	 * <scanLength->
448	 * ___________________________________
449	 * |-----Y-----|---UVUVUV...UVUV-----| \
450	 * |-----------+---------------------|  \
451	 * |<-- 176 -->|<------ 176*2 ------>|  Total 72. lines (interlaced)
452	 * |...	   ... |        ...          |  /
453	 * |<-- 352 -->|<------ 352*2 ------>|  Total 144. lines (interlaced)
454	 * |___________|_____________________| /
455	 *  \           \
456	 *   lumaLine    chromaLine
457	 */
458
459	/* Make sure there's enough data for the entire line */
460	if (RingQueue_GetLength(&uvd->dp) < len)
461		return scan_Out;
462
463	/* Suck one line out of the ring queue */
464	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
465
466	/*
467	 * Make sure that our writing into output buffer
468	 * will not exceed the buffer. Mind that we may write
469	 * not into current output scanline but in several after
470	 * it as well (if we enlarge image vertically.)
471	 */
472	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
473		return scan_NextFrame;
474
475	/*
476	 * Now we are sure that entire line (representing all 'scanLength'
477	 * pixels from the camera) is available in the buffer. We
478	 * start copying the line left-aligned to the V4L buffer.
479	 * If the camera line is shorter then we should pad the V4L
480	 * buffer with something (black) to complete the line.
481	 */
482	assert(frame->data != NULL);
483	f = frame->data + (v4l_linesize * frame->curline);
484
485	/*
486	 * To obtain chrominance data from the 'chromaLine' use this:
487	 *   v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...
488	 *   u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...
489	 *
490	 * Indices must be calculated this way:
491	 * v_index = (i >> 1) << 2;
492	 * u_index = (i >> 1) << 2 + 2;
493	 *
494	 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]
495	 */
496	lumaLine = lineBuffer;
497	chromaLine = lineBuffer + scanLength;
498	for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
499	{
500		unsigned char rv, gv, bv;	/* RGB components */
501
502		/* Check for various visual debugging hints (colorized pixels) */
503		if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {
504			/*
505			 * This is bad and should not happen. This means that
506			 * we somehow overshoot the line and encountered new
507			 * frame! Obviously our camera/V4L frame size is out
508			 * of whack. This cyan dot will help you to figure
509			 * out where exactly the new frame arrived.
510			 */
511			if (icam->has_hdr == 1) {
512				bv = 0; /* Yellow marker */
513				gv = 0xFF;
514				rv = 0xFF;
515			} else {
516				bv = 0xFF; /* Cyan marker */
517				gv = 0xFF;
518				rv = 0;
519			}
520			icam->has_hdr = 0;
521			goto make_pixel;
522		}
523
524		/*
525		 * Check if we are still in range. We may be out of range if our
526		 * V4L canvas is wider or taller than the camera "native" image.
527		 * Then we quickly fill the remainder of the line with zeros to
528		 * make black color and quit the horizontal scanning loop.
529		 */
530		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
531			const int j = i * V4L_BYTES_PER_PIXEL;
532#if USES_IBMCAM_PUTPIXEL
533			/* Refresh 'f' because we don't use it much with PUTPIXEL */
534			f = frame->data + (v4l_linesize * frame->curline) + j;
535#endif
536			memset(f, 0, v4l_linesize - j);
537			break;
538		}
539
540		y = lumaLine[i];
541		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
542			rv = gv = bv = y;
543		else {
544			int off_0, off_2;
545
546			off_0 = (i >> 1) << 2;
547			off_2 = off_0 + 2;
548
549			if (order_yc) {
550				off_0++;
551				off_2++;
552			}
553			if (!order_uv) {
554				off_0 += 2;
555				off_2 -= 2;
556			}
557			u = chromaLine[off_0] + hue_corr;
558			v = chromaLine[off_2] + hue2_corr;
559
560			/* Apply color correction */
561			if (color_corr != 0) {
562				/* Magnify up to 2 times, reduce down to zero saturation */
563				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
564				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
565			}
566			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
567		}
568
569	make_pixel:
570		/*
571		 * The purpose of creating the pixel here, in one,
572		 * dedicated place is that we may need to make the
573		 * pixel wider and taller than it actually is. This
574		 * may be used if camera generates small frames for
575		 * sake of frame rate (or any other reason.)
576		 *
577		 * The output data consists of B, G, R bytes
578		 * (in this order).
579		 */
580#if USES_IBMCAM_PUTPIXEL
581		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
582#else
583		*f++ = bv;
584		*f++ = gv;
585		*f++ = rv;
586#endif
587		/*
588		 * Typically we do not decide within a legitimate frame
589		 * that we want to end the frame. However debugging code
590		 * may detect marker of new frame within the data. Then
591		 * this condition activates. The 'data' pointer is already
592		 * pointing at the new marker, so we'd better leave it as is.
593		 */
594		if (frame_done)
595			break;	/* End scanning of lines */
596	}
597	/*
598	 * Account for number of bytes that we wrote into output V4L frame.
599	 * We do it here, after we are done with the scanline, because we
600	 * may fill more than one output scanline if we do vertical
601	 * enlargement.
602	 */
603	frame->curline += 2;
604	if (pcopylen != NULL)
605		*pcopylen += 2 * v4l_linesize;
606	frame->deinterlace = Deinterlace_FillOddLines;
607
608	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
609		return scan_NextFrame;
610	else
611		return scan_Continue;
612}
613
614/*
615 * ibmcam_model2_320x240_parse_lines()
616 *
617 * This procedure deals with a weird RGB format that is produced by IBM
618 * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
619 * depending on horizontal size of the picture:
620 *
621 * <--- 160 or 176 pairs of RA,RB bytes ----->
622 * *-----------------------------------------* \
623 * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \   This is pair of horizontal lines,
624 * |-----+-----+-----+-----+ ... +-----+-----|   *- or one interlaced line, total
625 * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   120 or 144 such pairs which yield
626 * |=====+=====+=====+=====+ ... +=====+=====| /    240 or 288 lines after deinterlacing.
627 *
628 * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
629 * defines ONE pixel. Therefore this format yields 176x144 "decoded"
630 * resolution at best. I do not know why camera sends such format - the
631 * previous model (1) just used interlaced I420 and everyone was happy.
632 *
633 * I do not know what is the difference between RAi and RBi bytes. Both
634 * seemingly represent R component, but slightly vary in value (so that
635 * the picture looks a bit colored if one or another is used). I use
636 * them both as R component in attempt to at least partially recover the
637 * lost resolution.
638 */
639static enum ParseState ibmcam_model2_320x240_parse_lines(
640	struct uvd *uvd,
641	struct usbvideo_frame *frame,
642	long *pcopylen)
643{
644	unsigned char *f, *la, *lb;
645	unsigned int len;
646	int v4l_linesize; /* V4L line offset */
647	int i, j, frame_done=0, color_corr;
648	int scanLength, scanHeight;
649	static unsigned char lineBuffer[352*2];
650
651	switch (uvd->videosize) {
652	case VIDEOSIZE_320x240:
653	case VIDEOSIZE_352x240:
654	case VIDEOSIZE_352x288:
655		scanLength = VIDEOSIZE_X(uvd->videosize);
656		scanHeight = VIDEOSIZE_Y(uvd->videosize);
657		break;
658	default:
659		err("ibmcam_model2_320x240_parse_lines: Wrong mode.");
660		return scan_Out;
661	}
662
663	color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */
664	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
665
666	len = scanLength * 2; /* See explanation above */
667	assert(len <= sizeof(lineBuffer));
668
669	/* Make sure there's enough data for the entire line */
670	if (RingQueue_GetLength(&uvd->dp) < len)
671		return scan_Out;
672
673	/* Suck one line out of the ring queue */
674	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
675
676	/*
677	 * Make sure that our writing into output buffer
678	 * will not exceed the buffer. Mind that we may write
679	 * not into current output scanline but in several after
680	 * it as well (if we enlarge image vertically.)
681	 */
682	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
683		return scan_NextFrame;
684
685	la = lineBuffer;
686	lb = lineBuffer + scanLength;
687
688	/*
689	 * Now we are sure that entire line (representing all
690	 *         VIDEOSIZE_X(frame->request)
691	 * pixels from the camera) is available in the scratch buffer. We
692	 * start copying the line left-aligned to the V4L buffer (which
693	 * might be larger - not smaller, hopefully). If the camera
694	 * line is shorter then we should pad the V4L buffer with something
695	 * (black in this case) to complete the line.
696	 */
697	f = frame->data + (v4l_linesize * frame->curline);
698
699	/* Fill the 2-line strip */
700	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
701		int y, rv, gv, bv;	/* RGB components */
702
703		j = i & (~1);
704
705		/* Check for various visual debugging hints (colorized pixels) */
706		if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {
707			if (IBMCAM_T(uvd)->has_hdr == 1) {
708				bv = 0; /* Yellow marker */
709				gv = 0xFF;
710				rv = 0xFF;
711			} else {
712				bv = 0xFF; /* Cyan marker */
713				gv = 0xFF;
714				rv = 0;
715			}
716			IBMCAM_T(uvd)->has_hdr = 0;
717			goto make_pixel;
718		}
719
720		/*
721		 * Check if we are still in range. We may be out of range if our
722		 * V4L canvas is wider or taller than the camera "native" image.
723		 * Then we quickly fill the remainder of the line with zeros to
724		 * make black color and quit the horizontal scanning loop.
725		 */
726		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
727			const int j = i * V4L_BYTES_PER_PIXEL;
728#if USES_IBMCAM_PUTPIXEL
729			/* Refresh 'f' because we don't use it much with PUTPIXEL */
730			f = frame->data + (v4l_linesize * frame->curline) + j;
731#endif
732			memset(f, 0, v4l_linesize - j);
733			break;
734		}
735
736		/*
737		 * Here I use RA and RB components, one per physical pixel.
738		 * This causes fine vertical grid on the picture but may improve
739		 * horizontal resolution. If you prefer replicating, use this:
740		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];
741		 * then the pixel will be replicated.
742		 */
743		rv = la[i];
744		gv = lb[j + 1];
745		bv = lb[j + 0];
746
747		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */
748
749		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
750			rv = gv = bv = y;
751		else if (color_corr != 128) {
752
753			/* Calculate difference between color and brightness */
754			rv -= y;
755			gv -= y;
756			bv -= y;
757
758			/* Scale differences */
759			rv = (rv * color_corr) / 128;
760			gv = (gv * color_corr) / 128;
761			bv = (bv * color_corr) / 128;
762
763			/* Reapply brightness */
764			rv += y;
765			gv += y;
766			bv += y;
767
768			/* Watch for overflows */
769			RESTRICT_TO_RANGE(rv, 0, 255);
770			RESTRICT_TO_RANGE(gv, 0, 255);
771			RESTRICT_TO_RANGE(bv, 0, 255);
772		}
773
774	make_pixel:
775		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
776	}
777	/*
778	 * Account for number of bytes that we wrote into output V4L frame.
779	 * We do it here, after we are done with the scanline, because we
780	 * may fill more than one output scanline if we do vertical
781	 * enlargement.
782	 */
783	frame->curline += 2;
784	*pcopylen += v4l_linesize * 2;
785	frame->deinterlace = Deinterlace_FillOddLines;
786
787	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
788		return scan_NextFrame;
789	else
790		return scan_Continue;
791}
792
793static enum ParseState ibmcam_model3_parse_lines(
794	struct uvd *uvd,
795	struct usbvideo_frame *frame,
796	long *pcopylen)
797{
798	unsigned char *data;
799	const unsigned char *color;
800	unsigned int len;
801	int v4l_linesize; /* V4L line offset */
802	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
803	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
804	const int ccm = 128; /* Color correction median - see below */
805	int i, u, v, rw, data_w=0, data_h=0, color_corr;
806	static unsigned char lineBuffer[640*3];
807
808	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
809	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
810
811	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
812
813	/* The header tells us what sort of data is in this frame */
814	switch (frame->header) {
815		/*
816		 * Uncompressed modes (that are easy to decode).
817		 */
818	case 0x0308:
819		data_w = 640;
820		data_h = 480;
821		break;
822	case 0x0208:
823		data_w = 320;
824		data_h = 240;
825		break;
826	case 0x020A:
827		data_w = 160;
828		data_h = 120;
829		break;
830		/*
831		 * Compressed modes (ViCE - that I don't know how to decode).
832		 */
833	case 0x0328:	/* 640x480, best quality compression */
834	case 0x0368:	/* 640x480, best frame rate compression */
835	case 0x0228:	/* 320x240, best quality compression */
836	case 0x0268:	/* 320x240, best frame rate compression */
837	case 0x02CA:	/* 160x120, best quality compression */
838	case 0x02EA:	/* 160x120, best frame rate compression */
839		/* Do nothing with this - not supported */
840		err("Unsupported mode $%04lx", frame->header);
841		return scan_NextFrame;
842	default:
843		/* Catch unknown headers, may help in learning new headers */
844		err("Strange frame->header=$%08lx", frame->header);
845		return scan_NextFrame;
846	}
847
848	/*
849	 * Make sure that our writing into output buffer
850	 * will not exceed the buffer. Note that we may write
851	 * not into current output scanline but in several after
852	 * it as well (if we enlarge image vertically.)
853	 */
854	if ((frame->curline + 1) >= data_h) {
855		if (uvd->debug >= 3)
856			info("Reached line %d. (frame is done)", frame->curline);
857		return scan_NextFrame;
858	}
859
860	/* Make sure there's enough data for the entire line */
861	len = 3 * data_w; /* <y-data> <uv-data> */
862	assert(len <= sizeof(lineBuffer));
863
864	/* Make sure there's enough data for the entire line */
865	if (RingQueue_GetLength(&uvd->dp) < len)
866		return scan_Out;
867
868	/* Suck one line out of the ring queue */
869	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
870
871	data = lineBuffer;
872	color = data + data_w;		/* Point to where color planes begin */
873
874	/* Bottom-to-top scanning */
875	rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
876	RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
877
878	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
879		int y, rv, gv, bv;	/* RGB components */
880
881		if (i < data_w) {
882			y = data[i];	/* Luminosity is the first line */
883
884			/* Apply static color correction */
885			u = color[i*2] + hue_corr;
886			v = color[i*2 + 1] + hue2_corr;
887
888			/* Apply color correction */
889			if (color_corr != 0) {
890				/* Magnify up to 2 times, reduce down to zero saturation */
891				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
892				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
893			}
894		} else
895			y = 0, u = v = 128;
896
897		YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
898		RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
899	}
900	frame->deinterlace = Deinterlace_FillEvenLines;
901
902	/*
903	 * Account for number of bytes that we wrote into output V4L frame.
904	 * We do it here, after we are done with the scanline, because we
905	 * may fill more than one output scanline if we do vertical
906	 * enlargement.
907	 */
908	frame->curline += 2;
909	*pcopylen += 2 * v4l_linesize;
910
911	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
912		if (uvd->debug >= 3) {
913			info("All requested lines (%ld.) done.",
914			     VIDEOSIZE_Y(frame->request));
915		}
916		return scan_NextFrame;
917	} else
918		return scan_Continue;
919}
920
921/*
922 * ibmcam_model4_128x96_parse_lines()
923 *
924 * This decoder is for one strange data format that is produced by Model 4
925 * camera only in 128x96 mode. This is RGB format and here is its description.
926 * First of all, this is non-interlaced stream, meaning that all scan lines
927 * are present in the datastream. There are 96 consecutive blocks of data
928 * that describe all 96 lines of the image. Each block is 5*128 bytes long
929 * and carries R, G, B components. The format of the block is shown in the
930 * code below. First 128*2 bytes are interleaved R and G components. Then
931 * we have a gap (junk data) 64 bytes long. Then follow B and something
932 * else, also interleaved (this makes another 128*2 bytes). After that
933 * probably another 64 bytes of junk follow.
934 *
935 * History:
936 * 10-Feb-2001 Created.
937 */
938static enum ParseState ibmcam_model4_128x96_parse_lines(
939	struct uvd *uvd,
940	struct usbvideo_frame *frame,
941	long *pcopylen)
942{
943	const unsigned char *data_rv, *data_gv, *data_bv;
944	unsigned int len;
945	int i, v4l_linesize; /* V4L line offset */
946	const int data_w=128, data_h=96;
947	static unsigned char lineBuffer[128*5];
948
949	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
950
951	/*
952	 * Make sure that our writing into output buffer
953	 * will not exceed the buffer. Note that we may write
954	 * not into current output scanline but in several after
955	 * it as well (if we enlarge image vertically.)
956	 */
957	if ((frame->curline + 1) >= data_h) {
958		if (uvd->debug >= 3)
959			info("Reached line %d. (frame is done)", frame->curline);
960		return scan_NextFrame;
961	}
962
963	/*
964	 * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________
965	 * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 --->
966	 */
967
968	/* Make sure there's enough data for the entire line */
969	len = 5 * data_w;
970	assert(len <= sizeof(lineBuffer));
971
972	/* Make sure there's enough data for the entire line */
973	if (RingQueue_GetLength(&uvd->dp) < len)
974		return scan_Out;
975
976	/* Suck one line out of the ring queue */
977	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
978
979	data_rv = lineBuffer;
980	data_gv = lineBuffer + 1;
981	data_bv = lineBuffer + data_w*2 + data_w/2;
982	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
983		int rv, gv, bv;	/* RGB components */
984		if (i < data_w) {
985			const int j = i * 2;
986			gv = data_rv[j];
987			rv = data_gv[j];
988			bv = data_bv[j];
989			if (flags & FLAGS_MONOCHROME) {
990				unsigned long y;
991				y = rv + gv + bv;
992				y /= 3;
993				if (y > 0xFF)
994					y = 0xFF;
995				rv = gv = bv = (unsigned char) y;
996			}
997		} else {
998			rv = gv = bv = 0;
999		}
1000		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
1001	}
1002	frame->deinterlace = Deinterlace_None;
1003	frame->curline++;
1004	*pcopylen += v4l_linesize;
1005
1006	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
1007		if (uvd->debug >= 3) {
1008			info("All requested lines (%ld.) done.",
1009			     VIDEOSIZE_Y(frame->request));
1010		}
1011		return scan_NextFrame;
1012	} else
1013		return scan_Continue;
1014}
1015
1016/*
1017 * ibmcam_ProcessIsocData()
1018 *
1019 * Generic routine to parse the ring queue data. It employs either
1020 * ibmcam_find_header() or ibmcam_parse_lines() to do most
1021 * of work.
1022 *
1023 * History:
1024 * 1/21/00  Created.
1025 */
1026static void ibmcam_ProcessIsocData(struct uvd *uvd,
1027				   struct usbvideo_frame *frame)
1028{
1029	enum ParseState newstate;
1030	long copylen = 0;
1031	int mod = IBMCAM_T(uvd)->camera_model;
1032
1033	while (1) {
1034		newstate = scan_Out;
1035		if (RingQueue_GetLength(&uvd->dp) > 0) {
1036			if (frame->scanstate == ScanState_Scanning) {
1037				newstate = ibmcam_find_header(uvd);
1038			} else if (frame->scanstate == ScanState_Lines) {
1039				if ((mod == IBMCAM_MODEL_2) &&
1040				    ((uvd->videosize == VIDEOSIZE_352x288) ||
1041				     (uvd->videosize == VIDEOSIZE_320x240) ||
1042				     (uvd->videosize == VIDEOSIZE_352x240)))
1043				{
1044					newstate = ibmcam_model2_320x240_parse_lines(
1045						uvd, frame, &copylen);
1046				} else if (mod == IBMCAM_MODEL_4) {
1047					/*
1048					 * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB)
1049					 * for 320x240 and above; 160x120 and 176x144 uses Model 1
1050					 * decoder (YUV), and 128x96 mode uses ???
1051					 */
1052					if ((uvd->videosize == VIDEOSIZE_352x288) ||
1053					    (uvd->videosize == VIDEOSIZE_320x240) ||
1054					    (uvd->videosize == VIDEOSIZE_352x240))
1055					{
1056						newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, &copylen);
1057					} else if (uvd->videosize == VIDEOSIZE_128x96) {
1058						newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, &copylen);
1059					} else {
1060						newstate = ibmcam_parse_lines(uvd, frame, &copylen);
1061					}
1062				} else if (mod == IBMCAM_MODEL_3) {
1063					newstate = ibmcam_model3_parse_lines(uvd, frame, &copylen);
1064				} else {
1065					newstate = ibmcam_parse_lines(uvd, frame, &copylen);
1066				}
1067			}
1068		}
1069		if (newstate == scan_Continue)
1070			continue;
1071		else if ((newstate == scan_NextFrame) || (newstate == scan_Out))
1072			break;
1073		else
1074			return; /* scan_EndParse */
1075	}
1076
1077	if (newstate == scan_NextFrame) {
1078		frame->frameState = FrameState_Done;
1079		uvd->curframe = -1;
1080		uvd->stats.frame_num++;
1081		if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) {
1082			/* Need software contrast adjustment for those cameras */
1083			frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST;
1084		}
1085	}
1086
1087	/* Update the frame's uncompressed length. */
1088	frame->seqRead_Length += copylen;
1089
1090}
1091
1092/*
1093 * ibmcam_veio()
1094 *
1095 * History:
1096 * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
1097 */
1098static int ibmcam_veio(
1099	struct uvd *uvd,
1100	unsigned char req,
1101	unsigned short value,
1102	unsigned short index)
1103{
1104	static const char proc[] = "ibmcam_veio";
1105	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
1106	int i;
1107
1108	if (!CAMERA_IS_OPERATIONAL(uvd))
1109		return 0;
1110
1111	if (req == 1) {
1112		i = usb_control_msg(
1113			uvd->dev,
1114			usb_rcvctrlpipe(uvd->dev, 0),
1115			req,
1116			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
1117			value,
1118			index,
1119			cp,
1120			sizeof(cp),
1121			1000);
1122	} else {
1123		i = usb_control_msg(
1124			uvd->dev,
1125			usb_sndctrlpipe(uvd->dev, 0),
1126			req,
1127			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
1128			value,
1129			index,
1130			NULL,
1131			0,
1132			1000);
1133	}
1134	if (i < 0) {
1135		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
1136		    proc, i);
1137		uvd->last_error = i;
1138	}
1139	return i;
1140}
1141
1142/*
1143 * ibmcam_calculate_fps()
1144 *
1145 * This procedure roughly calculates the real frame rate based
1146 * on FPS code (framerate=NNN option). Actual FPS differs
1147 * slightly depending on lighting conditions, so that actual frame
1148 * rate is determined by the camera. Since I don't know how to ask
1149 * the camera what FPS is now I have to use the FPS code instead.
1150 *
1151 * The FPS code is in range [0..6], 0 is slowest, 6 is fastest.
1152 * Corresponding real FPS should be in range [3..30] frames per second.
1153 * The conversion formula is obvious:
1154 *
1155 * real_fps = 3 + (fps_code * 4.5)
1156 *
1157 * History:
1158 * 1/18/00  Created.
1159 */
1160static int ibmcam_calculate_fps(struct uvd *uvd)
1161{
1162	return 3 + framerate*4 + framerate/2;
1163}
1164
1165/*
1166 * ibmcam_send_FF_04_02()
1167 *
1168 * This procedure sends magic 3-command prefix to the camera.
1169 * The purpose of this prefix is not known.
1170 *
1171 * History:
1172 * 1/2/00   Created.
1173 */
1174static void ibmcam_send_FF_04_02(struct uvd *uvd)
1175{
1176	ibmcam_veio(uvd, 0, 0x00FF, 0x0127);
1177	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
1178	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1179}
1180
1181static void ibmcam_send_00_04_06(struct uvd *uvd)
1182{
1183	ibmcam_veio(uvd, 0, 0x0000, 0x0127);
1184	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
1185	ibmcam_veio(uvd, 0, 0x0006, 0x0124);
1186}
1187
1188static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x)
1189{
1190	ibmcam_veio(uvd, 0, x,      0x0127);
1191	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1192}
1193
1194static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x)
1195{
1196	ibmcam_send_x_00(uvd, x);
1197	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1198}
1199
1200static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x)
1201{
1202	ibmcam_veio(uvd, 0, x,      0x0127);
1203	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1204	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1205	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1206}
1207
1208static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x)
1209{
1210	ibmcam_veio(uvd, 0, x,      0x0127);
1211	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1212	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1213	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1214}
1215
1216static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x)
1217{
1218	ibmcam_veio(uvd, 0, x,      0x0127);
1219	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1220	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1221	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1222	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1223}
1224
1225static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x)
1226{
1227	ibmcam_veio(uvd, 0, x,      0x0127);
1228	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1229	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1230	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1231	ibmcam_veio(uvd, 0, 0x0008, 0x0124);
1232	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1233}
1234
1235static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val)
1236{
1237	ibmcam_send_x_01_00_05(uvd, unknown_88);
1238	ibmcam_send_x_00_05(uvd, fkey);
1239	ibmcam_send_x_00_05_02_08_01(uvd, val);
1240	ibmcam_send_x_00_05(uvd, unknown_88);
1241	ibmcam_send_x_00_05_02_01(uvd, fkey);
1242	ibmcam_send_x_00_05(uvd, unknown_89);
1243	ibmcam_send_x_00(uvd, fkey);
1244	ibmcam_send_00_04_06(uvd);
1245	ibmcam_veio(uvd, 1, 0x0000, 0x0126);
1246	ibmcam_send_FF_04_02(uvd);
1247}
1248
1249static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val)
1250{
1251	ibmcam_send_x_01_00_05	(uvd, unknown_88);
1252	ibmcam_send_x_00_05	(uvd, fkey);
1253	ibmcam_send_x_00_05_02	(uvd, val);
1254}
1255
1256static void ibmcam_model2_Packet2(struct uvd *uvd)
1257{
1258	ibmcam_veio(uvd, 0, 0x00ff, 0x012d);
1259	ibmcam_veio(uvd, 0, 0xfea3, 0x0124);
1260}
1261
1262static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
1263{
1264	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1265	ibmcam_veio(uvd, 0, 0x00ff, 0x012e);
1266	ibmcam_veio(uvd, 0, v1,     0x012f);
1267	ibmcam_veio(uvd, 0, 0x00ff, 0x0130);
1268	ibmcam_veio(uvd, 0, 0xc719, 0x0124);
1269	ibmcam_veio(uvd, 0, v2,     0x0127);
1270
1271	ibmcam_model2_Packet2(uvd);
1272}
1273
1274/*
1275 * ibmcam_model3_Packet1()
1276 *
1277 * 00_0078_012d
1278 * 00_0097_012f
1279 * 00_d141_0124
1280 * 00_0096_0127
1281 * 00_fea8_0124
1282*/
1283static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
1284{
1285	ibmcam_veio(uvd, 0, 0x0078, 0x012d);
1286	ibmcam_veio(uvd, 0, v1,     0x012f);
1287	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1288	ibmcam_veio(uvd, 0, v2,     0x0127);
1289	ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
1290}
1291
1292static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i)
1293{
1294	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1295	ibmcam_veio(uvd, 0, 0x0026, 0x012f);
1296	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1297	ibmcam_veio(uvd, 0, i,      0x0127);
1298	ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
1299	ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
1300	ibmcam_veio(uvd, 0, 0x0038, 0x012d);
1301	ibmcam_veio(uvd, 0, 0x0004, 0x012f);
1302	ibmcam_veio(uvd, 0, 0xd145, 0x0124);
1303	ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
1304}
1305
1306/*
1307 * ibmcam_adjust_contrast()
1308 *
1309 * The contrast value changes from 0 (high contrast) to 15 (low contrast).
1310 * This is in reverse to usual order of things (such as TV controls), so
1311 * we reverse it again here.
1312 *
1313 * TODO: we probably don't need to send the setup 5 times...
1314 *
1315 * History:
1316 * 1/2/00   Created.
1317 */
1318static void ibmcam_adjust_contrast(struct uvd *uvd)
1319{
1320	unsigned char a_contrast = uvd->vpic.contrast >> 12;
1321	unsigned char new_contrast;
1322
1323	if (a_contrast >= 16)
1324		a_contrast = 15;
1325	new_contrast = 15 - a_contrast;
1326	if (new_contrast == uvd->vpic_old.contrast)
1327		return;
1328	uvd->vpic_old.contrast = new_contrast;
1329	switch (IBMCAM_T(uvd)->camera_model) {
1330	case IBMCAM_MODEL_1:
1331	{
1332		const int ntries = 5;
1333		int i;
1334		for (i=0; i < ntries; i++) {
1335			ibmcam_Packet_Format1(uvd, contrast_14, new_contrast);
1336			ibmcam_send_FF_04_02(uvd);
1337		}
1338		break;
1339	}
1340	case IBMCAM_MODEL_2:
1341	case IBMCAM_MODEL_4:
1342		/* Models 2, 4 do not have this control; implemented in software. */
1343		break;
1344	case IBMCAM_MODEL_3:
1345	{	/* Preset hardware values */
1346		static const struct {
1347			unsigned short cv1;
1348			unsigned short cv2;
1349			unsigned short cv3;
1350		} cv[7] = {
1351			{ 0x05, 0x05, 0x0f },	/* Minimum */
1352			{ 0x04, 0x04, 0x16 },
1353			{ 0x02, 0x03, 0x16 },
1354			{ 0x02, 0x08, 0x16 },
1355			{ 0x01, 0x0c, 0x16 },
1356			{ 0x01, 0x0e, 0x16 },
1357			{ 0x01, 0x10, 0x16 }	/* Maximum */
1358		};
1359		int i = a_contrast / 2;
1360		RESTRICT_TO_RANGE(i, 0, 6);
1361		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
1362		ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1);
1363		ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2);
1364		ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3);
1365		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1366		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
1367		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1368		break;
1369	}
1370	default:
1371		break;
1372	}
1373}
1374
1375/*
1376 * ibmcam_change_lighting_conditions()
1377 *
1378 * Camera model 1:
1379 * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
1380 *
1381 * Camera model 2:
1382 * We have 16 levels of lighting, 0 for bright light and up to 15 for
1383 * low light. But values above 5 or so are useless because camera is
1384 * not really capable to produce anything worth viewing at such light.
1385 * This setting may be altered only in certain camera state.
1386 *
1387 * Low lighting forces slower FPS. Lighting is set as a module parameter.
1388 *
1389 * History:
1390 * 1/5/00   Created.
1391 * 2/20/00  Added support for Model 2 cameras.
1392 */
1393static void ibmcam_change_lighting_conditions(struct uvd *uvd)
1394{
1395	static const char proc[] = "ibmcam_change_lighting_conditions";
1396
1397	if (debug > 0)
1398		info("%s: Set lighting to %hu.", proc, lighting);
1399
1400	switch (IBMCAM_T(uvd)->camera_model) {
1401	case IBMCAM_MODEL_1:
1402	{
1403		const int ntries = 5;
1404		int i;
1405		for (i=0; i < ntries; i++)
1406			ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting);
1407		break;
1408	}
1409	case IBMCAM_MODEL_2:
1410		break;
1411	case IBMCAM_MODEL_3:
1412	case IBMCAM_MODEL_4:
1413	default:
1414		break;
1415	}
1416}
1417
1418/*
1419 * ibmcam_set_sharpness()
1420 *
1421 * Cameras model 1 have internal smoothing feature. It is controlled by value in
1422 * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
1423 * Recommended value is 4. Cameras model 2 do not have this feature at all.
1424 */
1425static void ibmcam_set_sharpness(struct uvd *uvd)
1426{
1427	static const char proc[] = "ibmcam_set_sharpness";
1428
1429	switch (IBMCAM_T(uvd)->camera_model) {
1430	case IBMCAM_MODEL_1:
1431	{
1432		static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
1433		unsigned short i, sv;
1434
1435		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
1436		if (debug > 0)
1437			info("%s: Set sharpness to %hu.", proc, sharpness);
1438
1439		sv = sa[sharpness - SHARPNESS_MIN];
1440		for (i=0; i < 2; i++) {
1441			ibmcam_send_x_01_00_05	(uvd, unknown_88);
1442			ibmcam_send_x_00_05		(uvd, sharp_13);
1443			ibmcam_send_x_00_05_02	(uvd, sv);
1444		}
1445		break;
1446	}
1447	case IBMCAM_MODEL_2:
1448	case IBMCAM_MODEL_4:
1449		/* Models 2, 4 do not have this control */
1450		break;
1451	case IBMCAM_MODEL_3:
1452	{	/*
1453		 * "Use a table of magic numbers.
1454		 *  This setting doesn't really change much.
1455		 *  But that's how Windows does it."
1456		 */
1457		static const struct {
1458			unsigned short sv1;
1459			unsigned short sv2;
1460			unsigned short sv3;
1461			unsigned short sv4;
1462		} sv[7] = {
1463			{ 0x00, 0x00, 0x05, 0x14 },	/* Smoothest */
1464			{ 0x01, 0x04, 0x05, 0x14 },
1465			{ 0x02, 0x04, 0x05, 0x14 },
1466			{ 0x03, 0x04, 0x05, 0x14 },
1467			{ 0x03, 0x05, 0x05, 0x14 },
1468			{ 0x03, 0x06, 0x05, 0x14 },
1469			{ 0x03, 0x07, 0x05, 0x14 }	/* Sharpest */
1470		};
1471		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
1472		RESTRICT_TO_RANGE(sharpness, 0, 6);
1473		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
1474		ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1);
1475		ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2);
1476		ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3);
1477		ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4);
1478		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1479		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
1480		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1481		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
1482		break;
1483	}
1484	default:
1485		break;
1486	}
1487}
1488
1489/*
1490 * ibmcam_set_brightness()
1491 *
1492 * This procedure changes brightness of the picture.
1493 */
1494static void ibmcam_set_brightness(struct uvd *uvd)
1495{
1496	static const char proc[] = "ibmcam_set_brightness";
1497	static const unsigned short n = 1;
1498
1499	if (debug > 0)
1500		info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
1501
1502	switch (IBMCAM_T(uvd)->camera_model) {
1503	case IBMCAM_MODEL_1:
1504	{
1505		unsigned short i, j, bv[3];
1506		bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10;
1507		if (bv[0] == (uvd->vpic_old.brightness >> 10))
1508			return;
1509		uvd->vpic_old.brightness = bv[0];
1510		for (j=0; j < 3; j++)
1511			for (i=0; i < n; i++)
1512				ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]);
1513		break;
1514	}
1515	case IBMCAM_MODEL_2:
1516	{
1517		unsigned short i, j;
1518		i = uvd->vpic.brightness >> 12;	/* 0 .. 15 */
1519		j = 0x60 + i * ((0xee - 0x60) / 16);	/* 0x60 .. 0xee or so */
1520		if (uvd->vpic_old.brightness == j)
1521			break;
1522		uvd->vpic_old.brightness = j;
1523		ibmcam_model2_Packet1(uvd, mod2_brightness, j);
1524		break;
1525	}
1526	case IBMCAM_MODEL_3:
1527	{
1528		/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
1529		unsigned short i =
1530			0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1)));
1531		RESTRICT_TO_RANGE(i, 0x0C, 0x3F);
1532		if (uvd->vpic_old.brightness == i)
1533			break;
1534		uvd->vpic_old.brightness = i;
1535		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
1536		ibmcam_model3_Packet1(uvd, 0x0036, i);
1537		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1538		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
1539		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1540		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
1541		break;
1542	}
1543	case IBMCAM_MODEL_4:
1544	{
1545		/* Model 4: Brightness range 'i' in [0x04..0xb4] */
1546		unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1)));
1547		RESTRICT_TO_RANGE(i, 0x04, 0xb4);
1548		if (uvd->vpic_old.brightness == i)
1549			break;
1550		uvd->vpic_old.brightness = i;
1551		ibmcam_model4_BrightnessPacket(uvd, i);
1552		break;
1553	}
1554	default:
1555		break;
1556	}
1557}
1558
1559static void ibmcam_set_hue(struct uvd *uvd)
1560{
1561	switch (IBMCAM_T(uvd)->camera_model) {
1562	case IBMCAM_MODEL_2:
1563	{
1564		unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */
1565		if (uvd->vpic_old.hue == hue)
1566			return;
1567		uvd->vpic_old.hue = hue;
1568		ibmcam_model2_Packet1(uvd, mod2_hue, hue);
1569		/* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */
1570		break;
1571	}
1572	case IBMCAM_MODEL_3:
1573	{
1574		break;
1575	}
1576	case IBMCAM_MODEL_4:
1577	{
1578		unsigned short r_gain, g_gain, b_gain, hue;
1579
1580		/*
1581		 * I am not sure r/g/b_gain variables exactly control gain
1582		 * of those channels. Most likely they subtly change some
1583		 * very internal image processing settings in the camera.
1584		 * In any case, here is what they do, and feel free to tweak:
1585		 *
1586		 * r_gain: seriously affects red gain
1587		 * g_gain: seriously affects green gain
1588		 * b_gain: seriously affects blue gain
1589		 * hue: changes average color from violet (0) to red (0xFF)
1590		 *
1591		 * These settings are preset for a decent white balance in
1592		 * 320x240, 352x288 modes. Low-res modes exhibit higher contrast
1593		 * and therefore may need different values here.
1594		 */
1595		hue = 20 + (uvd->vpic.hue >> 9);
1596		switch (uvd->videosize) {
1597		case VIDEOSIZE_128x96:
1598			r_gain = 90;
1599			g_gain = 166;
1600			b_gain = 175;
1601			break;
1602		case VIDEOSIZE_160x120:
1603			r_gain = 70;
1604			g_gain = 166;
1605			b_gain = 185;
1606			break;
1607		case VIDEOSIZE_176x144:
1608			r_gain = 160;
1609			g_gain = 175;
1610			b_gain = 185;
1611			break;
1612		default:
1613			r_gain = 120;
1614			g_gain = 166;
1615			b_gain = 175;
1616			break;
1617		}
1618		RESTRICT_TO_RANGE(hue, 1, 0x7f);
1619
1620		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1621		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
1622		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1623		ibmcam_veio(uvd, 0, g_gain, 0x0127);	/* Green gain */
1624		ibmcam_veio(uvd, 0, r_gain, 0x012e);	/* Red gain */
1625		ibmcam_veio(uvd, 0, b_gain, 0x0130);	/* Blue gain */
1626		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
1627		ibmcam_veio(uvd, 0, hue,    0x012d);	/* Hue */
1628		ibmcam_veio(uvd, 0, 0xf545, 0x0124);
1629		break;
1630	}
1631	default:
1632		break;
1633	}
1634}
1635
1636/*
1637 * ibmcam_adjust_picture()
1638 *
1639 * This procedure gets called from V4L interface to update picture settings.
1640 * Here we change brightness and contrast.
1641 */
1642static void ibmcam_adjust_picture(struct uvd *uvd)
1643{
1644	ibmcam_adjust_contrast(uvd);
1645	ibmcam_set_brightness(uvd);
1646	ibmcam_set_hue(uvd);
1647}
1648
1649static int ibmcam_model1_setup(struct uvd *uvd)
1650{
1651	const int ntries = 5;
1652	int i;
1653
1654	ibmcam_veio(uvd, 1, 0x00, 0x0128);
1655	ibmcam_veio(uvd, 1, 0x00, 0x0100);
1656	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
1657	ibmcam_veio(uvd, 1, 0x00, 0x0100);
1658	ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
1659	ibmcam_veio(uvd, 1, 0x00, 0x0100);
1660	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
1661	ibmcam_veio(uvd, 0, 0x01, 0x0108);
1662
1663	ibmcam_veio(uvd, 0, 0x03, 0x0112);
1664	ibmcam_veio(uvd, 1, 0x00, 0x0115);
1665	ibmcam_veio(uvd, 0, 0x06, 0x0115);
1666	ibmcam_veio(uvd, 1, 0x00, 0x0116);
1667	ibmcam_veio(uvd, 0, 0x44, 0x0116);
1668	ibmcam_veio(uvd, 1, 0x00, 0x0116);
1669	ibmcam_veio(uvd, 0, 0x40, 0x0116);
1670	ibmcam_veio(uvd, 1, 0x00, 0x0115);
1671	ibmcam_veio(uvd, 0, 0x0e, 0x0115);
1672	ibmcam_veio(uvd, 0, 0x19, 0x012c);
1673
1674	ibmcam_Packet_Format1(uvd, 0x00, 0x1e);
1675	ibmcam_Packet_Format1(uvd, 0x39, 0x0d);
1676	ibmcam_Packet_Format1(uvd, 0x39, 0x09);
1677	ibmcam_Packet_Format1(uvd, 0x3b, 0x00);
1678	ibmcam_Packet_Format1(uvd, 0x28, 0x22);
1679	ibmcam_Packet_Format1(uvd, light_27, 0);
1680	ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
1681	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
1682
1683	for (i=0; i < ntries; i++)
1684		ibmcam_Packet_Format1(uvd, 0x2c, 0x00);
1685
1686	for (i=0; i < ntries; i++)
1687		ibmcam_Packet_Format1(uvd, 0x30, 0x14);
1688
1689	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1690	ibmcam_PacketFormat2(uvd, 0x01, 0xe1);
1691	ibmcam_PacketFormat2(uvd, 0x02, 0xcd);
1692	ibmcam_PacketFormat2(uvd, 0x03, 0xcd);
1693	ibmcam_PacketFormat2(uvd, 0x04, 0xfa);
1694	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1695	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1696
1697	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1698	ibmcam_PacketFormat2(uvd, 0x0a, 0x37);
1699	ibmcam_PacketFormat2(uvd, 0x0b, 0xb8);
1700	ibmcam_PacketFormat2(uvd, 0x0c, 0xf3);
1701	ibmcam_PacketFormat2(uvd, 0x0d, 0xe3);
1702	ibmcam_PacketFormat2(uvd, 0x0e, 0x0d);
1703	ibmcam_PacketFormat2(uvd, 0x0f, 0xf2);
1704	ibmcam_PacketFormat2(uvd, 0x10, 0xd5);
1705	ibmcam_PacketFormat2(uvd, 0x11, 0xba);
1706	ibmcam_PacketFormat2(uvd, 0x12, 0x53);
1707	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1708	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1709
1710	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1711	ibmcam_PacketFormat2(uvd, 0x16, 0x00);
1712	ibmcam_PacketFormat2(uvd, 0x17, 0x28);
1713	ibmcam_PacketFormat2(uvd, 0x18, 0x7d);
1714	ibmcam_PacketFormat2(uvd, 0x19, 0xbe);
1715	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1716	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1717
1718	for (i=0; i < ntries; i++)
1719		ibmcam_Packet_Format1(uvd, 0x00, 0x18);
1720	for (i=0; i < ntries; i++)
1721		ibmcam_Packet_Format1(uvd, 0x13, 0x18);
1722	for (i=0; i < ntries; i++)
1723		ibmcam_Packet_Format1(uvd, 0x14, 0x06);
1724
1725	/* This is default brightness */
1726	for (i=0; i < ntries; i++)
1727		ibmcam_Packet_Format1(uvd, 0x31, 0x37);
1728	for (i=0; i < ntries; i++)
1729		ibmcam_Packet_Format1(uvd, 0x32, 0x46);
1730	for (i=0; i < ntries; i++)
1731		ibmcam_Packet_Format1(uvd, 0x33, 0x55);
1732
1733	ibmcam_Packet_Format1(uvd, 0x2e, 0x04);
1734	for (i=0; i < ntries; i++)
1735		ibmcam_Packet_Format1(uvd, 0x2d, 0x04);
1736	for (i=0; i < ntries; i++)
1737		ibmcam_Packet_Format1(uvd, 0x29, 0x80);
1738	ibmcam_Packet_Format1(uvd, 0x2c, 0x01);
1739	ibmcam_Packet_Format1(uvd, 0x30, 0x17);
1740	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
1741	for (i=0; i < ntries; i++)
1742		ibmcam_Packet_Format1(uvd, 0x34, 0x00);
1743
1744	ibmcam_veio(uvd, 0, 0x00, 0x0101);
1745	ibmcam_veio(uvd, 0, 0x00, 0x010a);
1746
1747	switch (uvd->videosize) {
1748	case VIDEOSIZE_128x96:
1749		ibmcam_veio(uvd, 0, 0x80, 0x0103);
1750		ibmcam_veio(uvd, 0, 0x60, 0x0105);
1751		ibmcam_veio(uvd, 0, 0x0c, 0x010b);
1752		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
1753		ibmcam_veio(uvd, 0, 0x0b, 0x011d);
1754		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
1755		ibmcam_veio(uvd, 0, 0x00, 0x0129);
1756		break;
1757	case VIDEOSIZE_176x144:
1758		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
1759		ibmcam_veio(uvd, 0, 0x8f, 0x0105);
1760		ibmcam_veio(uvd, 0, 0x06, 0x010b);
1761		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
1762		ibmcam_veio(uvd, 0, 0x0d, 0x011d);
1763		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
1764		ibmcam_veio(uvd, 0, 0x03, 0x0129);
1765		break;
1766	case VIDEOSIZE_352x288:
1767		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
1768		ibmcam_veio(uvd, 0, 0x90, 0x0105);
1769		ibmcam_veio(uvd, 0, 0x02, 0x010b);
1770		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
1771		ibmcam_veio(uvd, 0, 0x05, 0x011d);
1772		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
1773		ibmcam_veio(uvd, 0, 0x00, 0x0129);
1774		break;
1775	}
1776
1777	ibmcam_veio(uvd, 0, 0xff, 0x012b);
1778
1779	/* This is another brightness - don't know why */
1780	for (i=0; i < ntries; i++)
1781		ibmcam_Packet_Format1(uvd, 0x31, 0xc3);
1782	for (i=0; i < ntries; i++)
1783		ibmcam_Packet_Format1(uvd, 0x32, 0xd2);
1784	for (i=0; i < ntries; i++)
1785		ibmcam_Packet_Format1(uvd, 0x33, 0xe1);
1786
1787	/* Default contrast */
1788	for (i=0; i < ntries; i++)
1789		ibmcam_Packet_Format1(uvd, contrast_14, 0x0a);
1790
1791	/* Default sharpness */
1792	for (i=0; i < 2; i++)
1793		ibmcam_PacketFormat2(uvd, sharp_13, 0x1a);
1794
1795	/* Default lighting conditions */
1796	ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */
1797
1798	/* Assorted init */
1799
1800	switch (uvd->videosize) {
1801	case VIDEOSIZE_128x96:
1802		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
1803		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
1804		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
1805		ibmcam_veio(uvd, 0, 0x36, 0x0102);
1806		ibmcam_veio(uvd, 0, 0x1a, 0x0104);
1807		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
1808		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
1809		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
1810		ibmcam_veio(uvd, 0, 0x02, 0x0106);
1811		ibmcam_veio(uvd, 0, 0x2a, 0x0107);
1812		break;
1813	case VIDEOSIZE_176x144:
1814		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
1815		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
1816		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
1817		ibmcam_veio(uvd, 0, 0x04, 0x0102);
1818		ibmcam_veio(uvd, 0, 0x02, 0x0104);
1819		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
1820		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
1821		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
1822		ibmcam_veio(uvd, 0, 0x01, 0x0106);
1823		ibmcam_veio(uvd, 0, 0xca, 0x0107);
1824		break;
1825	case VIDEOSIZE_352x288:
1826		ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
1827		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
1828		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
1829		ibmcam_veio(uvd, 0, 0x08, 0x0102);
1830		ibmcam_veio(uvd, 0, 0x01, 0x0104);
1831		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
1832		ibmcam_veio(uvd, 0, 0x2f, 0x011c);
1833		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
1834		ibmcam_veio(uvd, 0, 0x03, 0x0106);
1835		ibmcam_veio(uvd, 0, 0xf6, 0x0107);
1836		break;
1837	}
1838	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
1839}
1840
1841static int ibmcam_model2_setup(struct uvd *uvd)
1842{
1843	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
1844	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
1845	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
1846	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
1847	ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
1848	ibmcam_veio(uvd, 0, 0x0008, 0x012b);
1849	ibmcam_veio(uvd, 0, 0x0000, 0x0108);
1850	ibmcam_veio(uvd, 0, 0x0001, 0x0133);
1851	ibmcam_veio(uvd, 0, 0x0001, 0x0102);
1852	switch (uvd->videosize) {
1853	case VIDEOSIZE_176x144:
1854		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
1855		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
1856		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
1857		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);	/* Unique to this mode */
1858		ibmcam_veio(uvd, 0, 0x0038, 0x0119);	/* Unique to this mode */
1859		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
1860		ibmcam_veio(uvd, 0, 0x0090, 0x0107);	/* Unique to every mode*/
1861		break;
1862	case VIDEOSIZE_320x240:
1863		ibmcam_veio(uvd, 0, 0x0028, 0x0103);	/* Unique to this mode */
1864		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
1865		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
1866		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
1867		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
1868		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
1869		ibmcam_veio(uvd, 0, 0x0098, 0x0107);	/* Unique to every mode*/
1870		break;
1871	case VIDEOSIZE_352x240:
1872		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
1873		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
1874		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
1875		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
1876		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
1877		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
1878		ibmcam_veio(uvd, 0, 0x00da, 0x0107);	/* Unique to every mode*/
1879		break;
1880	case VIDEOSIZE_352x288:
1881		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
1882		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
1883		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
1884		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
1885		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
1886		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
1887		ibmcam_veio(uvd, 0, 0x00fe, 0x0107);	/* Unique to every mode*/
1888		break;
1889	}
1890	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
1891}
1892
1893/*
1894 * ibmcam_model1_setup_after_video_if()
1895 *
1896 * This code adds finishing touches to the video data interface.
1897 * Here we configure the frame rate and turn on the LED.
1898 */
1899static void ibmcam_model1_setup_after_video_if(struct uvd *uvd)
1900{
1901	unsigned short internal_frame_rate;
1902
1903	RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
1904	internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
1905	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
1906	ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111);
1907	ibmcam_veio(uvd, 0, 0x01, 0x0114);
1908	ibmcam_veio(uvd, 0, 0xc0, 0x010c);
1909}
1910
1911static void ibmcam_model2_setup_after_video_if(struct uvd *uvd)
1912{
1913	unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb;
1914
1915	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
1916
1917	switch (uvd->videosize) {
1918	case VIDEOSIZE_176x144:
1919		ibmcam_veio(uvd, 0, 0x0050, 0x0111);
1920		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
1921		break;
1922	case VIDEOSIZE_320x240:
1923	case VIDEOSIZE_352x240:
1924	case VIDEOSIZE_352x288:
1925		ibmcam_veio(uvd, 0, 0x0040, 0x0111);
1926		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
1927		break;
1928	}
1929	ibmcam_veio(uvd, 0, 0x009b, 0x010f);
1930	ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
1931
1932	/*
1933	 * Hardware settings, may affect CMOS sensor; not user controls!
1934	 * -------------------------------------------------------------
1935	 * 0x0004: no effect
1936	 * 0x0006: hardware effect
1937	 * 0x0008: no effect
1938	 * 0x000a: stops video stream, probably important h/w setting
1939	 * 0x000c: changes color in hardware manner (not user setting)
1940	 * 0x0012: changes number of colors (does not affect speed)
1941	 * 0x002a: no effect
1942	 * 0x002c: hardware setting (related to scan lines)
1943	 * 0x002e: stops video stream, probably important h/w setting
1944	 */
1945	ibmcam_model2_Packet1(uvd, 0x000a, 0x005c);
1946	ibmcam_model2_Packet1(uvd, 0x0004, 0x0000);
1947	ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb);
1948	ibmcam_model2_Packet1(uvd, 0x0008, 0x0000);
1949	ibmcam_model2_Packet1(uvd, 0x000c, 0x0009);
1950	ibmcam_model2_Packet1(uvd, 0x0012, 0x000a);
1951	ibmcam_model2_Packet1(uvd, 0x002a, 0x0000);
1952	ibmcam_model2_Packet1(uvd, 0x002c, 0x0000);
1953	ibmcam_model2_Packet1(uvd, 0x002e, 0x0008);
1954
1955	/*
1956	 * Function 0x0030 pops up all over the place. Apparently
1957	 * it is a hardware control register, with every bit assigned to
1958	 * do something.
1959	 */
1960	ibmcam_model2_Packet1(uvd, 0x0030, 0x0000);
1961
1962	/*
1963	 * Magic control of CMOS sensor. Only lower values like
1964	 * 0-3 work, and picture shifts left or right. Don't change.
1965	 */
1966	switch (uvd->videosize) {
1967	case VIDEOSIZE_176x144:
1968		ibmcam_model2_Packet1(uvd, 0x0014, 0x0002);
1969		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
1970		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
1971		break;
1972	case VIDEOSIZE_320x240:
1973		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009);
1974		ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */
1975		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */
1976		break;
1977	case VIDEOSIZE_352x240:
1978		/* This mode doesn't work as Windows programs it; changed to work */
1979		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */
1980		ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */
1981		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
1982		break;
1983	case VIDEOSIZE_352x288:
1984		ibmcam_model2_Packet1(uvd, 0x0014, 0x0003);
1985		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
1986		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
1987		break;
1988	}
1989
1990	ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a);
1991
1992	/*
1993	 * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest).
1994	 * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the
1995	 * slowest setting. However for all practical reasons high settings make no
1996	 * sense because USB is not fast enough to support high FPS. Be aware that
1997	 * the picture datastream will be severely disrupted if you ask for
1998	 * frame rate faster than allowed for the video size - see below:
1999	 *
2000	 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
2001	 * -----------------------------------------------------------------
2002	 * 176x144: [6..31]
2003	 * 320x240: [8..31]
2004	 * 352x240: [10..31]
2005	 * 352x288: [16..31] I have to raise lower threshold for stability...
2006	 *
2007	 * As usual, slower FPS provides better sensitivity.
2008	 */
2009	{
2010		short hw_fps=31, i_framerate;
2011
2012		RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
2013		i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN;
2014		switch (uvd->videosize) {
2015		case VIDEOSIZE_176x144:
2016			hw_fps = 6 + i_framerate*4;
2017			break;
2018		case VIDEOSIZE_320x240:
2019			hw_fps = 8 + i_framerate*3;
2020			break;
2021		case VIDEOSIZE_352x240:
2022			hw_fps = 10 + i_framerate*2;
2023			break;
2024		case VIDEOSIZE_352x288:
2025			hw_fps = 28 + i_framerate/2;
2026			break;
2027		}
2028		if (uvd->debug > 0)
2029			info("Framerate (hardware): %hd.", hw_fps);
2030		RESTRICT_TO_RANGE(hw_fps, 0, 31);
2031		ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
2032	}
2033
2034	/*
2035	 * This setting does not visibly affect pictures; left it here
2036	 * because it was present in Windows USB data stream. This function
2037	 * does not allow arbitrary values and apparently is a bit mask, to
2038	 * be activated only at appropriate time. Don't change it randomly!
2039	 */
2040	switch (uvd->videosize) {
2041	case VIDEOSIZE_176x144:
2042		ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2);
2043		break;
2044	case VIDEOSIZE_320x240:
2045		ibmcam_model2_Packet1(uvd, 0x0026, 0x0044);
2046		break;
2047	case VIDEOSIZE_352x240:
2048		ibmcam_model2_Packet1(uvd, 0x0026, 0x0046);
2049		break;
2050	case VIDEOSIZE_352x288:
2051		ibmcam_model2_Packet1(uvd, 0x0026, 0x0048);
2052		break;
2053	}
2054
2055	ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
2056
2057	if (init_model2_rg2 >= 0) {
2058		RESTRICT_TO_RANGE(init_model2_rg2, 0, 255);
2059		setup_model2_rg2 = init_model2_rg2;
2060	} else
2061		setup_model2_rg2 = 0x002f;
2062
2063	if (init_model2_sat >= 0) {
2064		RESTRICT_TO_RANGE(init_model2_sat, 0, 255);
2065		setup_model2_sat = init_model2_sat;
2066	} else
2067		setup_model2_sat = 0x0034;
2068
2069	if (init_model2_yb >= 0) {
2070		RESTRICT_TO_RANGE(init_model2_yb, 0, 255);
2071		setup_model2_yb = init_model2_yb;
2072	} else
2073		setup_model2_yb = 0x00a0;
2074
2075	ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2);
2076	ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat);
2077	ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb);
2078	ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */;
2079
2080	/* Hardware control command */
2081	ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
2082
2083	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go camera, go! */
2084	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
2085}
2086
2087static void ibmcam_model4_setup_after_video_if(struct uvd *uvd)
2088{
2089	switch (uvd->videosize) {
2090	case VIDEOSIZE_128x96:
2091		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2092		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2093		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2094		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2095		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2096		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2097		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2098		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2099		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2100		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2101		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2102		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2103		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2104		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2105		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2106		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2107		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2108		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2109		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2110		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2111		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2112		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2113		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2114		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2115		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2116		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2117		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2118		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2119		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2120		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2121		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2122		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2123		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2124		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2125		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2126		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2127		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2128		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2129		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2130		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2131		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2132		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2133		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2134		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2135		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2136		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2137		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
2138		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2139		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
2140		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2141		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2142		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2143		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2144		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2145		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2146		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2147		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2148		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2149		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2150		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
2151		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2152		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2153		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2154		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2155		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2156		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2157		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2158		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2159		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2160		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2161		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2162		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2163		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2164		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2165		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2166		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2167		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2168		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
2169		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2170		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2171		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2172		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2173		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2174		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2175		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2176		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2177		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2178		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2179		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2180		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2181		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2182		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2183		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
2184		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2185		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
2186		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2187		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
2188		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
2189		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2190		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2191		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2192		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2193		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2194		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2195		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2196		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2197		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2198		break;
2199	case VIDEOSIZE_160x120:
2200		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2201		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2202		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2203		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2204		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2205		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2206		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2207		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2208		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2209		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2210		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2211		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2212		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2213		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2214		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2215		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2216		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2217		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2218		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2219		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2220		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2221		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2222		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2223		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2224		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2225		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2226		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2227		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2228		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2229		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2230		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2231		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2232		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2233		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2234		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2235		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2236		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2237		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2238		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2239		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2240		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2241		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2242		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2243		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2244		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2245		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
2246		ibmcam_veio(uvd, 0, 0x00d8, 0x0107);
2247		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
2248		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2249		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
2250		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2251		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2252		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2253		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2254		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2255		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2256		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2257		ibmcam_veio(uvd, 0, 0x000b, 0x0127);
2258		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2259		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2260		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2261		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2262		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2263		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2264		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2265		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2266		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2267		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2268		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2269		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2270		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2271		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2272		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2273		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2274		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2275		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
2276		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2277		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2278		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2279		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2280		ibmcam_veio(uvd, 0, 0x0025, 0x0127);
2281		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2282		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2283		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2284		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2285		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2286		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2287		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2288		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2289		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2290		ibmcam_veio(uvd, 0, 0x0048, 0x0127);
2291		ibmcam_veio(uvd, 0, 0x0035, 0x012e);
2292		ibmcam_veio(uvd, 0, 0x00d0, 0x0130);
2293		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2294		ibmcam_veio(uvd, 0, 0x0048, 0x012d);
2295		ibmcam_veio(uvd, 0, 0x0090, 0x012f);
2296		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2297		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
2298		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2299		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2300		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2301		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2302		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2303		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2304		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2305		break;
2306	case VIDEOSIZE_176x144:
2307		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2308		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2309		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2310		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2311		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2312		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2313		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2314		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2315		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2316		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2317		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2318		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2319		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2320		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2321		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2322		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2323		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2324		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2325		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2326		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2327		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2328		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2329		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2330		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2331		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2332		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2333		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2334		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2335		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2336		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2337		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2338		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2339		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2340		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2341		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2342		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2343		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2344		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2345		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2346		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2347		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2348		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2349		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2350		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2351		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2352		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
2353		ibmcam_veio(uvd, 0, 0x00d6, 0x0107);
2354		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2355		ibmcam_veio(uvd, 0, 0x0018, 0x0107);
2356		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2357		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2358		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
2359		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2360		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
2361		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2362		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
2363		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2364		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2365		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2366		ibmcam_veio(uvd, 0, 0x0007, 0x0127);
2367		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2368		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2369		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2370		ibmcam_veio(uvd, 0, 0x0001, 0x012f);
2371		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2372		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2373		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2374		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2375		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
2376		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2377		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2378		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2379		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
2380		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2381		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2382		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2383		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2384		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
2385		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2386		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2387		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2388		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2389		ibmcam_veio(uvd, 0, 0x0028, 0x0127);
2390		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2391		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2392		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2393		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2394		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2395		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2396		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2397		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2398		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2399		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
2400		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2401		ibmcam_veio(uvd, 0, 0x002a, 0x0130);
2402		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2403		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
2404		ibmcam_veio(uvd, 0, 0x006d, 0x012f);
2405		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2406		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
2407		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2408		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2409		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2410		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2411		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2412		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2413		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2414		break;
2415	case VIDEOSIZE_320x240:
2416		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2417		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2418		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2419		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2420		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2421		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2422		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2423		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2424		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2425		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2426		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2427		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2428		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2429		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2430		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2431		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2432		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2433		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2434		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2435		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2436		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2437		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2438		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2439		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2440		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2441		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2442		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2443		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2444		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2445		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2446		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2447		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2448		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2449		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2450		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2451		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2452		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2453		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2454		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2455		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2456		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2457		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2458		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2459		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2460		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2461		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2462		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
2463		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2464		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
2465		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2466		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2467		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2468		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2469		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2470		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2471		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2472		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2473		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2474		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2475		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
2476		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2477		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2478		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2479		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2480		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2481		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2482		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2483		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2484		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2485		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2486		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2487		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2488		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2489		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2490		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2491		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2492		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2493		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
2494		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2495		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2496		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2497		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2498		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2499		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2500		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2501		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2502		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2503		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2504		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2505		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2506		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2507		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2508		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
2509		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2510		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
2511		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2512		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
2513		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
2514		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2515		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2516		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2517		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2518		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2519		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2520		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2521		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2522		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2523		break;
2524	case VIDEOSIZE_352x288:
2525		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2526		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2527		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2528		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2529		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2530		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2531		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2532		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2533		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2534		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2535		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2536		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2537		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2538		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2539		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2540		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2541		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2542		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2543		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2544		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2545		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2546		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2547		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2548		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2549		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2550		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2551		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2552		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2553		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2554		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2555		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2556		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2557		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2558		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2559		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2560		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2561		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2562		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2563		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2564		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2565		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2566		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2567		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2568		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2569		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2570		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2571		ibmcam_veio(uvd, 0, 0x00f2, 0x0107);
2572		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2573		ibmcam_veio(uvd, 0, 0x008c, 0x0107);
2574		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2575		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2576		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2577		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2578		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
2579		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2580		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
2581		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2582		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2583		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2584		ibmcam_veio(uvd, 0, 0x0006, 0x0127);
2585		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2586		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2587		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2588		ibmcam_veio(uvd, 0, 0x0002, 0x012f);
2589		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2590		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2591		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2592		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2593		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
2594		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2595		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2596		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2597		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
2598		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2599		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2600		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2601		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2602		ibmcam_veio(uvd, 0, 0x00cf, 0x012e);
2603		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2604		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2605		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2606		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2607		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2608		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2609		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2610		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2611		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2612		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2613		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2614		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2615		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2616		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2617		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
2618		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2619		ibmcam_veio(uvd, 0, 0x0025, 0x0130);
2620		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2621		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
2622		ibmcam_veio(uvd, 0, 0x0048, 0x012f);
2623		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2624		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2625		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2626		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2627		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2628		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2629		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2630		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2631		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2632		break;
2633	}
2634	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
2635}
2636
2637static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
2638{
2639	int i;
2640	/*
2641	 * 01.01.08 - Added for RCA video in support -LO
2642	 * This struct is used to init the Model3 cam to use the RCA video in port
2643	 * instead of the CCD sensor.
2644	 */
2645	static const struct struct_initData initData[] = {
2646		{0, 0x0000, 0x010c},
2647		{0, 0x0006, 0x012c},
2648		{0, 0x0078, 0x012d},
2649		{0, 0x0046, 0x012f},
2650		{0, 0xd141, 0x0124},
2651		{0, 0x0000, 0x0127},
2652		{0, 0xfea8, 0x0124},
2653		{1, 0x0000, 0x0116},
2654		{0, 0x0064, 0x0116},
2655		{1, 0x0000, 0x0115},
2656		{0, 0x0003, 0x0115},
2657		{0, 0x0008, 0x0123},
2658		{0, 0x0000, 0x0117},
2659		{0, 0x0000, 0x0112},
2660		{0, 0x0080, 0x0100},
2661		{0, 0x0000, 0x0100},
2662		{1, 0x0000, 0x0116},
2663		{0, 0x0060, 0x0116},
2664		{0, 0x0002, 0x0112},
2665		{0, 0x0000, 0x0123},
2666		{0, 0x0001, 0x0117},
2667		{0, 0x0040, 0x0108},
2668		{0, 0x0019, 0x012c},
2669		{0, 0x0040, 0x0116},
2670		{0, 0x000a, 0x0115},
2671		{0, 0x000b, 0x0115},
2672		{0, 0x0078, 0x012d},
2673		{0, 0x0046, 0x012f},
2674		{0, 0xd141, 0x0124},
2675		{0, 0x0000, 0x0127},
2676		{0, 0xfea8, 0x0124},
2677		{0, 0x0064, 0x0116},
2678		{0, 0x0000, 0x0115},
2679		{0, 0x0001, 0x0115},
2680		{0, 0xffff, 0x0124},
2681		{0, 0xfff9, 0x0124},
2682		{0, 0x0086, 0x0127},
2683		{0, 0xfff8, 0x0124},
2684		{0, 0xfffd, 0x0124},
2685		{0, 0x00aa, 0x0127},
2686		{0, 0xfff8, 0x0124},
2687		{0, 0xfffd, 0x0124},
2688		{0, 0x0000, 0x0127},
2689		{0, 0xfff8, 0x0124},
2690		{0, 0xfffd, 0x0124},
2691		{0, 0xfffa, 0x0124},
2692		{0, 0xffff, 0x0124},
2693		{0, 0xfff9, 0x0124},
2694		{0, 0x0086, 0x0127},
2695		{0, 0xfff8, 0x0124},
2696		{0, 0xfffd, 0x0124},
2697		{0, 0x00f2, 0x0127},
2698		{0, 0xfff8, 0x0124},
2699		{0, 0xfffd, 0x0124},
2700		{0, 0x000f, 0x0127},
2701		{0, 0xfff8, 0x0124},
2702		{0, 0xfffd, 0x0124},
2703		{0, 0xfffa, 0x0124},
2704		{0, 0xffff, 0x0124},
2705		{0, 0xfff9, 0x0124},
2706		{0, 0x0086, 0x0127},
2707		{0, 0xfff8, 0x0124},
2708		{0, 0xfffd, 0x0124},
2709		{0, 0x00f8, 0x0127},
2710		{0, 0xfff8, 0x0124},
2711		{0, 0xfffd, 0x0124},
2712		{0, 0x00fc, 0x0127},
2713		{0, 0xfff8, 0x0124},
2714		{0, 0xfffd, 0x0124},
2715		{0, 0xfffa, 0x0124},
2716		{0, 0xffff, 0x0124},
2717		{0, 0xfff9, 0x0124},
2718		{0, 0x0086, 0x0127},
2719		{0, 0xfff8, 0x0124},
2720		{0, 0xfffd, 0x0124},
2721		{0, 0x00f9, 0x0127},
2722		{0, 0xfff8, 0x0124},
2723		{0, 0xfffd, 0x0124},
2724		{0, 0x003c, 0x0127},
2725		{0, 0xfff8, 0x0124},
2726		{0, 0xfffd, 0x0124},
2727		{0, 0xfffa, 0x0124},
2728		{0, 0xffff, 0x0124},
2729		{0, 0xfff9, 0x0124},
2730		{0, 0x0086, 0x0127},
2731		{0, 0xfff8, 0x0124},
2732		{0, 0xfffd, 0x0124},
2733		{0, 0x0027, 0x0127},
2734		{0, 0xfff8, 0x0124},
2735		{0, 0xfffd, 0x0124},
2736		{0, 0x0019, 0x0127},
2737		{0, 0xfff8, 0x0124},
2738		{0, 0xfffd, 0x0124},
2739		{0, 0xfffa, 0x0124},
2740		{0, 0xfff9, 0x0124},
2741		{0, 0x0086, 0x0127},
2742		{0, 0xfff8, 0x0124},
2743		{0, 0xfffd, 0x0124},
2744		{0, 0x0037, 0x0127},
2745		{0, 0xfff8, 0x0124},
2746		{0, 0xfffd, 0x0124},
2747		{0, 0x0000, 0x0127},
2748		{0, 0xfff8, 0x0124},
2749		{0, 0xfffd, 0x0124},
2750		{0, 0x0021, 0x0127},
2751		{0, 0xfff8, 0x0124},
2752		{0, 0xfffd, 0x0124},
2753		{0, 0xfffa, 0x0124},
2754		{0, 0xfff9, 0x0124},
2755		{0, 0x0086, 0x0127},
2756		{0, 0xfff8, 0x0124},
2757		{0, 0xfffd, 0x0124},
2758		{0, 0x0038, 0x0127},
2759		{0, 0xfff8, 0x0124},
2760		{0, 0xfffd, 0x0124},
2761		{0, 0x0006, 0x0127},
2762		{0, 0xfff8, 0x0124},
2763		{0, 0xfffd, 0x0124},
2764		{0, 0x0045, 0x0127},
2765		{0, 0xfff8, 0x0124},
2766		{0, 0xfffd, 0x0124},
2767		{0, 0xfffa, 0x0124},
2768		{0, 0xfff9, 0x0124},
2769		{0, 0x0086, 0x0127},
2770		{0, 0xfff8, 0x0124},
2771		{0, 0xfffd, 0x0124},
2772		{0, 0x0037, 0x0127},
2773		{0, 0xfff8, 0x0124},
2774		{0, 0xfffd, 0x0124},
2775		{0, 0x0001, 0x0127},
2776		{0, 0xfff8, 0x0124},
2777		{0, 0xfffd, 0x0124},
2778		{0, 0x002a, 0x0127},
2779		{0, 0xfff8, 0x0124},
2780		{0, 0xfffd, 0x0124},
2781		{0, 0xfffa, 0x0124},
2782		{0, 0xfff9, 0x0124},
2783		{0, 0x0086, 0x0127},
2784		{0, 0xfff8, 0x0124},
2785		{0, 0xfffd, 0x0124},
2786		{0, 0x0038, 0x0127},
2787		{0, 0xfff8, 0x0124},
2788		{0, 0xfffd, 0x0124},
2789		{0, 0x0000, 0x0127},
2790		{0, 0xfff8, 0x0124},
2791		{0, 0xfffd, 0x0124},
2792		{0, 0x000e, 0x0127},
2793		{0, 0xfff8, 0x0124},
2794		{0, 0xfffd, 0x0124},
2795		{0, 0xfffa, 0x0124},
2796		{0, 0xfff9, 0x0124},
2797		{0, 0x0086, 0x0127},
2798		{0, 0xfff8, 0x0124},
2799		{0, 0xfffd, 0x0124},
2800		{0, 0x0037, 0x0127},
2801		{0, 0xfff8, 0x0124},
2802		{0, 0xfffd, 0x0124},
2803		{0, 0x0001, 0x0127},
2804		{0, 0xfff8, 0x0124},
2805		{0, 0xfffd, 0x0124},
2806		{0, 0x002b, 0x0127},
2807		{0, 0xfff8, 0x0124},
2808		{0, 0xfffd, 0x0124},
2809		{0, 0xfffa, 0x0124},
2810		{0, 0xfff9, 0x0124},
2811		{0, 0x0086, 0x0127},
2812		{0, 0xfff8, 0x0124},
2813		{0, 0xfffd, 0x0124},
2814		{0, 0x0038, 0x0127},
2815		{0, 0xfff8, 0x0124},
2816		{0, 0xfffd, 0x0124},
2817		{0, 0x0001, 0x0127},
2818		{0, 0xfff8, 0x0124},
2819		{0, 0xfffd, 0x0124},
2820		{0, 0x00f4, 0x0127},
2821		{0, 0xfff8, 0x0124},
2822		{0, 0xfffd, 0x0124},
2823		{0, 0xfffa, 0x0124},
2824		{0, 0xfff9, 0x0124},
2825		{0, 0x0086, 0x0127},
2826		{0, 0xfff8, 0x0124},
2827		{0, 0xfffd, 0x0124},
2828		{0, 0x0037, 0x0127},
2829		{0, 0xfff8, 0x0124},
2830		{0, 0xfffd, 0x0124},
2831		{0, 0x0001, 0x0127},
2832		{0, 0xfff8, 0x0124},
2833		{0, 0xfffd, 0x0124},
2834		{0, 0x002c, 0x0127},
2835		{0, 0xfff8, 0x0124},
2836		{0, 0xfffd, 0x0124},
2837		{0, 0xfffa, 0x0124},
2838		{0, 0xfff9, 0x0124},
2839		{0, 0x0086, 0x0127},
2840		{0, 0xfff8, 0x0124},
2841		{0, 0xfffd, 0x0124},
2842		{0, 0x0038, 0x0127},
2843		{0, 0xfff8, 0x0124},
2844		{0, 0xfffd, 0x0124},
2845		{0, 0x0001, 0x0127},
2846		{0, 0xfff8, 0x0124},
2847		{0, 0xfffd, 0x0124},
2848		{0, 0x0004, 0x0127},
2849		{0, 0xfff8, 0x0124},
2850		{0, 0xfffd, 0x0124},
2851		{0, 0xfffa, 0x0124},
2852		{0, 0xfff9, 0x0124},
2853		{0, 0x0086, 0x0127},
2854		{0, 0xfff8, 0x0124},
2855		{0, 0xfffd, 0x0124},
2856		{0, 0x0037, 0x0127},
2857		{0, 0xfff8, 0x0124},
2858		{0, 0xfffd, 0x0124},
2859		{0, 0x0001, 0x0127},
2860		{0, 0xfff8, 0x0124},
2861		{0, 0xfffd, 0x0124},
2862		{0, 0x002d, 0x0127},
2863		{0, 0xfff8, 0x0124},
2864		{0, 0xfffd, 0x0124},
2865		{0, 0xfffa, 0x0124},
2866		{0, 0xfff9, 0x0124},
2867		{0, 0x0086, 0x0127},
2868		{0, 0xfff8, 0x0124},
2869		{0, 0xfffd, 0x0124},
2870		{0, 0x0038, 0x0127},
2871		{0, 0xfff8, 0x0124},
2872		{0, 0xfffd, 0x0124},
2873		{0, 0x0000, 0x0127},
2874		{0, 0xfff8, 0x0124},
2875		{0, 0xfffd, 0x0124},
2876		{0, 0x0014, 0x0127},
2877		{0, 0xfff8, 0x0124},
2878		{0, 0xfffd, 0x0124},
2879		{0, 0xfffa, 0x0124},
2880		{0, 0xfff9, 0x0124},
2881		{0, 0x0086, 0x0127},
2882		{0, 0xfff8, 0x0124},
2883		{0, 0xfffd, 0x0124},
2884		{0, 0x0037, 0x0127},
2885		{0, 0xfff8, 0x0124},
2886		{0, 0xfffd, 0x0124},
2887		{0, 0x0001, 0x0127},
2888		{0, 0xfff8, 0x0124},
2889		{0, 0xfffd, 0x0124},
2890		{0, 0x002e, 0x0127},
2891		{0, 0xfff8, 0x0124},
2892		{0, 0xfffd, 0x0124},
2893		{0, 0xfffa, 0x0124},
2894		{0, 0xfff9, 0x0124},
2895		{0, 0x0086, 0x0127},
2896		{0, 0xfff8, 0x0124},
2897		{0, 0xfffd, 0x0124},
2898		{0, 0x0038, 0x0127},
2899		{0, 0xfff8, 0x0124},
2900		{0, 0xfffd, 0x0124},
2901		{0, 0x0003, 0x0127},
2902		{0, 0xfff8, 0x0124},
2903		{0, 0xfffd, 0x0124},
2904		{0, 0x0000, 0x0127},
2905		{0, 0xfff8, 0x0124},
2906		{0, 0xfffd, 0x0124},
2907		{0, 0xfffa, 0x0124},
2908		{0, 0xfff9, 0x0124},
2909		{0, 0x0086, 0x0127},
2910		{0, 0xfff8, 0x0124},
2911		{0, 0xfffd, 0x0124},
2912		{0, 0x0037, 0x0127},
2913		{0, 0xfff8, 0x0124},
2914		{0, 0xfffd, 0x0124},
2915		{0, 0x0001, 0x0127},
2916		{0, 0xfff8, 0x0124},
2917		{0, 0xfffd, 0x0124},
2918		{0, 0x002f, 0x0127},
2919		{0, 0xfff8, 0x0124},
2920		{0, 0xfffd, 0x0124},
2921		{0, 0xfffa, 0x0124},
2922		{0, 0xfff9, 0x0124},
2923		{0, 0x0086, 0x0127},
2924		{0, 0xfff8, 0x0124},
2925		{0, 0xfffd, 0x0124},
2926		{0, 0x0038, 0x0127},
2927		{0, 0xfff8, 0x0124},
2928		{0, 0xfffd, 0x0124},
2929		{0, 0x0003, 0x0127},
2930		{0, 0xfff8, 0x0124},
2931		{0, 0xfffd, 0x0124},
2932		{0, 0x0014, 0x0127},
2933		{0, 0xfff8, 0x0124},
2934		{0, 0xfffd, 0x0124},
2935		{0, 0xfffa, 0x0124},
2936		{0, 0xfff9, 0x0124},
2937		{0, 0x0086, 0x0127},
2938		{0, 0xfff8, 0x0124},
2939		{0, 0xfffd, 0x0124},
2940		{0, 0x0037, 0x0127},
2941		{0, 0xfff8, 0x0124},
2942		{0, 0xfffd, 0x0124},
2943		{0, 0x0001, 0x0127},
2944		{0, 0xfff8, 0x0124},
2945		{0, 0xfffd, 0x0124},
2946		{0, 0x0040, 0x0127},
2947		{0, 0xfff8, 0x0124},
2948		{0, 0xfffd, 0x0124},
2949		{0, 0xfffa, 0x0124},
2950		{0, 0xfff9, 0x0124},
2951		{0, 0x0086, 0x0127},
2952		{0, 0xfff8, 0x0124},
2953		{0, 0xfffd, 0x0124},
2954		{0, 0x0038, 0x0127},
2955		{0, 0xfff8, 0x0124},
2956		{0, 0xfffd, 0x0124},
2957		{0, 0x0000, 0x0127},
2958		{0, 0xfff8, 0x0124},
2959		{0, 0xfffd, 0x0124},
2960		{0, 0x0040, 0x0127},
2961		{0, 0xfff8, 0x0124},
2962		{0, 0xfffd, 0x0124},
2963		{0, 0xfffa, 0x0124},
2964		{0, 0xfff9, 0x0124},
2965		{0, 0x0086, 0x0127},
2966		{0, 0xfff8, 0x0124},
2967		{0, 0xfffd, 0x0124},
2968		{0, 0x0037, 0x0127},
2969		{0, 0xfff8, 0x0124},
2970		{0, 0xfffd, 0x0124},
2971		{0, 0x0001, 0x0127},
2972		{0, 0xfff8, 0x0124},
2973		{0, 0xfffd, 0x0124},
2974		{0, 0x0053, 0x0127},
2975		{0, 0xfff8, 0x0124},
2976		{0, 0xfffd, 0x0124},
2977		{0, 0xfffa, 0x0124},
2978		{0, 0xfff9, 0x0124},
2979		{0, 0x0086, 0x0127},
2980		{0, 0xfff8, 0x0124},
2981		{0, 0xfffd, 0x0124},
2982		{0, 0x0038, 0x0127},
2983		{0, 0xfff8, 0x0124},
2984		{0, 0xfffd, 0x0124},
2985		{0, 0x0000, 0x0127},
2986		{0, 0xfff8, 0x0124},
2987		{0, 0xfffd, 0x0124},
2988		{0, 0x0038, 0x0127},
2989		{0, 0xfff8, 0x0124},
2990		{0, 0xfffd, 0x0124},
2991		{0, 0xfffa, 0x0124},
2992		{0, 0x0000, 0x0101},
2993		{0, 0x00a0, 0x0103},
2994		{0, 0x0078, 0x0105},
2995		{0, 0x0000, 0x010a},
2996		{0, 0x0024, 0x010b},
2997		{0, 0x0028, 0x0119},
2998		{0, 0x0088, 0x011b},
2999		{0, 0x0002, 0x011d},
3000		{0, 0x0003, 0x011e},
3001		{0, 0x0000, 0x0129},
3002		{0, 0x00fc, 0x012b},
3003		{0, 0x0008, 0x0102},
3004		{0, 0x0000, 0x0104},
3005		{0, 0x0008, 0x011a},
3006		{0, 0x0028, 0x011c},
3007		{0, 0x0021, 0x012a},
3008		{0, 0x0000, 0x0118},
3009		{0, 0x0000, 0x0132},
3010		{0, 0x0000, 0x0109},
3011		{0, 0xfff9, 0x0124},
3012		{0, 0x0086, 0x0127},
3013		{0, 0xfff8, 0x0124},
3014		{0, 0xfffd, 0x0124},
3015		{0, 0x0037, 0x0127},
3016		{0, 0xfff8, 0x0124},
3017		{0, 0xfffd, 0x0124},
3018		{0, 0x0001, 0x0127},
3019		{0, 0xfff8, 0x0124},
3020		{0, 0xfffd, 0x0124},
3021		{0, 0x0031, 0x0127},
3022		{0, 0xfff8, 0x0124},
3023		{0, 0xfffd, 0x0124},
3024		{0, 0xfffa, 0x0124},
3025		{0, 0xfff9, 0x0124},
3026		{0, 0x0086, 0x0127},
3027		{0, 0xfff8, 0x0124},
3028		{0, 0xfffd, 0x0124},
3029		{0, 0x0038, 0x0127},
3030		{0, 0xfff8, 0x0124},
3031		{0, 0xfffd, 0x0124},
3032		{0, 0x0000, 0x0127},
3033		{0, 0xfff8, 0x0124},
3034		{0, 0xfffd, 0x0124},
3035		{0, 0x0000, 0x0127},
3036		{0, 0xfff8, 0x0124},
3037		{0, 0xfffd, 0x0124},
3038		{0, 0xfffa, 0x0124},
3039		{0, 0xfff9, 0x0124},
3040		{0, 0x0086, 0x0127},
3041		{0, 0xfff8, 0x0124},
3042		{0, 0xfffd, 0x0124},
3043		{0, 0x0037, 0x0127},
3044		{0, 0xfff8, 0x0124},
3045		{0, 0xfffd, 0x0124},
3046		{0, 0x0001, 0x0127},
3047		{0, 0xfff8, 0x0124},
3048		{0, 0xfffd, 0x0124},
3049		{0, 0x0040, 0x0127},
3050		{0, 0xfff8, 0x0124},
3051		{0, 0xfffd, 0x0124},
3052		{0, 0xfffa, 0x0124},
3053		{0, 0xfff9, 0x0124},
3054		{0, 0x0086, 0x0127},
3055		{0, 0xfff8, 0x0124},
3056		{0, 0xfffd, 0x0124},
3057		{0, 0x0038, 0x0127},
3058		{0, 0xfff8, 0x0124},
3059		{0, 0xfffd, 0x0124},
3060		{0, 0x0000, 0x0127},
3061		{0, 0xfff8, 0x0124},
3062		{0, 0xfffd, 0x0124},
3063		{0, 0x0040, 0x0127},
3064		{0, 0xfff8, 0x0124},
3065		{0, 0xfffd, 0x0124},
3066		{0, 0xfffa, 0x0124},
3067		{0, 0xfff9, 0x0124},
3068		{0, 0x0086, 0x0127},
3069		{0, 0xfff8, 0x0124},
3070		{0, 0xfffd, 0x0124},
3071		{0, 0x0037, 0x0127},
3072		{0, 0xfff8, 0x0124},
3073		{0, 0xfffd, 0x0124},
3074		{0, 0x0000, 0x0127},
3075		{0, 0xfff8, 0x0124},
3076		{0, 0xfffd, 0x0124},
3077		{0, 0x00dc, 0x0127},
3078		{0, 0xfff8, 0x0124},
3079		{0, 0xfffd, 0x0124},
3080		{0, 0xfffa, 0x0124},
3081		{0, 0xfff9, 0x0124},
3082		{0, 0x0086, 0x0127},
3083		{0, 0xfff8, 0x0124},
3084		{0, 0xfffd, 0x0124},
3085		{0, 0x0038, 0x0127},
3086		{0, 0xfff8, 0x0124},
3087		{0, 0xfffd, 0x0124},
3088		{0, 0x0000, 0x0127},
3089		{0, 0xfff8, 0x0124},
3090		{0, 0xfffd, 0x0124},
3091		{0, 0x0000, 0x0127},
3092		{0, 0xfff8, 0x0124},
3093		{0, 0xfffd, 0x0124},
3094		{0, 0xfffa, 0x0124},
3095		{0, 0xfff9, 0x0124},
3096		{0, 0x0086, 0x0127},
3097		{0, 0xfff8, 0x0124},
3098		{0, 0xfffd, 0x0124},
3099		{0, 0x0037, 0x0127},
3100		{0, 0xfff8, 0x0124},
3101		{0, 0xfffd, 0x0124},
3102		{0, 0x0001, 0x0127},
3103		{0, 0xfff8, 0x0124},
3104		{0, 0xfffd, 0x0124},
3105		{0, 0x0032, 0x0127},
3106		{0, 0xfff8, 0x0124},
3107		{0, 0xfffd, 0x0124},
3108		{0, 0xfffa, 0x0124},
3109		{0, 0xfff9, 0x0124},
3110		{0, 0x0086, 0x0127},
3111		{0, 0xfff8, 0x0124},
3112		{0, 0xfffd, 0x0124},
3113		{0, 0x0038, 0x0127},
3114		{0, 0xfff8, 0x0124},
3115		{0, 0xfffd, 0x0124},
3116		{0, 0x0001, 0x0127},
3117		{0, 0xfff8, 0x0124},
3118		{0, 0xfffd, 0x0124},
3119		{0, 0x0020, 0x0127},
3120		{0, 0xfff8, 0x0124},
3121		{0, 0xfffd, 0x0124},
3122		{0, 0xfffa, 0x0124},
3123		{0, 0xfff9, 0x0124},
3124		{0, 0x0086, 0x0127},
3125		{0, 0xfff8, 0x0124},
3126		{0, 0xfffd, 0x0124},
3127		{0, 0x0037, 0x0127},
3128		{0, 0xfff8, 0x0124},
3129		{0, 0xfffd, 0x0124},
3130		{0, 0x0001, 0x0127},
3131		{0, 0xfff8, 0x0124},
3132		{0, 0xfffd, 0x0124},
3133		{0, 0x0040, 0x0127},
3134		{0, 0xfff8, 0x0124},
3135		{0, 0xfffd, 0x0124},
3136		{0, 0xfffa, 0x0124},
3137		{0, 0xfff9, 0x0124},
3138		{0, 0x0086, 0x0127},
3139		{0, 0xfff8, 0x0124},
3140		{0, 0xfffd, 0x0124},
3141		{0, 0x0038, 0x0127},
3142		{0, 0xfff8, 0x0124},
3143		{0, 0xfffd, 0x0124},
3144		{0, 0x0000, 0x0127},
3145		{0, 0xfff8, 0x0124},
3146		{0, 0xfffd, 0x0124},
3147		{0, 0x0040, 0x0127},
3148		{0, 0xfff8, 0x0124},
3149		{0, 0xfffd, 0x0124},
3150		{0, 0xfffa, 0x0124},
3151		{0, 0xfff9, 0x0124},
3152		{0, 0x0086, 0x0127},
3153		{0, 0xfff8, 0x0124},
3154		{0, 0xfffd, 0x0124},
3155		{0, 0x0037, 0x0127},
3156		{0, 0xfff8, 0x0124},
3157		{0, 0xfffd, 0x0124},
3158		{0, 0x0000, 0x0127},
3159		{0, 0xfff8, 0x0124},
3160		{0, 0xfffd, 0x0124},
3161		{0, 0x0030, 0x0127},
3162		{0, 0xfff8, 0x0124},
3163		{0, 0xfffd, 0x0124},
3164		{0, 0xfffa, 0x0124},
3165		{0, 0xfff9, 0x0124},
3166		{0, 0x0086, 0x0127},
3167		{0, 0xfff8, 0x0124},
3168		{0, 0xfffd, 0x0124},
3169		{0, 0x0038, 0x0127},
3170		{0, 0xfff8, 0x0124},
3171		{0, 0xfffd, 0x0124},
3172		{0, 0x0008, 0x0127},
3173		{0, 0xfff8, 0x0124},
3174		{0, 0xfffd, 0x0124},
3175		{0, 0x0000, 0x0127},
3176		{0, 0xfff8, 0x0124},
3177		{0, 0xfffd, 0x0124},
3178		{0, 0xfffa, 0x0124},
3179		{0, 0x0003, 0x0106},
3180		{0, 0x0062, 0x0107},
3181		{0, 0x0003, 0x0111},
3182	};
3183#define NUM_INIT_DATA
3184
3185	unsigned short compression = 0;	/* 0=none, 7=best frame rate  */
3186	int f_rate; /* 0=Fastest 7=slowest */
3187
3188	if (IBMCAM_T(uvd)->initialized)
3189		return;
3190
3191	/* Internal frame rate is controlled by f_rate value */
3192	f_rate = 7 - framerate;
3193	RESTRICT_TO_RANGE(f_rate, 0, 7);
3194
3195	ibmcam_veio(uvd, 0, 0x0000, 0x0100);
3196	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
3197	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
3198	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
3199	ibmcam_veio(uvd, 0, 0x0000, 0x0123);
3200	ibmcam_veio(uvd, 0, 0x0001, 0x0117);
3201	ibmcam_veio(uvd, 0, 0x0040, 0x0108);
3202	ibmcam_veio(uvd, 0, 0x0019, 0x012c);
3203	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
3204	ibmcam_veio(uvd, 0, 0x0002, 0x0115);
3205	ibmcam_veio(uvd, 0, 0x0003, 0x0115);
3206	ibmcam_veio(uvd, 1, 0x0000, 0x0115);
3207	ibmcam_veio(uvd, 0, 0x000b, 0x0115);
3208	ibmcam_model3_Packet1(uvd, 0x000a, 0x0040);
3209	ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6);
3210	ibmcam_model3_Packet1(uvd, 0x000c, 0x0002);
3211	ibmcam_model3_Packet1(uvd, 0x000d, 0x0020);
3212	ibmcam_model3_Packet1(uvd, 0x000e, 0x0033);
3213	ibmcam_model3_Packet1(uvd, 0x000f, 0x0007);
3214	ibmcam_model3_Packet1(uvd, 0x0010, 0x0000);
3215	ibmcam_model3_Packet1(uvd, 0x0011, 0x0070);
3216	ibmcam_model3_Packet1(uvd, 0x0012, 0x0030);
3217	ibmcam_model3_Packet1(uvd, 0x0013, 0x0000);
3218	ibmcam_model3_Packet1(uvd, 0x0014, 0x0001);
3219	ibmcam_model3_Packet1(uvd, 0x0015, 0x0001);
3220	ibmcam_model3_Packet1(uvd, 0x0016, 0x0001);
3221	ibmcam_model3_Packet1(uvd, 0x0017, 0x0001);
3222	ibmcam_model3_Packet1(uvd, 0x0018, 0x0000);
3223	ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3);
3224	ibmcam_model3_Packet1(uvd, 0x0020, 0x0000);
3225	ibmcam_model3_Packet1(uvd, 0x0028, 0x0010);
3226	ibmcam_model3_Packet1(uvd, 0x0029, 0x0054);
3227	ibmcam_model3_Packet1(uvd, 0x002a, 0x0013);
3228	ibmcam_model3_Packet1(uvd, 0x002b, 0x0007);
3229	ibmcam_model3_Packet1(uvd, 0x002d, 0x0028);
3230	ibmcam_model3_Packet1(uvd, 0x002e, 0x0000);
3231	ibmcam_model3_Packet1(uvd, 0x0031, 0x0000);
3232	ibmcam_model3_Packet1(uvd, 0x0032, 0x0000);
3233	ibmcam_model3_Packet1(uvd, 0x0033, 0x0000);
3234	ibmcam_model3_Packet1(uvd, 0x0034, 0x0000);
3235	ibmcam_model3_Packet1(uvd, 0x0035, 0x0038);
3236	ibmcam_model3_Packet1(uvd, 0x003a, 0x0001);
3237	ibmcam_model3_Packet1(uvd, 0x003c, 0x001e);
3238	ibmcam_model3_Packet1(uvd, 0x003f, 0x000a);
3239	ibmcam_model3_Packet1(uvd, 0x0041, 0x0000);
3240	ibmcam_model3_Packet1(uvd, 0x0046, 0x003f);
3241	ibmcam_model3_Packet1(uvd, 0x0047, 0x0000);
3242	ibmcam_model3_Packet1(uvd, 0x0050, 0x0005);
3243	ibmcam_model3_Packet1(uvd, 0x0052, 0x001a);
3244	ibmcam_model3_Packet1(uvd, 0x0053, 0x0003);
3245	ibmcam_model3_Packet1(uvd, 0x005a, 0x006b);
3246	ibmcam_model3_Packet1(uvd, 0x005d, 0x001e);
3247	ibmcam_model3_Packet1(uvd, 0x005e, 0x0030);
3248	ibmcam_model3_Packet1(uvd, 0x005f, 0x0041);
3249	ibmcam_model3_Packet1(uvd, 0x0064, 0x0008);
3250	ibmcam_model3_Packet1(uvd, 0x0065, 0x0015);
3251	ibmcam_model3_Packet1(uvd, 0x0068, 0x000f);
3252	ibmcam_model3_Packet1(uvd, 0x0079, 0x0000);
3253	ibmcam_model3_Packet1(uvd, 0x007a, 0x0000);
3254	ibmcam_model3_Packet1(uvd, 0x007c, 0x003f);
3255	ibmcam_model3_Packet1(uvd, 0x0082, 0x000f);
3256	ibmcam_model3_Packet1(uvd, 0x0085, 0x0000);
3257	ibmcam_model3_Packet1(uvd, 0x0099, 0x0000);
3258	ibmcam_model3_Packet1(uvd, 0x009b, 0x0023);
3259	ibmcam_model3_Packet1(uvd, 0x009c, 0x0022);
3260	ibmcam_model3_Packet1(uvd, 0x009d, 0x0096);
3261	ibmcam_model3_Packet1(uvd, 0x009e, 0x0096);
3262	ibmcam_model3_Packet1(uvd, 0x009f, 0x000a);
3263
3264	switch (uvd->videosize) {
3265	case VIDEOSIZE_160x120:
3266		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
3267		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
3268		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
3269		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3270		ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */
3271		ibmcam_veio(uvd, 0, 0x00a9, 0x0119);
3272		ibmcam_veio(uvd, 0, 0x0016, 0x011b);
3273		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */
3274		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
3275		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3276		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3277		ibmcam_veio(uvd, 0, 0x0018, 0x0102);
3278		ibmcam_veio(uvd, 0, 0x0004, 0x0104);
3279		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
3280		ibmcam_veio(uvd, 0, 0x0028, 0x011c);
3281		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3282		ibmcam_veio(uvd, 0, 0x0000, 0x0118);
3283		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
3284		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3285		ibmcam_veio(uvd, 0, compression, 0x0109);
3286		break;
3287	case VIDEOSIZE_320x240:
3288		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
3289		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
3290		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
3291		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3292		ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */
3293		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */
3294		ibmcam_veio(uvd, 0, 0x0000, 0x011e);
3295		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3296		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3297		/* 4 commands from 160x120 skipped */
3298		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3299		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3300		ibmcam_veio(uvd, 0, compression, 0x0109);
3301		ibmcam_veio(uvd, 0, 0x00d9, 0x0119);
3302		ibmcam_veio(uvd, 0, 0x0006, 0x011b);
3303		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
3304		ibmcam_veio(uvd, 0, 0x0010, 0x0104);
3305		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
3306		ibmcam_veio(uvd, 0, 0x003f, 0x011c);
3307		ibmcam_veio(uvd, 0, 0x001c, 0x0118);
3308		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
3309		break;
3310	case VIDEOSIZE_640x480:
3311		ibmcam_veio(uvd, 0, 0x00f0, 0x0105);
3312		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3313		ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */
3314		ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
3315		ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
3316		ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */
3317		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
3318		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3319		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3320		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
3321		ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */
3322		ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
3323		ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
3324		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3325		ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
3326		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3327		ibmcam_veio(uvd, 0, compression, 0x0109);
3328		ibmcam_veio(uvd, 0, 0x0040, 0x0101);
3329		ibmcam_veio(uvd, 0, 0x0040, 0x0103);
3330		ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
3331		break;
3332	}
3333	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);	/* Hue */
3334	ibmcam_model3_Packet1(uvd, 0x0036, 0x0011);	/* Brightness */
3335	ibmcam_model3_Packet1(uvd, 0x0060, 0x0002);	/* Sharpness */
3336	ibmcam_model3_Packet1(uvd, 0x0061, 0x0004);	/* Sharpness */
3337	ibmcam_model3_Packet1(uvd, 0x0062, 0x0005);	/* Sharpness */
3338	ibmcam_model3_Packet1(uvd, 0x0063, 0x0014);	/* Sharpness */
3339	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
3340	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
3341	ibmcam_model3_Packet1(uvd, 0x0067, 0x0001);	/* Contrast */
3342	ibmcam_model3_Packet1(uvd, 0x005b, 0x000c);	/* Contrast */
3343	ibmcam_model3_Packet1(uvd, 0x005c, 0x0016);	/* Contrast */
3344	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
3345	ibmcam_model3_Packet1(uvd, 0x002c, 0x0003);	/* Was 1, broke 640x480 */
3346	ibmcam_model3_Packet1(uvd, 0x002f, 0x002a);
3347	ibmcam_model3_Packet1(uvd, 0x0030, 0x0029);
3348	ibmcam_model3_Packet1(uvd, 0x0037, 0x0002);
3349	ibmcam_model3_Packet1(uvd, 0x0038, 0x0059);
3350	ibmcam_model3_Packet1(uvd, 0x003d, 0x002e);
3351	ibmcam_model3_Packet1(uvd, 0x003e, 0x0028);
3352	ibmcam_model3_Packet1(uvd, 0x0078, 0x0005);
3353	ibmcam_model3_Packet1(uvd, 0x007b, 0x0011);
3354	ibmcam_model3_Packet1(uvd, 0x007d, 0x004b);
3355	ibmcam_model3_Packet1(uvd, 0x007f, 0x0022);
3356	ibmcam_model3_Packet1(uvd, 0x0080, 0x000c);
3357	ibmcam_model3_Packet1(uvd, 0x0081, 0x000b);
3358	ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd);
3359	ibmcam_model3_Packet1(uvd, 0x0086, 0x000b);
3360	ibmcam_model3_Packet1(uvd, 0x0087, 0x000b);
3361	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);
3362	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
3363	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
3364	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
3365
3366	switch (uvd->videosize) {
3367	case VIDEOSIZE_160x120:
3368		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
3369		ibmcam_veio(uvd, 0, 0x0008, 0x0107);
3370		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
3371		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
3372		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
3373		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
3374		ibmcam_model3_Packet1(uvd, 0x0040, 0x000a);
3375		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
3376		break;
3377	case VIDEOSIZE_320x240:
3378		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
3379		ibmcam_veio(uvd, 0, 0x0062, 0x0107);
3380		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
3381		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
3382		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
3383		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
3384		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
3385		ibmcam_model3_Packet1(uvd, 0x0051, 0x000b);
3386		break;
3387	case VIDEOSIZE_640x480:
3388		ibmcam_veio(uvd, 0, 0x0002, 0x0106);	/* Adjustments */
3389		ibmcam_veio(uvd, 0, 0x00b4, 0x0107);	/* Adjustments */
3390		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
3391		ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */
3392		ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */
3393		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
3394		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
3395		break;
3396	}
3397
3398	/* 01.01.08 - Added for RCA video in support -LO */
3399	if(init_model3_input) {
3400		if (debug > 0)
3401			info("Setting input to RCA.");
3402		for (i=0; i < ARRAY_SIZE(initData); i++) {
3403			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
3404		}
3405	}
3406
3407	ibmcam_veio(uvd, 0, 0x0001, 0x0114);
3408	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
3409	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
3410}
3411
3412/*
3413 * ibmcam_video_stop()
3414 *
3415 * This code tells camera to stop streaming. The interface remains
3416 * configured and bandwidth - claimed.
3417 */
3418static void ibmcam_video_stop(struct uvd *uvd)
3419{
3420	switch (IBMCAM_T(uvd)->camera_model) {
3421	case IBMCAM_MODEL_1:
3422		ibmcam_veio(uvd, 0, 0x00, 0x010c);
3423		ibmcam_veio(uvd, 0, 0x00, 0x010c);
3424		ibmcam_veio(uvd, 0, 0x01, 0x0114);
3425		ibmcam_veio(uvd, 0, 0xc0, 0x010c);
3426		ibmcam_veio(uvd, 0, 0x00, 0x010c);
3427		ibmcam_send_FF_04_02(uvd);
3428		ibmcam_veio(uvd, 1, 0x00, 0x0100);
3429		ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
3430		break;
3431	case IBMCAM_MODEL_2:
3432case IBMCAM_MODEL_4:
3433		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop the camera */
3434
3435		ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
3436
3437		ibmcam_veio(uvd, 0, 0x0080, 0x0100);	/* LED Off */
3438		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
3439		ibmcam_veio(uvd, 0, 0x00a0, 0x0111);
3440
3441		ibmcam_model2_Packet1(uvd, 0x0030, 0x0002);
3442
3443		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
3444		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
3445		break;
3446	case IBMCAM_MODEL_3:
3447		ibmcam_veio(uvd, 0, 0x0000, 0x010c);
3448
3449		/* Here we are supposed to select video interface alt. setting 0 */
3450		ibmcam_veio(uvd, 0, 0x0006, 0x012c);
3451
3452		ibmcam_model3_Packet1(uvd, 0x0046, 0x0000);
3453
3454		ibmcam_veio(uvd, 1, 0x0000, 0x0116);
3455		ibmcam_veio(uvd, 0, 0x0064, 0x0116);
3456		ibmcam_veio(uvd, 1, 0x0000, 0x0115);
3457		ibmcam_veio(uvd, 0, 0x0003, 0x0115);
3458		ibmcam_veio(uvd, 0, 0x0008, 0x0123);
3459		ibmcam_veio(uvd, 0, 0x0000, 0x0117);
3460		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
3461		ibmcam_veio(uvd, 0, 0x0080, 0x0100);
3462		IBMCAM_T(uvd)->initialized = 0;
3463		break;
3464	} /* switch */
3465}
3466
3467/*
3468 * ibmcam_reinit_iso()
3469 *
3470 * This procedure sends couple of commands to the camera and then
3471 * resets the video pipe. This sequence was observed to reinit the
3472 * camera or, at least, to initiate ISO data stream.
3473 *
3474 * History:
3475 * 1/2/00   Created.
3476 */
3477static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop)
3478{
3479	switch (IBMCAM_T(uvd)->camera_model) {
3480	case IBMCAM_MODEL_1:
3481		if (do_stop)
3482			ibmcam_video_stop(uvd);
3483		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
3484		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
3485		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
3486		ibmcam_model1_setup_after_video_if(uvd);
3487		break;
3488	case IBMCAM_MODEL_2:
3489		ibmcam_model2_setup_after_video_if(uvd);
3490		break;
3491	case IBMCAM_MODEL_3:
3492		ibmcam_video_stop(uvd);
3493		ibmcam_model3_setup_after_video_if(uvd);
3494		break;
3495	case IBMCAM_MODEL_4:
3496		ibmcam_model4_setup_after_video_if(uvd);
3497		break;
3498	}
3499}
3500
3501static void ibmcam_video_start(struct uvd *uvd)
3502{
3503	ibmcam_change_lighting_conditions(uvd);
3504	ibmcam_set_sharpness(uvd);
3505	ibmcam_reinit_iso(uvd, 0);
3506}
3507
3508/*
3509 * Return negative code on failure, 0 on success.
3510 */
3511static int ibmcam_setup_on_open(struct uvd *uvd)
3512{
3513	int setup_ok = 0; /* Success by default */
3514	/* Send init sequence only once, it's large! */
3515	if (!IBMCAM_T(uvd)->initialized) {
3516		switch (IBMCAM_T(uvd)->camera_model) {
3517		case IBMCAM_MODEL_1:
3518			setup_ok = ibmcam_model1_setup(uvd);
3519			break;
3520		case IBMCAM_MODEL_2:
3521			setup_ok = ibmcam_model2_setup(uvd);
3522			break;
3523		case IBMCAM_MODEL_3:
3524		case IBMCAM_MODEL_4:
3525			/* We do all setup when Isoc stream is requested */
3526			break;
3527		}
3528		IBMCAM_T(uvd)->initialized = (setup_ok != 0);
3529	}
3530	return setup_ok;
3531}
3532
3533static void ibmcam_configure_video(struct uvd *uvd)
3534{
3535	if (uvd == NULL)
3536		return;
3537
3538	RESTRICT_TO_RANGE(init_brightness, 0, 255);
3539	RESTRICT_TO_RANGE(init_contrast, 0, 255);
3540	RESTRICT_TO_RANGE(init_color, 0, 255);
3541	RESTRICT_TO_RANGE(init_hue, 0, 255);
3542	RESTRICT_TO_RANGE(hue_correction, 0, 255);
3543
3544	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
3545	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
3546
3547	uvd->vpic.colour = init_color << 8;
3548	uvd->vpic.hue = init_hue << 8;
3549	uvd->vpic.brightness = init_brightness << 8;
3550	uvd->vpic.contrast = init_contrast << 8;
3551	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
3552	uvd->vpic.depth = 24;
3553	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
3554
3555	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
3556	strcpy(uvd->vcap.name, "IBM USB Camera");
3557	uvd->vcap.type = VID_TYPE_CAPTURE;
3558	uvd->vcap.channels = 1;
3559	uvd->vcap.audios = 0;
3560	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
3561	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
3562	uvd->vcap.minwidth = min_canvasWidth;
3563	uvd->vcap.minheight = min_canvasHeight;
3564
3565	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
3566	uvd->vchan.flags = 0;
3567	uvd->vchan.tuners = 0;
3568	uvd->vchan.channel = 0;
3569	uvd->vchan.type = VIDEO_TYPE_CAMERA;
3570	strcpy(uvd->vchan.name, "Camera");
3571}
3572
3573/*
3574 * ibmcam_probe()
3575 *
3576 * This procedure queries device descriptor and accepts the interface
3577 * if it looks like IBM C-it camera.
3578 *
3579 * History:
3580 * 22-Jan-2000 Moved camera init code to ibmcam_open()
3581 * 27=Jan-2000 Changed to use static structures, added locking.
3582 * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
3583 * 03-Jul-2000 Fixed endianness bug.
3584 * 12-Nov-2000 Reworked to comply with new probe() signature.
3585 * 23-Jan-2001 Added compatibility with 2.2.x kernels.
3586 */
3587static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
3588{
3589	struct usb_device *dev = interface_to_usbdev(intf);
3590	struct uvd *uvd = NULL;
3591	int ix, i, nas, model=0, canvasX=0, canvasY=0;
3592	int actInterface=-1, inactInterface=-1, maxPS=0;
3593	__u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
3594	unsigned char video_ep = 0;
3595
3596	if (debug >= 1)
3597		info("ibmcam_probe(%p,%u.)", intf, ifnum);
3598
3599	/* We don't handle multi-config cameras */
3600	if (dev->descriptor.bNumConfigurations != 1)
3601		return -ENODEV;
3602
3603	/* Check the version/revision */
3604	switch (le16_to_cpu(dev->descriptor.bcdDevice)) {
3605	case 0x0002:
3606		if (ifnum != 2)
3607			return -ENODEV;
3608		model = IBMCAM_MODEL_1;
3609		break;
3610	case 0x030A:
3611		if (ifnum != 0)
3612			return -ENODEV;
3613		if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) ||
3614		    (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID))
3615			model = IBMCAM_MODEL_4;
3616		else
3617			model = IBMCAM_MODEL_2;
3618		break;
3619	case 0x0301:
3620		if (ifnum != 0)
3621			return -ENODEV;
3622		model = IBMCAM_MODEL_3;
3623		break;
3624	default:
3625		err("IBM camera with revision 0x%04x is not supported.",
3626			le16_to_cpu(dev->descriptor.bcdDevice));
3627		return -ENODEV;
3628	}
3629
3630	/* Print detailed info on what we found so far */
3631	do {
3632		char *brand = NULL;
3633		switch (le16_to_cpu(dev->descriptor.idProduct)) {
3634		case NETCAM_PRODUCT_ID:
3635			brand = "IBM NetCamera";
3636			break;
3637		case VEO_800C_PRODUCT_ID:
3638			brand = "Veo Stingray [800C]";
3639			break;
3640		case VEO_800D_PRODUCT_ID:
3641			brand = "Veo Stingray [800D]";
3642			break;
3643		case IBMCAM_PRODUCT_ID:
3644		default:
3645			brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
3646			break;
3647		}
3648		info("%s USB camera found (model %d, rev. 0x%04x)",
3649		     brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
3650	} while (0);
3651
3652	/* Validate found interface: must have one ISO endpoint */
3653	nas = intf->num_altsetting;
3654	if (debug > 0)
3655		info("Number of alternate settings=%d.", nas);
3656	if (nas < 2) {
3657		err("Too few alternate settings for this camera!");
3658		return -ENODEV;
3659	}
3660	/* Validate all alternate settings */
3661	for (ix=0; ix < nas; ix++) {
3662		const struct usb_host_interface *interface;
3663		const struct usb_endpoint_descriptor *endpoint;
3664
3665		interface = &intf->altsetting[ix];
3666		i = interface->desc.bAlternateSetting;
3667		if (interface->desc.bNumEndpoints != 1) {
3668			err("Interface %d. has %u. endpoints!",
3669			    ifnum, (unsigned)(interface->desc.bNumEndpoints));
3670			return -ENODEV;
3671		}
3672		endpoint = &interface->endpoint[0].desc;
3673		if (video_ep == 0)
3674			video_ep = endpoint->bEndpointAddress;
3675		else if (video_ep != endpoint->bEndpointAddress) {
3676			err("Alternate settings have different endpoint addresses!");
3677			return -ENODEV;
3678		}
3679		if ((endpoint->bmAttributes & 0x03) != 0x01) {
3680			err("Interface %d. has non-ISO endpoint!", ifnum);
3681			return -ENODEV;
3682		}
3683		if ((endpoint->bEndpointAddress & 0x80) == 0) {
3684			err("Interface %d. has ISO OUT endpoint!", ifnum);
3685			return -ENODEV;
3686		}
3687		if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
3688			if (inactInterface < 0)
3689				inactInterface = i;
3690			else {
3691				err("More than one inactive alt. setting!");
3692				return -ENODEV;
3693			}
3694		} else {
3695			if (actInterface < 0) {
3696				actInterface = i;
3697				maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
3698				if (debug > 0)
3699					info("Active setting=%d. maxPS=%d.", i, maxPS);
3700			} else
3701				err("More than one active alt. setting! Ignoring #%d.", i);
3702		}
3703	}
3704	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
3705		err("Failed to recognize the camera!");
3706		return -ENODEV;
3707	}
3708
3709	/* Validate options */
3710	switch (model) {
3711	case IBMCAM_MODEL_1:
3712		RESTRICT_TO_RANGE(lighting, 0, 2);
3713		RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288);
3714		if (framerate < 0)
3715			framerate = 2;
3716		canvasX = 352;
3717		canvasY = 288;
3718		break;
3719	case IBMCAM_MODEL_2:
3720		RESTRICT_TO_RANGE(lighting, 0, 15);
3721		RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240);
3722		if (framerate < 0)
3723			framerate = 2;
3724		canvasX = 352;
3725		canvasY = 240;
3726		break;
3727	case IBMCAM_MODEL_3:
3728		RESTRICT_TO_RANGE(lighting, 0, 15);
3729		switch (size) {
3730		case SIZE_160x120:
3731			canvasX = 160;
3732			canvasY = 120;
3733			if (framerate < 0)
3734				framerate = 2;
3735			RESTRICT_TO_RANGE(framerate, 0, 5);
3736			break;
3737		default:
3738			info("IBM camera: using 320x240");
3739			size = SIZE_320x240;
3740			/* No break here */
3741		case SIZE_320x240:
3742			canvasX = 320;
3743			canvasY = 240;
3744			if (framerate < 0)
3745				framerate = 3;
3746			RESTRICT_TO_RANGE(framerate, 0, 5);
3747			break;
3748		case SIZE_640x480:
3749			canvasX = 640;
3750			canvasY = 480;
3751			framerate = 0;	/* Slowest, and maybe even that is too fast */
3752			break;
3753		}
3754		break;
3755	case IBMCAM_MODEL_4:
3756		RESTRICT_TO_RANGE(lighting, 0, 2);
3757		switch (size) {
3758		case SIZE_128x96:
3759			canvasX = 128;
3760			canvasY = 96;
3761			break;
3762		case SIZE_160x120:
3763			canvasX = 160;
3764			canvasY = 120;
3765			break;
3766		default:
3767			info("IBM NetCamera: using 176x144");
3768			size = SIZE_176x144;
3769			/* No break here */
3770		case SIZE_176x144:
3771			canvasX = 176;
3772			canvasY = 144;
3773			break;
3774		case SIZE_320x240:
3775			canvasX = 320;
3776			canvasY = 240;
3777			break;
3778		case SIZE_352x288:
3779			canvasX = 352;
3780			canvasY = 288;
3781			break;
3782		}
3783		break;
3784	default:
3785		err("IBM camera: Model %d. not supported!", model);
3786		return -ENODEV;
3787	}
3788
3789	uvd = usbvideo_AllocateDevice(cams);
3790	if (uvd != NULL) {
3791		/* Here uvd is a fully allocated uvd object */
3792		uvd->flags = flags;
3793		uvd->debug = debug;
3794		uvd->dev = dev;
3795		uvd->iface = ifnum;
3796		uvd->ifaceAltInactive = inactInterface;
3797		uvd->ifaceAltActive = actInterface;
3798		uvd->video_endp = video_ep;
3799		uvd->iso_packet_len = maxPS;
3800		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
3801		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
3802		uvd->canvas = VIDEOSIZE(canvasX, canvasY);
3803		uvd->videosize = ibmcam_size_to_videosize(size);
3804
3805		/* Initialize ibmcam-specific data */
3806		assert(IBMCAM_T(uvd) != NULL);
3807		IBMCAM_T(uvd)->camera_model = model;
3808		IBMCAM_T(uvd)->initialized = 0;
3809
3810		ibmcam_configure_video(uvd);
3811
3812		i = usbvideo_RegisterVideoDevice(uvd);
3813		if (i != 0) {
3814			err("usbvideo_RegisterVideoDevice() failed.");
3815			uvd = NULL;
3816		}
3817	}
3818	usb_set_intfdata (intf, uvd);
3819	return 0;
3820}
3821
3822
3823static struct usb_device_id id_table[] = {
3824	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
3825	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
3826	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
3827	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
3828	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
3829	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
3830	{ }  /* Terminating entry */
3831};
3832
3833/*
3834 * ibmcam_init()
3835 *
3836 * This code is run to initialize the driver.
3837 *
3838 * History:
3839 * 1/27/00  Reworked to use statically allocated ibmcam structures.
3840 * 21/10/00 Completely redesigned to use usbvideo services.
3841 */
3842static int __init ibmcam_init(void)
3843{
3844	struct usbvideo_cb cbTbl;
3845	memset(&cbTbl, 0, sizeof(cbTbl));
3846	cbTbl.probe = ibmcam_probe;
3847	cbTbl.setupOnOpen = ibmcam_setup_on_open;
3848	cbTbl.videoStart = ibmcam_video_start;
3849	cbTbl.videoStop = ibmcam_video_stop;
3850	cbTbl.processData = ibmcam_ProcessIsocData;
3851	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
3852	cbTbl.adjustPicture = ibmcam_adjust_picture;
3853	cbTbl.getFPS = ibmcam_calculate_fps;
3854	return usbvideo_register(
3855		&cams,
3856		MAX_IBMCAM,
3857		sizeof(ibmcam_t),
3858		"ibmcam",
3859		&cbTbl,
3860		THIS_MODULE,
3861		id_table);
3862}
3863
3864static void __exit ibmcam_cleanup(void)
3865{
3866	usbvideo_Deregister(&cams);
3867}
3868
3869MODULE_DEVICE_TABLE(usb, id_table);
3870
3871module_init(ibmcam_init);
3872module_exit(ibmcam_cleanup);
3873