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