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