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