linux/drivers/media/video/gspca/spca508.c
<<
>>
Prefs
   1/*
   2 * SPCA508 chip based cameras subdriver
   3 *
   4 * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20
  21#define MODULE_NAME "spca508"
  22
  23#include "gspca.h"
  24
  25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  26MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
  27MODULE_LICENSE("GPL");
  28
  29/* specific webcam descriptor */
  30struct sd {
  31        struct gspca_dev gspca_dev;             /* !! must be the first item */
  32
  33        u8 brightness;
  34
  35        u8 subtype;
  36#define CreativeVista 0
  37#define HamaUSBSightcam 1
  38#define HamaUSBSightcam2 2
  39#define IntelEasyPCCamera 3
  40#define MicroInnovationIC200 4
  41#define ViewQuestVQ110 5
  42};
  43
  44/* V4L2 controls supported by the driver */
  45static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  46static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  47
  48static const struct ctrl sd_ctrls[] = {
  49        {
  50            {
  51                .id      = V4L2_CID_BRIGHTNESS,
  52                .type    = V4L2_CTRL_TYPE_INTEGER,
  53                .name    = "Brightness",
  54                .minimum = 0,
  55                .maximum = 255,
  56                .step    = 1,
  57#define BRIGHTNESS_DEF 128
  58                .default_value = BRIGHTNESS_DEF,
  59            },
  60            .set = sd_setbrightness,
  61            .get = sd_getbrightness,
  62        },
  63};
  64
  65static const struct v4l2_pix_format sif_mode[] = {
  66        {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
  67                .bytesperline = 160,
  68                .sizeimage = 160 * 120 * 3 / 2,
  69                .colorspace = V4L2_COLORSPACE_SRGB,
  70                .priv = 3},
  71        {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
  72                .bytesperline = 176,
  73                .sizeimage = 176 * 144 * 3 / 2,
  74                .colorspace = V4L2_COLORSPACE_SRGB,
  75                .priv = 2},
  76        {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
  77                .bytesperline = 320,
  78                .sizeimage = 320 * 240 * 3 / 2,
  79                .colorspace = V4L2_COLORSPACE_SRGB,
  80                .priv = 1},
  81        {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
  82                .bytesperline = 352,
  83                .sizeimage = 352 * 288 * 3 / 2,
  84                .colorspace = V4L2_COLORSPACE_SRGB,
  85                .priv = 0},
  86};
  87
  88/* Frame packet header offsets for the spca508 */
  89#define SPCA508_OFFSET_DATA 37
  90
  91/*
  92 * Initialization data: this is the first set-up data written to the
  93 * device (before the open data).
  94 */
  95static const u16 spca508_init_data[][2] = {
  96        {0x0000, 0x870b},
  97
  98        {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
  99        {0x0003, 0x8111},       /* Reset compression & memory */
 100        {0x0000, 0x8110},       /* Disable all outputs */
 101        /* READ {0x0000, 0x8114} -> 0000: 00  */
 102        {0x0000, 0x8114},       /* SW GPIO data */
 103        {0x0008, 0x8110},       /* Enable charge pump output */
 104        {0x0002, 0x8116},       /* 200 kHz pump clock */
 105        /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
 106        {0x0003, 0x8111},       /* Reset compression & memory */
 107        {0x0000, 0x8111},       /* Normal mode (not reset) */
 108        {0x0098, 0x8110},
 109                /* Enable charge pump output, sync.serial,external 2x clock */
 110        {0x000d, 0x8114},       /* SW GPIO data */
 111        {0x0002, 0x8116},       /* 200 kHz pump clock */
 112        {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
 113/* --------------------------------------- */
 114        {0x000f, 0x8402},       /* memory bank */
 115        {0x0000, 0x8403},       /* ... address */
 116/* --------------------------------------- */
 117/* 0x88__ is Synchronous Serial Interface. */
 118/* TBD: This table could be expressed more compactly */
 119/* using spca508_write_i2c_vector(). */
 120/* TBD: Should see if the values in spca50x_i2c_data */
 121/* would work with the VQ110 instead of the values */
 122/* below. */
 123        {0x00c0, 0x8804},       /* SSI slave addr */
 124        {0x0008, 0x8802},       /* 375 Khz SSI clock */
 125        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 126        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 127        {0x0008, 0x8802},       /* 375 Khz SSI clock */
 128        {0x0012, 0x8801},       /* SSI reg addr */
 129        {0x0080, 0x8800},       /* SSI data to write */
 130        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 131        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 132        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 133        {0x0008, 0x8802},       /* 375 Khz SSI clock */
 134        {0x0012, 0x8801},       /* SSI reg addr */
 135        {0x0000, 0x8800},       /* SSI data to write */
 136        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 137        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 138        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 139        {0x0008, 0x8802},       /* 375 Khz SSI clock */
 140        {0x0011, 0x8801},       /* SSI reg addr */
 141        {0x0040, 0x8800},       /* SSI data to write */
 142        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 143        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 144        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 145        {0x0008, 0x8802},
 146        {0x0013, 0x8801},
 147        {0x0000, 0x8800},
 148        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 149        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 150        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 151        {0x0008, 0x8802},
 152        {0x0014, 0x8801},
 153        {0x0000, 0x8800},
 154        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 155        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 156        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 157        {0x0008, 0x8802},
 158        {0x0015, 0x8801},
 159        {0x0001, 0x8800},
 160        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 161        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 162        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 163        {0x0008, 0x8802},
 164        {0x0016, 0x8801},
 165        {0x0003, 0x8800},
 166        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 167        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 168        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 169        {0x0008, 0x8802},
 170        {0x0017, 0x8801},
 171        {0x0036, 0x8800},
 172        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 173        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 174        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 175        {0x0008, 0x8802},
 176        {0x0018, 0x8801},
 177        {0x00ec, 0x8800},
 178        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 179        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 180        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 181        {0x0008, 0x8802},
 182        {0x001a, 0x8801},
 183        {0x0094, 0x8800},
 184        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 185        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 186        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 187        {0x0008, 0x8802},
 188        {0x001b, 0x8801},
 189        {0x0000, 0x8800},
 190        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 191        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 192        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 193        {0x0008, 0x8802},
 194        {0x0027, 0x8801},
 195        {0x00a2, 0x8800},
 196        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 197        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 198        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 199        {0x0008, 0x8802},
 200        {0x0028, 0x8801},
 201        {0x0040, 0x8800},
 202        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 203        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 204        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 205        {0x0008, 0x8802},
 206        {0x002a, 0x8801},
 207        {0x0084, 0x8800},
 208        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 209        /* READ { 0x0001, 0x8803 } -> 0000: 00 */
 210        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 211        {0x0008, 0x8802},
 212        {0x002b, 0x8801},
 213        {0x00a8, 0x8800},
 214        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 215        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 216        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 217        {0x0008, 0x8802},
 218        {0x002c, 0x8801},
 219        {0x00fe, 0x8800},
 220        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 221        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 222        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 223        {0x0008, 0x8802},
 224        {0x002d, 0x8801},
 225        {0x0003, 0x8800},
 226        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 227        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 228        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 229        {0x0008, 0x8802},
 230        {0x0038, 0x8801},
 231        {0x0083, 0x8800},
 232        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 233        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 234        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 235        {0x0008, 0x8802},
 236        {0x0033, 0x8801},
 237        {0x0081, 0x8800},
 238        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 239        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 240        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 241        {0x0008, 0x8802},
 242        {0x0034, 0x8801},
 243        {0x004a, 0x8800},
 244        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 245        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 246        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 247        {0x0008, 0x8802},
 248        {0x0039, 0x8801},
 249        {0x0000, 0x8800},
 250        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 251        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 252        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 253        {0x0008, 0x8802},
 254        {0x0010, 0x8801},
 255        {0x00a8, 0x8800},
 256        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 257        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 258        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 259        {0x0008, 0x8802},
 260        {0x0006, 0x8801},
 261        {0x0058, 0x8800},
 262        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 263        /* READ { 0x0001, 0x8803 } -> 0000: 00 */
 264        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 265        {0x0008, 0x8802},
 266        {0x0000, 0x8801},
 267        {0x0004, 0x8800},
 268        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 269        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 270        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 271        {0x0008, 0x8802},
 272        {0x0040, 0x8801},
 273        {0x0080, 0x8800},
 274        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 275        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 276        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 277        {0x0008, 0x8802},
 278        {0x0041, 0x8801},
 279        {0x000c, 0x8800},
 280        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 281        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 282        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 283        {0x0008, 0x8802},
 284        {0x0042, 0x8801},
 285        {0x000c, 0x8800},
 286        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 287        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 288        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 289        {0x0008, 0x8802},
 290        {0x0043, 0x8801},
 291        {0x0028, 0x8800},
 292        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 293        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 294        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 295        {0x0008, 0x8802},
 296        {0x0044, 0x8801},
 297        {0x0080, 0x8800},
 298        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 299        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 300        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 301        {0x0008, 0x8802},
 302        {0x0045, 0x8801},
 303        {0x0020, 0x8800},
 304        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 305        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 306        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 307        {0x0008, 0x8802},
 308        {0x0046, 0x8801},
 309        {0x0020, 0x8800},
 310        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 311        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 312        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 313        {0x0008, 0x8802},
 314        {0x0047, 0x8801},
 315        {0x0080, 0x8800},
 316        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 317        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 318        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 319        {0x0008, 0x8802},
 320        {0x0048, 0x8801},
 321        {0x004c, 0x8800},
 322        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 323        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 324        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 325        {0x0008, 0x8802},
 326        {0x0049, 0x8801},
 327        {0x0084, 0x8800},
 328        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 329        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 330        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 331        {0x0008, 0x8802},
 332        {0x004a, 0x8801},
 333        {0x0084, 0x8800},
 334        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 335        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 336        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 337        {0x0008, 0x8802},
 338        {0x004b, 0x8801},
 339        {0x0084, 0x8800},
 340        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 341        /* --------------------------------------- */
 342        {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
 343        {0x0000, 0x8701},       /* CKx1 clock delay adj */
 344        {0x0000, 0x8701},       /* CKx1 clock delay adj */
 345        {0x0001, 0x870c},       /* CKOx2 output */
 346        /* --------------------------------------- */
 347        {0x0080, 0x8600},       /* Line memory read counter (L) */
 348        {0x0001, 0x8606},       /* reserved */
 349        {0x0064, 0x8607},       /* Line memory read counter (H) 0x6480=25,728 */
 350        {0x002a, 0x8601},       /* CDSP sharp interpolation mode,
 351         *                      line sel for color sep, edge enhance enab */
 352        {0x0000, 0x8602},       /* optical black level for user settng = 0 */
 353        {0x0080, 0x8600},       /* Line memory read counter (L) */
 354        {0x000a, 0x8603},       /* optical black level calc mode:
 355                                 * auto; optical black offset = 10 */
 356        {0x00df, 0x865b},       /* Horiz offset for valid pixels (L)=0xdf */
 357        {0x0012, 0x865c},       /* Vert offset for valid lines (L)=0x12 */
 358
 359/* The following two lines seem to be the "wrong" resolution. */
 360/* But perhaps these indicate the actual size of the sensor */
 361/* rather than the size of the current video mode. */
 362        {0x0058, 0x865d},       /* Horiz valid pixels (*4) (L) = 352 */
 363        {0x0048, 0x865e},       /* Vert valid lines (*4) (L) = 288 */
 364
 365        {0x0015, 0x8608},       /* A11 Coef ... */
 366        {0x0030, 0x8609},
 367        {0x00fb, 0x860a},
 368        {0x003e, 0x860b},
 369        {0x00ce, 0x860c},
 370        {0x00f4, 0x860d},
 371        {0x00eb, 0x860e},
 372        {0x00dc, 0x860f},
 373        {0x0039, 0x8610},
 374        {0x0001, 0x8611},       /* R offset for white balance ... */
 375        {0x0000, 0x8612},
 376        {0x0001, 0x8613},
 377        {0x0000, 0x8614},
 378        {0x005b, 0x8651},       /* R gain for white balance ... */
 379        {0x0040, 0x8652},
 380        {0x0060, 0x8653},
 381        {0x0040, 0x8654},
 382        {0x0000, 0x8655},
 383        {0x0001, 0x863f},       /* Fixed gamma correction enable, USB control,
 384                                 * lum filter disable, lum noise clip disable */
 385        {0x00a1, 0x8656},       /* Window1 size 256x256, Windows2 size 64x64,
 386                                 * gamma look-up disable,
 387                                 * new edge enhancement enable */
 388        {0x0018, 0x8657},       /* Edge gain high thresh */
 389        {0x0020, 0x8658},       /* Edge gain low thresh */
 390        {0x000a, 0x8659},       /* Edge bandwidth high threshold */
 391        {0x0005, 0x865a},       /* Edge bandwidth low threshold */
 392        /* -------------------------------- */
 393        {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
 394        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 395        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 396        {0xa908, 0x8802},
 397        {0x0034, 0x8801},       /* SSI reg addr */
 398        {0x00ca, 0x8800},
 399        /* SSI data to write */
 400        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 401        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 402        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 403        {0x1f08, 0x8802},
 404        {0x0006, 0x8801},
 405        {0x0080, 0x8800},
 406        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 407
 408/* ----- Read back coefs we wrote earlier. */
 409        /* READ { 0x0000, 0x8608 } -> 0000: 15  */
 410        /* READ { 0x0000, 0x8609 } -> 0000: 30  */
 411        /* READ { 0x0000, 0x860a } -> 0000: fb  */
 412        /* READ { 0x0000, 0x860b } -> 0000: 3e  */
 413        /* READ { 0x0000, 0x860c } -> 0000: ce  */
 414        /* READ { 0x0000, 0x860d } -> 0000: f4  */
 415        /* READ { 0x0000, 0x860e } -> 0000: eb  */
 416        /* READ { 0x0000, 0x860f } -> 0000: dc  */
 417        /* READ { 0x0000, 0x8610 } -> 0000: 39  */
 418        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 419        /* READ { 0x0001, 0x8802 } -> 0000: 08  */
 420        {0xb008, 0x8802},
 421        {0x0006, 0x8801},
 422        {0x007d, 0x8800},
 423        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 424
 425
 426        /* This chunk is seemingly redundant with */
 427        /* earlier commands (A11 Coef...), but if I disable it, */
 428        /* the image appears too dark.  Maybe there was some kind of */
 429        /* reset since the earlier commands, so this is necessary again. */
 430        {0x0015, 0x8608},
 431        {0x0030, 0x8609},
 432        {0xfffb, 0x860a},
 433        {0x003e, 0x860b},
 434        {0xffce, 0x860c},
 435        {0xfff4, 0x860d},
 436        {0xffeb, 0x860e},
 437        {0xffdc, 0x860f},
 438        {0x0039, 0x8610},
 439        {0x0018, 0x8657},
 440
 441        {0x0000, 0x8508},       /* Disable compression. */
 442        /* Previous line was:
 443        {0x0021, 0x8508},        * Enable compression. */
 444        {0x0032, 0x850b},       /* compression stuff */
 445        {0x0003, 0x8509},       /* compression stuff */
 446        {0x0011, 0x850a},       /* compression stuff */
 447        {0x0021, 0x850d},       /* compression stuff */
 448        {0x0010, 0x850c},       /* compression stuff */
 449        {0x0003, 0x8500},       /* *** Video mode: 160x120 */
 450        {0x0001, 0x8501},       /* Hardware-dominated snap control */
 451        {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
 452                                 * gamma look-up disable,
 453                                 * new edge enhancement enable */
 454        {0x0018, 0x8617},       /* Window1 start X (*2) */
 455        {0x0008, 0x8618},       /* Window1 start Y (*2) */
 456        {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
 457                                 * gamma look-up disable,
 458                                 * new edge enhancement enable */
 459        {0x0058, 0x8619},       /* Window2 start X (*2) */
 460        {0x0008, 0x861a},       /* Window2 start Y (*2) */
 461        {0x00ff, 0x8615},       /* High lum thresh for white balance */
 462        {0x0000, 0x8616},       /* Low lum thresh for white balance */
 463        {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
 464        {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
 465        /* READ { 0x0000, 0x8656 } -> 0000: 61  */
 466        {0x0028, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
 467        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 468        /* READ { 0x0001, 0x8802 } -> 0000: 28  */
 469        {0x1f28, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
 470        {0x0010, 0x8801},       /* SSI reg addr */
 471        {0x003e, 0x8800},       /* SSI data to write */
 472        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 473        {0x0028, 0x8802},
 474        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 475        /* READ { 0x0001, 0x8802 } -> 0000: 28  */
 476        {0x1f28, 0x8802},
 477        {0x0000, 0x8801},
 478        {0x001f, 0x8800},
 479        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 480        {0x0001, 0x8602},    /* optical black level for user settning = 1 */
 481
 482        /* Original: */
 483        {0x0023, 0x8700},       /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
 484        {0x000f, 0x8602},    /* optical black level for user settning = 15 */
 485
 486        {0x0028, 0x8802},
 487        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 488        /* READ { 0x0001, 0x8802 } -> 0000: 28  */
 489        {0x1f28, 0x8802},
 490        {0x0010, 0x8801},
 491        {0x007b, 0x8800},
 492        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
 493        {0x002f, 0x8651},       /* R gain for white balance ... */
 494        {0x0080, 0x8653},
 495        /* READ { 0x0000, 0x8655 } -> 0000: 00  */
 496        {0x0000, 0x8655},
 497
 498        {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
 499        {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
 500        /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
 501        {}
 502};
 503
 504/*
 505 * Initialization data for Intel EasyPC Camera CS110
 506 */
 507static const u16 spca508cs110_init_data[][2] = {
 508        {0x0000, 0x870b},       /* Reset CTL3 */
 509        {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
 510        {0x0000, 0x8111},       /* Normal operation on reset */
 511        {0x0090, 0x8110},
 512                 /* External Clock 2x & Synchronous Serial Interface Output */
 513        {0x0020, 0x8112},       /* Video Drop packet enable */
 514        {0x0000, 0x8114},       /* Software GPIO output data */
 515        {0x0001, 0x8114},
 516        {0x0001, 0x8114},
 517        {0x0001, 0x8114},
 518        {0x0003, 0x8114},
 519
 520        /* Initial sequence Synchronous Serial Interface */
 521        {0x000f, 0x8402},       /* Memory bank Address */
 522        {0x0000, 0x8403},       /* Memory bank Address */
 523        {0x00ba, 0x8804},       /* SSI Slave address */
 524        {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
 525        {0x0010, 0x8802},       /* 93.75kHz SSI Clock two DataByte */
 526
 527        {0x0001, 0x8801},
 528        {0x000a, 0x8805},       /* a - NWG: Dunno what this is about */
 529        {0x0000, 0x8800},
 530        {0x0010, 0x8802},
 531
 532        {0x0002, 0x8801},
 533        {0x0000, 0x8805},
 534        {0x0000, 0x8800},
 535        {0x0010, 0x8802},
 536
 537        {0x0003, 0x8801},
 538        {0x0027, 0x8805},
 539        {0x0001, 0x8800},
 540        {0x0010, 0x8802},
 541
 542        {0x0004, 0x8801},
 543        {0x0065, 0x8805},
 544        {0x0001, 0x8800},
 545        {0x0010, 0x8802},
 546
 547        {0x0005, 0x8801},
 548        {0x0003, 0x8805},
 549        {0x0000, 0x8800},
 550        {0x0010, 0x8802},
 551
 552        {0x0006, 0x8801},
 553        {0x001c, 0x8805},
 554        {0x0000, 0x8800},
 555        {0x0010, 0x8802},
 556
 557        {0x0007, 0x8801},
 558        {0x002a, 0x8805},
 559        {0x0000, 0x8800},
 560        {0x0010, 0x8802},
 561
 562        {0x0002, 0x8704},       /* External input CKIx1 */
 563        {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
 564        {0x009a, 0x8600},       /* Line memory Read Counter (L) */
 565        {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
 566        {0x0003, 0x865c},       /* 3 Vertical Offset for Valid Lines(L) */
 567        {0x0058, 0x865d},       /* 58 Horizontal Valid Pixel Window(L) */
 568
 569        {0x0006, 0x8660},       /* Nibble data + input order */
 570
 571        {0x000a, 0x8602},       /* Optical black level set to 0x0a */
 572        {0x0000, 0x8603},       /* Optical black level Offset */
 573
 574/*      {0x0000, 0x8611},        * 0 R  Offset for white Balance */
 575/*      {0x0000, 0x8612},        * 1 Gr Offset for white Balance */
 576/*      {0x0000, 0x8613},        * 1f B  Offset for white Balance */
 577/*      {0x0000, 0x8614},        * f0 Gb Offset for white Balance */
 578
 579        {0x0040, 0x8651},   /* 2b BLUE gain for white balance  good at all 60 */
 580        {0x0030, 0x8652},       /* 41 Gr Gain for white Balance (L) */
 581        {0x0035, 0x8653},       /* 26 RED gain for white balance */
 582        {0x0035, 0x8654},       /* 40Gb Gain for white Balance (L) */
 583        {0x0041, 0x863f},
 584              /* Fixed Gamma correction enabled (makes colours look better) */
 585
 586        {0x0000, 0x8655},
 587                /* High bits for white balance*****brightness control*** */
 588        {}
 589};
 590
 591static const u16 spca508_sightcam_init_data[][2] = {
 592/* This line seems to setup the frame/canvas */
 593        {0x000f, 0x8402},
 594
 595/* These 6 lines are needed to startup the webcam */
 596        {0x0090, 0x8110},
 597        {0x0001, 0x8114},
 598        {0x0001, 0x8114},
 599        {0x0001, 0x8114},
 600        {0x0003, 0x8114},
 601        {0x0080, 0x8804},
 602
 603/* This part seems to make the pictures darker? (autobrightness?) */
 604        {0x0001, 0x8801},
 605        {0x0004, 0x8800},
 606        {0x0003, 0x8801},
 607        {0x00e0, 0x8800},
 608        {0x0004, 0x8801},
 609        {0x00b4, 0x8800},
 610        {0x0005, 0x8801},
 611        {0x0000, 0x8800},
 612
 613        {0x0006, 0x8801},
 614        {0x00e0, 0x8800},
 615        {0x0007, 0x8801},
 616        {0x000c, 0x8800},
 617
 618/* This section is just needed, it probably
 619 * does something like the previous section,
 620 * but the cam won't start if it's not included.
 621 */
 622        {0x0014, 0x8801},
 623        {0x0008, 0x8800},
 624        {0x0015, 0x8801},
 625        {0x0067, 0x8800},
 626        {0x0016, 0x8801},
 627        {0x0000, 0x8800},
 628        {0x0017, 0x8801},
 629        {0x0020, 0x8800},
 630        {0x0018, 0x8801},
 631        {0x0044, 0x8800},
 632
 633/* Makes the picture darker - and the
 634 * cam won't start if not included
 635 */
 636        {0x001e, 0x8801},
 637        {0x00ea, 0x8800},
 638        {0x001f, 0x8801},
 639        {0x0001, 0x8800},
 640        {0x0003, 0x8801},
 641        {0x00e0, 0x8800},
 642
 643/* seems to place the colors ontop of each other #1 */
 644        {0x0006, 0x8704},
 645        {0x0001, 0x870c},
 646        {0x0016, 0x8600},
 647        {0x0002, 0x8606},
 648
 649/* if not included the pictures becomes _very_ dark */
 650        {0x0064, 0x8607},
 651        {0x003a, 0x8601},
 652        {0x0000, 0x8602},
 653
 654/* seems to place the colors ontop of each other #2 */
 655        {0x0016, 0x8600},
 656        {0x0018, 0x8617},
 657        {0x0008, 0x8618},
 658        {0x00a1, 0x8656},
 659
 660/* webcam won't start if not included */
 661        {0x0007, 0x865b},
 662        {0x0001, 0x865c},
 663        {0x0058, 0x865d},
 664        {0x0048, 0x865e},
 665
 666/* adjusts the colors */
 667        {0x0049, 0x8651},
 668        {0x0040, 0x8652},
 669        {0x004c, 0x8653},
 670        {0x0040, 0x8654},
 671        {}
 672};
 673
 674static const u16 spca508_sightcam2_init_data[][2] = {
 675        {0x0020, 0x8112},
 676
 677        {0x000f, 0x8402},
 678        {0x0000, 0x8403},
 679
 680        {0x0008, 0x8201},
 681        {0x0008, 0x8200},
 682        {0x0001, 0x8200},
 683        {0x0009, 0x8201},
 684        {0x0008, 0x8200},
 685        {0x0001, 0x8200},
 686        {0x000a, 0x8201},
 687        {0x0008, 0x8200},
 688        {0x0001, 0x8200},
 689        {0x000b, 0x8201},
 690        {0x0008, 0x8200},
 691        {0x0001, 0x8200},
 692        {0x000c, 0x8201},
 693        {0x0008, 0x8200},
 694        {0x0001, 0x8200},
 695        {0x000d, 0x8201},
 696        {0x0008, 0x8200},
 697        {0x0001, 0x8200},
 698        {0x000e, 0x8201},
 699        {0x0008, 0x8200},
 700        {0x0001, 0x8200},
 701        {0x0007, 0x8201},
 702        {0x0008, 0x8200},
 703        {0x0001, 0x8200},
 704        {0x000f, 0x8201},
 705        {0x0008, 0x8200},
 706        {0x0001, 0x8200},
 707
 708        {0x0018, 0x8660},
 709        {0x0010, 0x8201},
 710
 711        {0x0008, 0x8200},
 712        {0x0001, 0x8200},
 713        {0x0011, 0x8201},
 714        {0x0008, 0x8200},
 715        {0x0001, 0x8200},
 716
 717        {0x0000, 0x86b0},
 718        {0x0034, 0x86b1},
 719        {0x0000, 0x86b2},
 720        {0x0049, 0x86b3},
 721        {0x0000, 0x86b4},
 722        {0x0000, 0x86b4},
 723
 724        {0x0012, 0x8201},
 725        {0x0008, 0x8200},
 726        {0x0001, 0x8200},
 727        {0x0013, 0x8201},
 728        {0x0008, 0x8200},
 729        {0x0001, 0x8200},
 730
 731        {0x0001, 0x86b0},
 732        {0x00aa, 0x86b1},
 733        {0x0000, 0x86b2},
 734        {0x00e4, 0x86b3},
 735        {0x0000, 0x86b4},
 736        {0x0000, 0x86b4},
 737
 738        {0x0018, 0x8660},
 739
 740        {0x0090, 0x8110},
 741        {0x0001, 0x8114},
 742        {0x0001, 0x8114},
 743        {0x0001, 0x8114},
 744        {0x0003, 0x8114},
 745
 746        {0x0080, 0x8804},
 747        {0x0003, 0x8801},
 748        {0x0012, 0x8800},
 749        {0x0004, 0x8801},
 750        {0x0005, 0x8800},
 751        {0x0005, 0x8801},
 752        {0x0000, 0x8800},
 753        {0x0006, 0x8801},
 754        {0x0000, 0x8800},
 755        {0x0007, 0x8801},
 756        {0x0000, 0x8800},
 757        {0x0008, 0x8801},
 758        {0x0005, 0x8800},
 759        {0x000a, 0x8700},
 760        {0x000e, 0x8801},
 761        {0x0004, 0x8800},
 762        {0x0005, 0x8801},
 763        {0x0047, 0x8800},
 764        {0x0006, 0x8801},
 765        {0x0000, 0x8800},
 766        {0x0007, 0x8801},
 767        {0x00c0, 0x8800},
 768        {0x0008, 0x8801},
 769        {0x0003, 0x8800},
 770        {0x0013, 0x8801},
 771        {0x0001, 0x8800},
 772        {0x0009, 0x8801},
 773        {0x0000, 0x8800},
 774        {0x000a, 0x8801},
 775        {0x0000, 0x8800},
 776        {0x000b, 0x8801},
 777        {0x0000, 0x8800},
 778        {0x000c, 0x8801},
 779        {0x0000, 0x8800},
 780        {0x000e, 0x8801},
 781        {0x0004, 0x8800},
 782        {0x000f, 0x8801},
 783        {0x0000, 0x8800},
 784        {0x0010, 0x8801},
 785        {0x0006, 0x8800},
 786        {0x0011, 0x8801},
 787        {0x0006, 0x8800},
 788        {0x0012, 0x8801},
 789        {0x0000, 0x8800},
 790        {0x0013, 0x8801},
 791        {0x0001, 0x8800},
 792
 793        {0x000a, 0x8700},
 794        {0x0000, 0x8702},
 795        {0x0000, 0x8703},
 796        {0x00c2, 0x8704},
 797        {0x0001, 0x870c},
 798
 799        {0x0044, 0x8600},
 800        {0x0002, 0x8606},
 801        {0x0064, 0x8607},
 802        {0x003a, 0x8601},
 803        {0x0008, 0x8602},
 804        {0x0044, 0x8600},
 805        {0x0018, 0x8617},
 806        {0x0008, 0x8618},
 807        {0x00a1, 0x8656},
 808        {0x0004, 0x865b},
 809        {0x0002, 0x865c},
 810        {0x0058, 0x865d},
 811        {0x0048, 0x865e},
 812        {0x0012, 0x8608},
 813        {0x002c, 0x8609},
 814        {0x0002, 0x860a},
 815        {0x002c, 0x860b},
 816        {0x00db, 0x860c},
 817        {0x00f9, 0x860d},
 818        {0x00f1, 0x860e},
 819        {0x00e3, 0x860f},
 820        {0x002c, 0x8610},
 821        {0x006c, 0x8651},
 822        {0x0041, 0x8652},
 823        {0x0059, 0x8653},
 824        {0x0040, 0x8654},
 825        {0x00fa, 0x8611},
 826        {0x00ff, 0x8612},
 827        {0x00f8, 0x8613},
 828        {0x0000, 0x8614},
 829        {0x0001, 0x863f},
 830        {0x0000, 0x8640},
 831        {0x0026, 0x8641},
 832        {0x0045, 0x8642},
 833        {0x0060, 0x8643},
 834        {0x0075, 0x8644},
 835        {0x0088, 0x8645},
 836        {0x009b, 0x8646},
 837        {0x00b0, 0x8647},
 838        {0x00c5, 0x8648},
 839        {0x00d2, 0x8649},
 840        {0x00dc, 0x864a},
 841        {0x00e5, 0x864b},
 842        {0x00eb, 0x864c},
 843        {0x00f0, 0x864d},
 844        {0x00f6, 0x864e},
 845        {0x00fa, 0x864f},
 846        {0x00ff, 0x8650},
 847        {0x0060, 0x8657},
 848        {0x0010, 0x8658},
 849        {0x0018, 0x8659},
 850        {0x0005, 0x865a},
 851        {0x0018, 0x8660},
 852        {0x0003, 0x8509},
 853        {0x0011, 0x850a},
 854        {0x0032, 0x850b},
 855        {0x0010, 0x850c},
 856        {0x0021, 0x850d},
 857        {0x0001, 0x8500},
 858        {0x0000, 0x8508},
 859        {0x0012, 0x8608},
 860        {0x002c, 0x8609},
 861        {0x0002, 0x860a},
 862        {0x0039, 0x860b},
 863        {0x00d0, 0x860c},
 864        {0x00f7, 0x860d},
 865        {0x00ed, 0x860e},
 866        {0x00db, 0x860f},
 867        {0x0039, 0x8610},
 868        {0x0012, 0x8657},
 869        {0x000c, 0x8619},
 870        {0x0004, 0x861a},
 871        {0x00a1, 0x8656},
 872        {0x00c8, 0x8615},
 873        {0x0032, 0x8616},
 874
 875        {0x0030, 0x8112},
 876        {0x0020, 0x8112},
 877        {0x0020, 0x8112},
 878        {0x000f, 0x8402},
 879        {0x0000, 0x8403},
 880
 881        {0x0090, 0x8110},
 882        {0x0001, 0x8114},
 883        {0x0001, 0x8114},
 884        {0x0001, 0x8114},
 885        {0x0003, 0x8114},
 886        {0x0080, 0x8804},
 887
 888        {0x0003, 0x8801},
 889        {0x0012, 0x8800},
 890        {0x0004, 0x8801},
 891        {0x0005, 0x8800},
 892        {0x0005, 0x8801},
 893        {0x0047, 0x8800},
 894        {0x0006, 0x8801},
 895        {0x0000, 0x8800},
 896        {0x0007, 0x8801},
 897        {0x00c0, 0x8800},
 898        {0x0008, 0x8801},
 899        {0x0003, 0x8800},
 900        {0x000a, 0x8700},
 901        {0x000e, 0x8801},
 902        {0x0004, 0x8800},
 903        {0x0005, 0x8801},
 904        {0x0047, 0x8800},
 905        {0x0006, 0x8801},
 906        {0x0000, 0x8800},
 907        {0x0007, 0x8801},
 908        {0x00c0, 0x8800},
 909        {0x0008, 0x8801},
 910        {0x0003, 0x8800},
 911        {0x0013, 0x8801},
 912        {0x0001, 0x8800},
 913        {0x0009, 0x8801},
 914        {0x0000, 0x8800},
 915        {0x000a, 0x8801},
 916        {0x0000, 0x8800},
 917        {0x000b, 0x8801},
 918        {0x0000, 0x8800},
 919        {0x000c, 0x8801},
 920        {0x0000, 0x8800},
 921        {0x000e, 0x8801},
 922        {0x0004, 0x8800},
 923        {0x000f, 0x8801},
 924        {0x0000, 0x8800},
 925        {0x0010, 0x8801},
 926        {0x0006, 0x8800},
 927        {0x0011, 0x8801},
 928        {0x0006, 0x8800},
 929        {0x0012, 0x8801},
 930        {0x0000, 0x8800},
 931        {0x0013, 0x8801},
 932        {0x0001, 0x8800},
 933        {0x000a, 0x8700},
 934        {0x0000, 0x8702},
 935        {0x0000, 0x8703},
 936        {0x00c2, 0x8704},
 937        {0x0001, 0x870c},
 938        {0x0044, 0x8600},
 939        {0x0002, 0x8606},
 940        {0x0064, 0x8607},
 941        {0x003a, 0x8601},
 942        {0x0008, 0x8602},
 943        {0x0044, 0x8600},
 944        {0x0018, 0x8617},
 945        {0x0008, 0x8618},
 946        {0x00a1, 0x8656},
 947        {0x0004, 0x865b},
 948        {0x0002, 0x865c},
 949        {0x0058, 0x865d},
 950        {0x0048, 0x865e},
 951        {0x0012, 0x8608},
 952        {0x002c, 0x8609},
 953        {0x0002, 0x860a},
 954        {0x002c, 0x860b},
 955        {0x00db, 0x860c},
 956        {0x00f9, 0x860d},
 957        {0x00f1, 0x860e},
 958        {0x00e3, 0x860f},
 959        {0x002c, 0x8610},
 960        {0x006c, 0x8651},
 961        {0x0041, 0x8652},
 962        {0x0059, 0x8653},
 963        {0x0040, 0x8654},
 964        {0x00fa, 0x8611},
 965        {0x00ff, 0x8612},
 966        {0x00f8, 0x8613},
 967        {0x0000, 0x8614},
 968        {0x0001, 0x863f},
 969        {0x0000, 0x8640},
 970        {0x0026, 0x8641},
 971        {0x0045, 0x8642},
 972        {0x0060, 0x8643},
 973        {0x0075, 0x8644},
 974        {0x0088, 0x8645},
 975        {0x009b, 0x8646},
 976        {0x00b0, 0x8647},
 977        {0x00c5, 0x8648},
 978        {0x00d2, 0x8649},
 979        {0x00dc, 0x864a},
 980        {0x00e5, 0x864b},
 981        {0x00eb, 0x864c},
 982        {0x00f0, 0x864d},
 983        {0x00f6, 0x864e},
 984        {0x00fa, 0x864f},
 985        {0x00ff, 0x8650},
 986        {0x0060, 0x8657},
 987        {0x0010, 0x8658},
 988        {0x0018, 0x8659},
 989        {0x0005, 0x865a},
 990        {0x0018, 0x8660},
 991        {0x0003, 0x8509},
 992        {0x0011, 0x850a},
 993        {0x0032, 0x850b},
 994        {0x0010, 0x850c},
 995        {0x0021, 0x850d},
 996        {0x0001, 0x8500},
 997        {0x0000, 0x8508},
 998
 999        {0x0012, 0x8608},
1000        {0x002c, 0x8609},
1001        {0x0002, 0x860a},
1002        {0x0039, 0x860b},
1003        {0x00d0, 0x860c},
1004        {0x00f7, 0x860d},
1005        {0x00ed, 0x860e},
1006        {0x00db, 0x860f},
1007        {0x0039, 0x8610},
1008        {0x0012, 0x8657},
1009        {0x0064, 0x8619},
1010
1011/* This line starts it all, it is not needed here */
1012/* since it has been build into the driver */
1013/* jfm: don't start now */
1014/*      {0x0030, 0x8112}, */
1015        {}
1016};
1017
1018/*
1019 * Initialization data for Creative Webcam Vista
1020 */
1021static const u16 spca508_vista_init_data[][2] = {
1022        {0x0008, 0x8200},       /* Clear register */
1023        {0x0000, 0x870b},       /* Reset CTL3 */
1024        {0x0020, 0x8112},       /* Video Drop packet enable */
1025        {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
1026        {0x0000, 0x8110},       /* Disable everything */
1027        {0x0000, 0x8114},       /* Software GPIO output data */
1028        {0x0000, 0x8114},
1029
1030        {0x0003, 0x8111},
1031        {0x0000, 0x8111},
1032        {0x0090, 0x8110},    /* Enable: SSI output, External 2X clock output */
1033        {0x0020, 0x8112},
1034        {0x0000, 0x8114},
1035        {0x0001, 0x8114},
1036        {0x0001, 0x8114},
1037        {0x0001, 0x8114},
1038        {0x0003, 0x8114},
1039
1040        {0x000f, 0x8402},       /* Memory bank Address */
1041        {0x0000, 0x8403},       /* Memory bank Address */
1042        {0x00ba, 0x8804},       /* SSI Slave address */
1043        {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
1044
1045        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1046        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1047        {0x0010, 0x8802},       /* Will write 2 bytes (DATA1+DATA2) */
1048        {0x0020, 0x8801},       /* Register address for SSI read/write */
1049        {0x0044, 0x8805},       /* DATA2 */
1050        {0x0004, 0x8800},       /* DATA1 -> write triggered */
1051        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1052
1053        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1054        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1055        {0x0010, 0x8802},
1056        {0x0009, 0x8801},
1057        {0x0042, 0x8805},
1058        {0x0001, 0x8800},
1059        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1060
1061        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1062        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1063        {0x0010, 0x8802},
1064        {0x003c, 0x8801},
1065        {0x0001, 0x8805},
1066        {0x0000, 0x8800},
1067        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1068
1069        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1070        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1071        {0x0010, 0x8802},
1072        {0x0001, 0x8801},
1073        {0x000a, 0x8805},
1074        {0x0000, 0x8800},
1075        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1076
1077        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1078        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1079        {0x0010, 0x8802},
1080        {0x0002, 0x8801},
1081        {0x0000, 0x8805},
1082        {0x0000, 0x8800},
1083        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1084
1085        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1086        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1087        {0x0010, 0x8802},
1088        {0x0003, 0x8801},
1089        {0x0027, 0x8805},
1090        {0x0001, 0x8800},
1091        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1092
1093        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1094        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1095        {0x0010, 0x8802},
1096        {0x0004, 0x8801},
1097        {0x0065, 0x8805},
1098        {0x0001, 0x8800},
1099        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1100
1101        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1102        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1103        {0x0010, 0x8802},
1104        {0x0005, 0x8801},
1105        {0x0003, 0x8805},
1106        {0x0000, 0x8800},
1107        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1108
1109        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1110        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1111        {0x0010, 0x8802},
1112        {0x0006, 0x8801},
1113        {0x001c, 0x8805},
1114        {0x0000, 0x8800},
1115        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1116
1117        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1118        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1119        {0x0010, 0x8802},
1120        {0x0007, 0x8801},
1121        {0x002a, 0x8805},
1122        {0x0000, 0x8800},
1123        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1124
1125        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1126        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1127        {0x0010, 0x8802},
1128        {0x000e, 0x8801},
1129        {0x0000, 0x8805},
1130        {0x0000, 0x8800},
1131        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1132
1133        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1134        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1135        {0x0010, 0x8802},
1136        {0x0028, 0x8801},
1137        {0x002e, 0x8805},
1138        {0x0000, 0x8800},
1139        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1140
1141        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1142        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1143        {0x0010, 0x8802},
1144        {0x0039, 0x8801},
1145        {0x0013, 0x8805},
1146        {0x0000, 0x8800},
1147        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1148
1149        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1150        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1151        {0x0010, 0x8802},
1152        {0x003b, 0x8801},
1153        {0x000c, 0x8805},
1154        {0x0000, 0x8800},
1155        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1156
1157        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1158        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1159        {0x0010, 0x8802},
1160        {0x0035, 0x8801},
1161        {0x0028, 0x8805},
1162        {0x0000, 0x8800},
1163        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1164
1165        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1166        /* READ { 0x0001, 0x8802 } -> 0000: 10  */
1167        {0x0010, 0x8802},
1168        {0x0009, 0x8801},
1169        {0x0042, 0x8805},
1170        {0x0001, 0x8800},
1171        /* READ { 0x0001, 0x8803 } -> 0000: 00  */
1172
1173        {0x0050, 0x8703},
1174        {0x0002, 0x8704},       /* External input CKIx1 */
1175        {0x0001, 0x870c},       /* Select CKOx2 output */
1176        {0x009a, 0x8600},       /* Line memory Read Counter (L) */
1177        {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
1178        {0x0023, 0x8601},
1179        {0x0010, 0x8602},
1180        {0x000a, 0x8603},
1181        {0x009a, 0x8600},
1182        {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
1183        {0x0003, 0x865c},       /* Vertical offset for valid lines (L) */
1184        {0x0058, 0x865d},       /* Horizontal valid pixels window (L) */
1185        {0x0048, 0x865e},       /* Vertical valid lines window (L) */
1186        {0x0000, 0x865f},
1187
1188        {0x0006, 0x8660},
1189                    /* Enable nibble data input, select nibble input order */
1190
1191        {0x0013, 0x8608},       /* A11 Coeficients for color correction */
1192        {0x0028, 0x8609},
1193                    /* Note: these values are confirmed at the end of array */
1194        {0x0005, 0x860a},       /* ... */
1195        {0x0025, 0x860b},
1196        {0x00e1, 0x860c},
1197        {0x00fa, 0x860d},
1198        {0x00f4, 0x860e},
1199        {0x00e8, 0x860f},
1200        {0x0025, 0x8610},       /* A33 Coef. */
1201        {0x00fc, 0x8611},       /* White balance offset: R */
1202        {0x0001, 0x8612},       /* White balance offset: Gr */
1203        {0x00fe, 0x8613},       /* White balance offset: B */
1204        {0x0000, 0x8614},       /* White balance offset: Gb */
1205
1206        {0x0064, 0x8651},       /* R gain for white balance (L) */
1207        {0x0040, 0x8652},       /* Gr gain for white balance (L) */
1208        {0x0066, 0x8653},       /* B gain for white balance (L) */
1209        {0x0040, 0x8654},       /* Gb gain for white balance (L) */
1210        {0x0001, 0x863f},       /* Enable fixed gamma correction */
1211
1212        {0x00a1, 0x8656},       /* Size - Window1: 256x256, Window2: 128x128,
1213                                 * UV division: UV no change,
1214                                 * Enable New edge enhancement */
1215        {0x0018, 0x8657},       /* Edge gain high threshold */
1216        {0x0020, 0x8658},       /* Edge gain low threshold */
1217        {0x000a, 0x8659},       /* Edge bandwidth high threshold */
1218        {0x0005, 0x865a},       /* Edge bandwidth low threshold */
1219        {0x0064, 0x8607},       /* UV filter enable */
1220
1221        {0x0016, 0x8660},
1222        {0x0000, 0x86b0},       /* Bad pixels compensation address */
1223        {0x00dc, 0x86b1},       /* X coord for bad pixels compensation (L) */
1224        {0x0000, 0x86b2},
1225        {0x0009, 0x86b3},       /* Y coord for bad pixels compensation (L) */
1226        {0x0000, 0x86b4},
1227
1228        {0x0001, 0x86b0},
1229        {0x00f5, 0x86b1},
1230        {0x0000, 0x86b2},
1231        {0x00c6, 0x86b3},
1232        {0x0000, 0x86b4},
1233
1234        {0x0002, 0x86b0},
1235        {0x001c, 0x86b1},
1236        {0x0001, 0x86b2},
1237        {0x00d7, 0x86b3},
1238        {0x0000, 0x86b4},
1239
1240        {0x0003, 0x86b0},
1241        {0x001c, 0x86b1},
1242        {0x0001, 0x86b2},
1243        {0x00d8, 0x86b3},
1244        {0x0000, 0x86b4},
1245
1246        {0x0004, 0x86b0},
1247        {0x001d, 0x86b1},
1248        {0x0001, 0x86b2},
1249        {0x00d8, 0x86b3},
1250        {0x0000, 0x86b4},
1251        {0x001e, 0x8660},
1252
1253        /* READ { 0x0000, 0x8608 } -> 0000: 13  */
1254        /* READ { 0x0000, 0x8609 } -> 0000: 28  */
1255        /* READ { 0x0000, 0x8610 } -> 0000: 05  */
1256        /* READ { 0x0000, 0x8611 } -> 0000: 25  */
1257        /* READ { 0x0000, 0x8612 } -> 0000: e1  */
1258        /* READ { 0x0000, 0x8613 } -> 0000: fa  */
1259        /* READ { 0x0000, 0x8614 } -> 0000: f4  */
1260        /* READ { 0x0000, 0x8615 } -> 0000: e8  */
1261        /* READ { 0x0000, 0x8616 } -> 0000: 25  */
1262        {}
1263};
1264
1265static int reg_write(struct usb_device *dev,
1266                        u16 index, u16 value)
1267{
1268        int ret;
1269
1270        ret = usb_control_msg(dev,
1271                        usb_sndctrlpipe(dev, 0),
1272                        0,              /* request */
1273                        USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1274                        value, index, NULL, 0, 500);
1275        PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1276                index, value);
1277        if (ret < 0)
1278                err("reg write: error %d", ret);
1279        return ret;
1280}
1281
1282/* read 1 byte */
1283/* returns: negative is error, pos or zero is data */
1284static int reg_read(struct gspca_dev *gspca_dev,
1285                        u16 index)      /* wIndex */
1286{
1287        int ret;
1288
1289        ret = usb_control_msg(gspca_dev->dev,
1290                        usb_rcvctrlpipe(gspca_dev->dev, 0),
1291                        0,                      /* register */
1292                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1293                        0,              /* value */
1294                        index,
1295                        gspca_dev->usb_buf, 1,
1296                        500);                   /* timeout */
1297        PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1298                index, gspca_dev->usb_buf[0]);
1299        if (ret < 0) {
1300                err("reg_read err %d", ret);
1301                return ret;
1302        }
1303        return gspca_dev->usb_buf[0];
1304}
1305
1306/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
1307static int ssi_w(struct gspca_dev *gspca_dev,
1308                u16 reg, u16 val)
1309{
1310        struct usb_device *dev = gspca_dev->dev;
1311        int ret, retry;
1312
1313        ret = reg_write(dev, 0x8802, reg >> 8);
1314        if (ret < 0)
1315                goto out;
1316        ret = reg_write(dev, 0x8801, reg & 0x00ff);
1317        if (ret < 0)
1318                goto out;
1319        if ((reg & 0xff00) == 0x1000) {         /* if 2 bytes */
1320                ret = reg_write(dev, 0x8805, val & 0x00ff);
1321                if (ret < 0)
1322                        goto out;
1323                val >>= 8;
1324        }
1325        ret = reg_write(dev, 0x8800, val);
1326        if (ret < 0)
1327                goto out;
1328
1329        /* poll until not busy */
1330        retry = 10;
1331        for (;;) {
1332                ret = reg_read(gspca_dev, 0x8803);
1333                if (ret < 0)
1334                        break;
1335                if (gspca_dev->usb_buf[0] == 0)
1336                        break;
1337                if (--retry <= 0) {
1338                        PDEBUG(D_ERR, "ssi_w busy %02x",
1339                                        gspca_dev->usb_buf[0]);
1340                        ret = -1;
1341                        break;
1342                }
1343                msleep(8);
1344        }
1345
1346out:
1347        return ret;
1348}
1349
1350static int write_vector(struct gspca_dev *gspca_dev,
1351                        const u16 (*data)[2])
1352{
1353        struct usb_device *dev = gspca_dev->dev;
1354        int ret = 0;
1355
1356        while ((*data)[1] != 0) {
1357                if ((*data)[1] & 0x8000) {
1358                        if ((*data)[1] == 0xdd00)       /* delay */
1359                                msleep((*data)[0]);
1360                        else
1361                                ret = reg_write(dev, (*data)[1], (*data)[0]);
1362                } else {
1363                        ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
1364                }
1365                if (ret < 0)
1366                        break;
1367                data++;
1368        }
1369        return ret;
1370}
1371
1372/* this function is called at probe time */
1373static int sd_config(struct gspca_dev *gspca_dev,
1374                        const struct usb_device_id *id)
1375{
1376        struct sd *sd = (struct sd *) gspca_dev;
1377        struct cam *cam;
1378        int data1, data2;
1379        const u16 (*init_data)[2];
1380        static const u16 (*(init_data_tb[]))[2] = {
1381                spca508_vista_init_data,        /* CreativeVista 0 */
1382                spca508_sightcam_init_data,     /* HamaUSBSightcam 1 */
1383                spca508_sightcam2_init_data,    /* HamaUSBSightcam2 2 */
1384                spca508cs110_init_data,         /* IntelEasyPCCamera 3 */
1385                spca508cs110_init_data,         /* MicroInnovationIC200 4 */
1386                spca508_init_data,              /* ViewQuestVQ110 5 */
1387        };
1388
1389        /* Read from global register the USB product and vendor IDs, just to
1390         * prove that we can communicate with the device.  This works, which
1391         * confirms at we are communicating properly and that the device
1392         * is a 508. */
1393        data1 = reg_read(gspca_dev, 0x8104);
1394        data2 = reg_read(gspca_dev, 0x8105);
1395        PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1396
1397        data1 = reg_read(gspca_dev, 0x8106);
1398        data2 = reg_read(gspca_dev, 0x8107);
1399        PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1400
1401        data1 = reg_read(gspca_dev, 0x8621);
1402        PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1403
1404        cam = &gspca_dev->cam;
1405        cam->cam_mode = sif_mode;
1406        cam->nmodes = ARRAY_SIZE(sif_mode);
1407
1408        sd->subtype = id->driver_info;
1409        sd->brightness = BRIGHTNESS_DEF;
1410
1411        init_data = init_data_tb[sd->subtype];
1412        return write_vector(gspca_dev, init_data);
1413}
1414
1415/* this function is called at probe and resume time */
1416static int sd_init(struct gspca_dev *gspca_dev)
1417{
1418        return 0;
1419}
1420
1421static int sd_start(struct gspca_dev *gspca_dev)
1422{
1423        int mode;
1424
1425        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1426        reg_write(gspca_dev->dev, 0x8500, mode);
1427        switch (mode) {
1428        case 0:
1429        case 1:
1430                reg_write(gspca_dev->dev, 0x8700, 0x28);        /* clock */
1431                break;
1432        default:
1433/*      case 2: */
1434/*      case 3: */
1435                reg_write(gspca_dev->dev, 0x8700, 0x23);        /* clock */
1436                break;
1437        }
1438        reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
1439        return 0;
1440}
1441
1442static void sd_stopN(struct gspca_dev *gspca_dev)
1443{
1444        /* Video ISO disable, Video Drop Packet enable: */
1445        reg_write(gspca_dev->dev, 0x8112, 0x20);
1446}
1447
1448static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1449                        u8 *data,                       /* isoc packet */
1450                        int len)                        /* iso packet length */
1451{
1452        switch (data[0]) {
1453        case 0:                         /* start of frame */
1454                gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1455                data += SPCA508_OFFSET_DATA;
1456                len -= SPCA508_OFFSET_DATA;
1457                gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1458                break;
1459        case 0xff:                      /* drop */
1460                break;
1461        default:
1462                data += 1;
1463                len -= 1;
1464                gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1465                break;
1466        }
1467}
1468
1469static void setbrightness(struct gspca_dev *gspca_dev)
1470{
1471        struct sd *sd = (struct sd *) gspca_dev;
1472        u8 brightness = sd->brightness;
1473
1474        /* MX seem contrast */
1475        reg_write(gspca_dev->dev, 0x8651, brightness);
1476        reg_write(gspca_dev->dev, 0x8652, brightness);
1477        reg_write(gspca_dev->dev, 0x8653, brightness);
1478        reg_write(gspca_dev->dev, 0x8654, brightness);
1479}
1480
1481static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1482{
1483        struct sd *sd = (struct sd *) gspca_dev;
1484
1485        sd->brightness = val;
1486        if (gspca_dev->streaming)
1487                setbrightness(gspca_dev);
1488        return 0;
1489}
1490
1491static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1492{
1493        struct sd *sd = (struct sd *) gspca_dev;
1494
1495        *val = sd->brightness;
1496        return 0;
1497}
1498
1499/* sub-driver description */
1500static const struct sd_desc sd_desc = {
1501        .name = MODULE_NAME,
1502        .ctrls = sd_ctrls,
1503        .nctrls = ARRAY_SIZE(sd_ctrls),
1504        .config = sd_config,
1505        .init = sd_init,
1506        .start = sd_start,
1507        .stopN = sd_stopN,
1508        .pkt_scan = sd_pkt_scan,
1509};
1510
1511/* -- module initialisation -- */
1512static const struct usb_device_id device_table[] = {
1513        {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
1514        {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
1515        {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
1516        {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
1517        {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
1518        {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
1519        {}
1520};
1521MODULE_DEVICE_TABLE(usb, device_table);
1522
1523/* -- device connect -- */
1524static int sd_probe(struct usb_interface *intf,
1525                        const struct usb_device_id *id)
1526{
1527        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1528                                THIS_MODULE);
1529}
1530
1531static struct usb_driver sd_driver = {
1532        .name = MODULE_NAME,
1533        .id_table = device_table,
1534        .probe = sd_probe,
1535        .disconnect = gspca_disconnect,
1536#ifdef CONFIG_PM
1537        .suspend = gspca_suspend,
1538        .resume = gspca_resume,
1539#endif
1540};
1541
1542/* -- module insert / remove -- */
1543static int __init sd_mod_init(void)
1544{
1545        return usb_register(&sd_driver);
1546}
1547static void __exit sd_mod_exit(void)
1548{
1549        usb_deregister(&sd_driver);
1550}
1551
1552module_init(sd_mod_init);
1553module_exit(sd_mod_exit);
1554