1/* 2 * SPCA508 chip based cameras subdriver 3 * 4 * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#define MODULE_NAME "spca508" 22 23#include "gspca.h" 24 25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 26MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver"); 27MODULE_LICENSE("GPL"); 28 29/* specific webcam descriptor */ 30struct sd { 31 struct gspca_dev gspca_dev; /* !! must be the first item */ 32 33 u8 brightness; 34 35 u8 subtype; 36#define CreativeVista 0 37#define HamaUSBSightcam 1 38#define HamaUSBSightcam2 2 39#define IntelEasyPCCamera 3 40#define MicroInnovationIC200 4 41#define ViewQuestVQ110 5 42}; 43 44/* V4L2 controls supported by the driver */ 45static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 46static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 47 48static const struct ctrl sd_ctrls[] = { 49 { 50 { 51 .id = V4L2_CID_BRIGHTNESS, 52 .type = V4L2_CTRL_TYPE_INTEGER, 53 .name = "Brightness", 54 .minimum = 0, 55 .maximum = 255, 56 .step = 1, 57#define BRIGHTNESS_DEF 128 58 .default_value = BRIGHTNESS_DEF, 59 }, 60 .set = sd_setbrightness, 61 .get = sd_getbrightness, 62 }, 63}; 64 65static const struct v4l2_pix_format sif_mode[] = { 66 {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, 67 .bytesperline = 160, 68 .sizeimage = 160 * 120 * 3 / 2, 69 .colorspace = V4L2_COLORSPACE_SRGB, 70 .priv = 3}, 71 {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, 72 .bytesperline = 176, 73 .sizeimage = 176 * 144 * 3 / 2, 74 .colorspace = V4L2_COLORSPACE_SRGB, 75 .priv = 2}, 76 {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, 77 .bytesperline = 320, 78 .sizeimage = 320 * 240 * 3 / 2, 79 .colorspace = V4L2_COLORSPACE_SRGB, 80 .priv = 1}, 81 {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, 82 .bytesperline = 352, 83 .sizeimage = 352 * 288 * 3 / 2, 84 .colorspace = V4L2_COLORSPACE_SRGB, 85 .priv = 0}, 86}; 87 88/* Frame packet header offsets for the spca508 */ 89#define SPCA508_OFFSET_DATA 37 90 91/* 92 * Initialization data: this is the first set-up data written to the 93 * device (before the open data). 94 */ 95static const u16 spca508_init_data[][2] = 96{ 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 u8 *data, /* isoc packet */ 1451 int len) /* iso packet length */ 1452{ 1453 switch (data[0]) { 1454 case 0: /* start of frame */ 1455 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 1456 data += SPCA508_OFFSET_DATA; 1457 len -= SPCA508_OFFSET_DATA; 1458 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); 1459 break; 1460 case 0xff: /* drop */ 1461 break; 1462 default: 1463 data += 1; 1464 len -= 1; 1465 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 1466 break; 1467 } 1468} 1469 1470static void setbrightness(struct gspca_dev *gspca_dev) 1471{ 1472 struct sd *sd = (struct sd *) gspca_dev; 1473 u8 brightness = sd->brightness; 1474 1475 /* MX seem contrast */ 1476 reg_write(gspca_dev->dev, 0x8651, brightness); 1477 reg_write(gspca_dev->dev, 0x8652, brightness); 1478 reg_write(gspca_dev->dev, 0x8653, brightness); 1479 reg_write(gspca_dev->dev, 0x8654, brightness); 1480} 1481 1482static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 1483{ 1484 struct sd *sd = (struct sd *) gspca_dev; 1485 1486 sd->brightness = val; 1487 if (gspca_dev->streaming) 1488 setbrightness(gspca_dev); 1489 return 0; 1490} 1491 1492static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 1493{ 1494 struct sd *sd = (struct sd *) gspca_dev; 1495 1496 *val = sd->brightness; 1497 return 0; 1498} 1499 1500/* sub-driver description */ 1501static const struct sd_desc sd_desc = { 1502 .name = MODULE_NAME, 1503 .ctrls = sd_ctrls, 1504 .nctrls = ARRAY_SIZE(sd_ctrls), 1505 .config = sd_config, 1506 .init = sd_init, 1507 .start = sd_start, 1508 .stopN = sd_stopN, 1509 .pkt_scan = sd_pkt_scan, 1510}; 1511 1512/* -- module initialisation -- */ 1513static const __devinitdata struct usb_device_id device_table[] = { 1514 {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, 1515 {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, 1516 {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, 1517 {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam}, 1518 {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, 1519 {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera}, 1520 {} 1521}; 1522MODULE_DEVICE_TABLE(usb, device_table); 1523 1524/* -- device connect -- */ 1525static int sd_probe(struct usb_interface *intf, 1526 const struct usb_device_id *id) 1527{ 1528 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1529 THIS_MODULE); 1530} 1531 1532static struct usb_driver sd_driver = { 1533 .name = MODULE_NAME, 1534 .id_table = device_table, 1535 .probe = sd_probe, 1536 .disconnect = gspca_disconnect, 1537#ifdef CONFIG_PM 1538 .suspend = gspca_suspend, 1539 .resume = gspca_resume, 1540#endif 1541}; 1542 1543/* -- module insert / remove -- */ 1544static int __init sd_mod_init(void) 1545{ 1546 int ret; 1547 1548 ret = usb_register(&sd_driver); 1549 if (ret < 0) 1550 return ret; 1551 PDEBUG(D_PROBE, "registered"); 1552 return 0; 1553} 1554static void __exit sd_mod_exit(void) 1555{ 1556 usb_deregister(&sd_driver); 1557 PDEBUG(D_PROBE, "deregistered"); 1558} 1559 1560module_init(sd_mod_init); 1561module_exit(sd_mod_exit); 1562