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