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