1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * SPCA508 chip based cameras subdriver 4 * 5 * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr> 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #define MODULE_NAME "spca508" 11 12 #include "gspca.h" 13 14 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 15 MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver"); 16 MODULE_LICENSE("GPL"); 17 18 /* specific webcam descriptor */ 19 struct sd { 20 struct gspca_dev gspca_dev; /* !! must be the first item */ 21 22 u8 subtype; 23 #define CreativeVista 0 24 #define HamaUSBSightcam 1 25 #define HamaUSBSightcam2 2 26 #define IntelEasyPCCamera 3 27 #define MicroInnovationIC200 4 28 #define ViewQuestVQ110 5 29 }; 30 31 static 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 37 56 57 /* 58 * Initialization data: this is the first set-up data written to the 59 * device (before the open data). 60 */ 61 static 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 CS110 472 */ 473 static 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 557 static 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 probably 585 * 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 the 600 * cam won't start if not included 601 */ 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 640 static 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 Vista 986 */ 987 static 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 1231 static 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 */ 1250 static 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 */ 1273 static 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 1311 out: 1312 return ret; 1313 } 1314 1315 static 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 else 1325 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 */ 1338 static 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 to 1355 * prove that we can communicate with the device. This works, which 1356 * confirms at we are communicating properly and that the device 1357 * 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 */ 1383 static int sd_init(struct gspca_dev *gspca_dev) 1384 { 1385 return 0; 1386 } 1387 1388 static 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 1409 static 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 1415 static 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 1436 static 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 1445 static 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 1463 static const struct v4l2_ctrl_ops sd_ctrl_ops = { 1464 .s_ctrl = sd_s_ctrl, 1465 }; 1466 1467 static 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 */ 1484 static 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 -- */ 1495 static 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 }; 1504 MODULE_DEVICE_TABLE(usb, device_table); 1505 1506 /* -- device connect -- */ 1507 static 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 1514 static 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_PM 1520 .suspend = gspca_suspend, 1521 .resume = gspca_resume, 1522 .reset_resume = gspca_resume, 1523 #endif 1524 }; 1525 1526 module_usb_driver(sd_driver); 1527