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