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