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