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