792 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SPCA505 chip based cameras initialization data4 *5 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>6 */7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9 10#define MODULE_NAME "spca505"11 12#include "gspca.h"13 14MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");15MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");16MODULE_LICENSE("GPL");17 18/* specific webcam descriptor */19struct sd {20 struct gspca_dev gspca_dev; /* !! must be the first item */21 22 u8 subtype;23#define IntelPCCameraPro 024#define Nxultra 125};26 27static const struct v4l2_pix_format vga_mode[] = {28 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,29 .bytesperline = 160,30 .sizeimage = 160 * 120 * 3 / 2,31 .colorspace = V4L2_COLORSPACE_SRGB,32 .priv = 4},33 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,34 .bytesperline = 176,35 .sizeimage = 176 * 144 * 3 / 2,36 .colorspace = V4L2_COLORSPACE_SRGB,37 .priv = 3},38 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,39 .bytesperline = 320,40 .sizeimage = 320 * 240 * 3 / 2,41 .colorspace = V4L2_COLORSPACE_SRGB,42 .priv = 2},43 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,44 .bytesperline = 352,45 .sizeimage = 352 * 288 * 3 / 2,46 .colorspace = V4L2_COLORSPACE_SRGB,47 .priv = 1},48 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,49 .bytesperline = 640,50 .sizeimage = 640 * 480 * 3 / 2,51 .colorspace = V4L2_COLORSPACE_SRGB,52 .priv = 0},53};54 55#define SPCA50X_OFFSET_DATA 1056 57#define SPCA50X_REG_USB 0x02 /* spca505 501 */58 59#define SPCA50X_USB_CTRL 0x00 /* spca505 */60#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */61 62#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */63#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */64#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */65 66#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */67#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */68#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */69 70/* Image format and compression control */71#define SPCA50X_REG_COMPRESS 0x0472 73/*74 * Data to initialize a SPCA505. Common to the CCD and external modes75 */76static const u8 spca505_init_data[][3] = {77 /* bmRequest,value,index */78 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},79 /* Sensor reset */80 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},81 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},82 /* Block USB reset */83 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},84 85 {0x05, 0x01, 0x10},86 /* Maybe power down some stuff */87 {0x05, 0x0f, 0x11},88 89 /* Setup internal CCD ? */90 {0x06, 0x10, 0x08},91 {0x06, 0x00, 0x09},92 {0x06, 0x00, 0x0a},93 {0x06, 0x00, 0x0b},94 {0x06, 0x10, 0x0c},95 {0x06, 0x00, 0x0d},96 {0x06, 0x00, 0x0e},97 {0x06, 0x00, 0x0f},98 {0x06, 0x10, 0x10},99 {0x06, 0x02, 0x11},100 {0x06, 0x00, 0x12},101 {0x06, 0x04, 0x13},102 {0x06, 0x02, 0x14},103 {0x06, 0x8a, 0x51},104 {0x06, 0x40, 0x52},105 {0x06, 0xb6, 0x53},106 {0x06, 0x3d, 0x54},107 {}108};109 110/*111 * Data to initialize the camera using the internal CCD112 */113static const u8 spca505_open_data_ccd[][3] = {114 /* bmRequest,value,index */115 /* Internal CCD data set */116 {0x03, 0x04, 0x01},117 /* This could be a reset */118 {0x03, 0x00, 0x01},119 120 /* Setup compression and image registers. 0x6 and 0x7 seem to be121 related to H&V hold, and are resolution mode specific */122 {0x04, 0x10, 0x01},123 /* DIFF(0x50), was (0x10) */124 {0x04, 0x00, 0x04},125 {0x04, 0x00, 0x05},126 {0x04, 0x20, 0x06},127 {0x04, 0x20, 0x07},128 129 {0x08, 0x0a, 0x00},130 /* DIFF (0x4a), was (0xa) */131 132 {0x05, 0x00, 0x10},133 {0x05, 0x00, 0x11},134 {0x05, 0x00, 0x00},135 /* DIFF not written */136 {0x05, 0x00, 0x01},137 /* DIFF not written */138 {0x05, 0x00, 0x02},139 /* DIFF not written */140 {0x05, 0x00, 0x03},141 /* DIFF not written */142 {0x05, 0x00, 0x04},143 /* DIFF not written */144 {0x05, 0x80, 0x05},145 /* DIFF not written */146 {0x05, 0xe0, 0x06},147 /* DIFF not written */148 {0x05, 0x20, 0x07},149 /* DIFF not written */150 {0x05, 0xa0, 0x08},151 /* DIFF not written */152 {0x05, 0x0, 0x12},153 /* DIFF not written */154 {0x05, 0x02, 0x0f},155 /* DIFF not written */156 {0x05, 0x10, 0x46},157 /* DIFF not written */158 {0x05, 0x8, 0x4a},159 /* DIFF not written */160 161 {0x03, 0x08, 0x03},162 /* DIFF (0x3,0x28,0x3) */163 {0x03, 0x08, 0x01},164 {0x03, 0x0c, 0x03},165 /* DIFF not written */166 {0x03, 0x21, 0x00},167 /* DIFF (0x39) */168 169/* Extra block copied from init to hopefully ensure CCD is in a sane state */170 {0x06, 0x10, 0x08},171 {0x06, 0x00, 0x09},172 {0x06, 0x00, 0x0a},173 {0x06, 0x00, 0x0b},174 {0x06, 0x10, 0x0c},175 {0x06, 0x00, 0x0d},176 {0x06, 0x00, 0x0e},177 {0x06, 0x00, 0x0f},178 {0x06, 0x10, 0x10},179 {0x06, 0x02, 0x11},180 {0x06, 0x00, 0x12},181 {0x06, 0x04, 0x13},182 {0x06, 0x02, 0x14},183 {0x06, 0x8a, 0x51},184 {0x06, 0x40, 0x52},185 {0x06, 0xb6, 0x53},186 {0x06, 0x3d, 0x54},187 /* End of extra block */188 189 {0x06, 0x3f, 0x1},190 /* Block skipped */191 {0x06, 0x10, 0x02},192 {0x06, 0x64, 0x07},193 {0x06, 0x10, 0x08},194 {0x06, 0x00, 0x09},195 {0x06, 0x00, 0x0a},196 {0x06, 0x00, 0x0b},197 {0x06, 0x10, 0x0c},198 {0x06, 0x00, 0x0d},199 {0x06, 0x00, 0x0e},200 {0x06, 0x00, 0x0f},201 {0x06, 0x10, 0x10},202 {0x06, 0x02, 0x11},203 {0x06, 0x00, 0x12},204 {0x06, 0x04, 0x13},205 {0x06, 0x02, 0x14},206 {0x06, 0x8a, 0x51},207 {0x06, 0x40, 0x52},208 {0x06, 0xb6, 0x53},209 {0x06, 0x3d, 0x54},210 {0x06, 0x60, 0x57},211 {0x06, 0x20, 0x58},212 {0x06, 0x15, 0x59},213 {0x06, 0x05, 0x5a},214 215 {0x05, 0x01, 0xc0},216 {0x05, 0x10, 0xcb},217 {0x05, 0x80, 0xc1},218 /* */219 {0x05, 0x0, 0xc2},220 /* 4 was 0 */221 {0x05, 0x00, 0xca},222 {0x05, 0x80, 0xc1},223 /* */224 {0x05, 0x04, 0xc2},225 {0x05, 0x00, 0xca},226 {0x05, 0x0, 0xc1},227 /* */228 {0x05, 0x00, 0xc2},229 {0x05, 0x00, 0xca},230 {0x05, 0x40, 0xc1},231 /* */232 {0x05, 0x17, 0xc2},233 {0x05, 0x00, 0xca},234 {0x05, 0x80, 0xc1},235 /* */236 {0x05, 0x06, 0xc2},237 {0x05, 0x00, 0xca},238 {0x05, 0x80, 0xc1},239 /* */240 {0x05, 0x04, 0xc2},241 {0x05, 0x00, 0xca},242 243 {0x03, 0x4c, 0x3},244 {0x03, 0x18, 0x1},245 246 {0x06, 0x70, 0x51},247 {0x06, 0xbe, 0x53},248 {0x06, 0x71, 0x57},249 {0x06, 0x20, 0x58},250 {0x06, 0x05, 0x59},251 {0x06, 0x15, 0x5a},252 253 {0x04, 0x00, 0x08},254 /* Compress = OFF (0x1 to turn on) */255 {0x04, 0x12, 0x09},256 {0x04, 0x21, 0x0a},257 {0x04, 0x10, 0x0b},258 {0x04, 0x21, 0x0c},259 {0x04, 0x05, 0x00},260 /* was 5 (Image Type ? ) */261 {0x04, 0x00, 0x01},262 263 {0x06, 0x3f, 0x01},264 265 {0x04, 0x00, 0x04},266 {0x04, 0x00, 0x05},267 {0x04, 0x40, 0x06},268 {0x04, 0x40, 0x07},269 270 {0x06, 0x1c, 0x17},271 {0x06, 0xe2, 0x19},272 {0x06, 0x1c, 0x1b},273 {0x06, 0xe2, 0x1d},274 {0x06, 0xaa, 0x1f},275 {0x06, 0x70, 0x20},276 277 {0x05, 0x01, 0x10},278 {0x05, 0x00, 0x11},279 {0x05, 0x01, 0x00},280 {0x05, 0x05, 0x01},281 {0x05, 0x00, 0xc1},282 /* */283 {0x05, 0x00, 0xc2},284 {0x05, 0x00, 0xca},285 286 {0x06, 0x70, 0x51},287 {0x06, 0xbe, 0x53},288 {}289};290 291/*292 * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)293 * SPCA505b chip based cameras initialization data294 */295/* jfm */296#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */297/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */298/*299 * Data to initialize a SPCA505. Common to the CCD and external modes300 */301static const u8 spca505b_init_data[][3] = {302/* start */303 {0x02, 0x00, 0x00}, /* init */304 {0x02, 0x00, 0x01},305 {0x02, 0x00, 0x02},306 {0x02, 0x00, 0x03},307 {0x02, 0x00, 0x04},308 {0x02, 0x00, 0x05},309 {0x02, 0x00, 0x06},310 {0x02, 0x00, 0x07},311 {0x02, 0x00, 0x08},312 {0x02, 0x00, 0x09},313 {0x03, 0x00, 0x00},314 {0x03, 0x00, 0x01},315 {0x03, 0x00, 0x02},316 {0x03, 0x00, 0x03},317 {0x03, 0x00, 0x04},318 {0x03, 0x00, 0x05},319 {0x03, 0x00, 0x06},320 {0x04, 0x00, 0x00},321 {0x04, 0x00, 0x02},322 {0x04, 0x00, 0x04},323 {0x04, 0x00, 0x05},324 {0x04, 0x00, 0x06},325 {0x04, 0x00, 0x07},326 {0x04, 0x00, 0x08},327 {0x04, 0x00, 0x09},328 {0x04, 0x00, 0x0a},329 {0x04, 0x00, 0x0b},330 {0x04, 0x00, 0x0c},331 {0x07, 0x00, 0x00},332 {0x07, 0x00, 0x03},333 {0x08, 0x00, 0x00},334 {0x08, 0x00, 0x01},335 {0x08, 0x00, 0x02},336 {0x06, 0x18, 0x08},337 {0x06, 0xfc, 0x09},338 {0x06, 0xfc, 0x0a},339 {0x06, 0xfc, 0x0b},340 {0x06, 0x18, 0x0c},341 {0x06, 0xfc, 0x0d},342 {0x06, 0xfc, 0x0e},343 {0x06, 0xfc, 0x0f},344 {0x06, 0x18, 0x10},345 {0x06, 0xfe, 0x12},346 {0x06, 0x00, 0x11},347 {0x06, 0x00, 0x14},348 {0x06, 0x00, 0x13},349 {0x06, 0x28, 0x51},350 {0x06, 0xff, 0x53},351 {0x02, 0x00, 0x08},352 353 {0x03, 0x00, 0x03},354 {0x03, 0x10, 0x03},355 {}356};357 358/*359 * Data to initialize the camera using the internal CCD360 */361static const u8 spca505b_open_data_ccd[][3] = {362 363/* {0x02,0x00,0x00}, */364 {0x03, 0x04, 0x01}, /* rst */365 {0x03, 0x00, 0x01},366 {0x03, 0x00, 0x00},367 {0x03, 0x21, 0x00},368 {0x03, 0x00, 0x04},369 {0x03, 0x00, 0x03},370 {0x03, 0x18, 0x03},371 {0x03, 0x08, 0x01},372 {0x03, 0x1c, 0x03},373 {0x03, 0x5c, 0x03},374 {0x03, 0x5c, 0x03},375 {0x03, 0x18, 0x01},376 377/* same as 505 */378 {0x04, 0x10, 0x01},379 {0x04, 0x00, 0x04},380 {0x04, 0x00, 0x05},381 {0x04, 0x20, 0x06},382 {0x04, 0x20, 0x07},383 384 {0x08, 0x0a, 0x00},385 386 {0x05, 0x00, 0x10},387 {0x05, 0x00, 0x11},388 {0x05, 0x00, 0x12},389 {0x05, 0x6f, 0x00},390 {0x05, initial_brightness >> 6, 0x00},391 {0x05, (initial_brightness << 2) & 0xff, 0x01},392 {0x05, 0x00, 0x02},393 {0x05, 0x01, 0x03},394 {0x05, 0x00, 0x04},395 {0x05, 0x03, 0x05},396 {0x05, 0xe0, 0x06},397 {0x05, 0x20, 0x07},398 {0x05, 0xa0, 0x08},399 {0x05, 0x00, 0x12},400 {0x05, 0x02, 0x0f},401 {0x05, 0x80, 0x14}, /* max exposure off (0=on) */402 {0x05, 0x01, 0xb0},403 {0x05, 0x01, 0xbf},404 {0x03, 0x02, 0x06},405 {0x05, 0x10, 0x46},406 {0x05, 0x08, 0x4a},407 408 {0x06, 0x00, 0x01},409 {0x06, 0x10, 0x02},410 {0x06, 0x64, 0x07},411 {0x06, 0x18, 0x08},412 {0x06, 0xfc, 0x09},413 {0x06, 0xfc, 0x0a},414 {0x06, 0xfc, 0x0b},415 {0x04, 0x00, 0x01},416 {0x06, 0x18, 0x0c},417 {0x06, 0xfc, 0x0d},418 {0x06, 0xfc, 0x0e},419 {0x06, 0xfc, 0x0f},420 {0x06, 0x11, 0x10}, /* contrast */421 {0x06, 0x00, 0x11},422 {0x06, 0xfe, 0x12},423 {0x06, 0x00, 0x13},424 {0x06, 0x00, 0x14},425 {0x06, 0x9d, 0x51},426 {0x06, 0x40, 0x52},427 {0x06, 0x7c, 0x53},428 {0x06, 0x40, 0x54},429 {0x06, 0x02, 0x57},430 {0x06, 0x03, 0x58},431 {0x06, 0x15, 0x59},432 {0x06, 0x05, 0x5a},433 {0x06, 0x03, 0x56},434 {0x06, 0x02, 0x3f},435 {0x06, 0x00, 0x40},436 {0x06, 0x39, 0x41},437 {0x06, 0x69, 0x42},438 {0x06, 0x87, 0x43},439 {0x06, 0x9e, 0x44},440 {0x06, 0xb1, 0x45},441 {0x06, 0xbf, 0x46},442 {0x06, 0xcc, 0x47},443 {0x06, 0xd5, 0x48},444 {0x06, 0xdd, 0x49},445 {0x06, 0xe3, 0x4a},446 {0x06, 0xe8, 0x4b},447 {0x06, 0xed, 0x4c},448 {0x06, 0xf2, 0x4d},449 {0x06, 0xf7, 0x4e},450 {0x06, 0xfc, 0x4f},451 {0x06, 0xff, 0x50},452 453 {0x05, 0x01, 0xc0},454 {0x05, 0x10, 0xcb},455 {0x05, 0x40, 0xc1},456 {0x05, 0x04, 0xc2},457 {0x05, 0x00, 0xca},458 {0x05, 0x40, 0xc1},459 {0x05, 0x09, 0xc2},460 {0x05, 0x00, 0xca},461 {0x05, 0xc0, 0xc1},462 {0x05, 0x09, 0xc2},463 {0x05, 0x00, 0xca},464 {0x05, 0x40, 0xc1},465 {0x05, 0x59, 0xc2},466 {0x05, 0x00, 0xca},467 {0x04, 0x00, 0x01},468 {0x05, 0x80, 0xc1},469 {0x05, 0xec, 0xc2},470 {0x05, 0x0, 0xca},471 472 {0x06, 0x02, 0x57},473 {0x06, 0x01, 0x58},474 {0x06, 0x15, 0x59},475 {0x06, 0x0a, 0x5a},476 {0x06, 0x01, 0x57},477 {0x06, 0x8a, 0x03},478 {0x06, 0x0a, 0x6c},479 {0x06, 0x30, 0x01},480 {0x06, 0x20, 0x02},481 {0x06, 0x00, 0x03},482 483 {0x05, 0x8c, 0x25},484 485 {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */486 {0x06, 0x84, 0x53}, /* making green (84) */487 {0x06, 0x00, 0x57}, /* sharpness (1) */488 {0x06, 0x18, 0x08},489 {0x06, 0xfc, 0x09},490 {0x06, 0xfc, 0x0a},491 {0x06, 0xfc, 0x0b},492 {0x06, 0x18, 0x0c}, /* maybe hue (18) */493 {0x06, 0xfc, 0x0d},494 {0x06, 0xfc, 0x0e},495 {0x06, 0xfc, 0x0f},496 {0x06, 0x18, 0x10}, /* maybe contrast (18) */497 498 {0x05, 0x01, 0x02},499 500 {0x04, 0x00, 0x08}, /* compression */501 {0x04, 0x12, 0x09},502 {0x04, 0x21, 0x0a},503 {0x04, 0x10, 0x0b},504 {0x04, 0x21, 0x0c},505 {0x04, 0x1d, 0x00}, /* imagetype (1d) */506 {0x04, 0x41, 0x01}, /* hardware snapcontrol */507 508 {0x04, 0x00, 0x04},509 {0x04, 0x00, 0x05},510 {0x04, 0x10, 0x06},511 {0x04, 0x10, 0x07},512 {0x04, 0x40, 0x06},513 {0x04, 0x40, 0x07},514 {0x04, 0x00, 0x04},515 {0x04, 0x00, 0x05},516 517 {0x06, 0x1c, 0x17},518 {0x06, 0xe2, 0x19},519 {0x06, 0x1c, 0x1b},520 {0x06, 0xe2, 0x1d},521 {0x06, 0x5f, 0x1f},522 {0x06, 0x32, 0x20},523 524 {0x05, initial_brightness >> 6, 0x00},525 {0x05, (initial_brightness << 2) & 0xff, 0x01},526 {0x05, 0x06, 0xc1},527 {0x05, 0x58, 0xc2},528 {0x05, 0x00, 0xca},529 {0x05, 0x00, 0x11},530 {}531};532 533static int reg_write(struct gspca_dev *gspca_dev,534 u16 req, u16 index, u16 value)535{536 int ret;537 struct usb_device *dev = gspca_dev->dev;538 539 ret = usb_control_msg(dev,540 usb_sndctrlpipe(dev, 0),541 req,542 USB_TYPE_VENDOR | USB_RECIP_DEVICE,543 value, index, NULL, 0, 500);544 gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",545 req, index, value, ret);546 if (ret < 0)547 pr_err("reg write: error %d\n", ret);548 return ret;549}550 551/* returns: negative is error, pos or zero is data */552static int reg_read(struct gspca_dev *gspca_dev,553 u16 req, /* bRequest */554 u16 index) /* wIndex */555{556 int ret;557 558 ret = usb_control_msg(gspca_dev->dev,559 usb_rcvctrlpipe(gspca_dev->dev, 0),560 req,561 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,562 0, /* value */563 index,564 gspca_dev->usb_buf, 2,565 500); /* timeout */566 if (ret < 0)567 return ret;568 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];569}570 571static int write_vector(struct gspca_dev *gspca_dev,572 const u8 data[][3])573{574 int ret, i = 0;575 576 while (data[i][0] != 0) {577 ret = reg_write(gspca_dev, data[i][0], data[i][2],578 data[i][1]);579 if (ret < 0)580 return ret;581 i++;582 }583 return 0;584}585 586/* this function is called at probe time */587static int sd_config(struct gspca_dev *gspca_dev,588 const struct usb_device_id *id)589{590 struct sd *sd = (struct sd *) gspca_dev;591 struct cam *cam;592 593 cam = &gspca_dev->cam;594 cam->cam_mode = vga_mode;595 sd->subtype = id->driver_info;596 if (sd->subtype != IntelPCCameraPro)597 cam->nmodes = ARRAY_SIZE(vga_mode);598 else /* no 640x480 for IntelPCCameraPro */599 cam->nmodes = ARRAY_SIZE(vga_mode) - 1;600 601 return 0;602}603 604/* this function is called at probe and resume time */605static int sd_init(struct gspca_dev *gspca_dev)606{607 struct sd *sd = (struct sd *) gspca_dev;608 609 if (write_vector(gspca_dev,610 sd->subtype == Nxultra611 ? spca505b_init_data612 : spca505_init_data))613 return -EIO;614 return 0;615}616 617static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)618{619 reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);620 reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);621}622 623static int sd_start(struct gspca_dev *gspca_dev)624{625 struct sd *sd = (struct sd *) gspca_dev;626 int ret, mode;627 static u8 mode_tb[][3] = {628 /* r00 r06 r07 */629 {0x00, 0x10, 0x10}, /* 640x480 */630 {0x01, 0x1a, 0x1a}, /* 352x288 */631 {0x02, 0x1c, 0x1d}, /* 320x240 */632 {0x04, 0x34, 0x34}, /* 176x144 */633 {0x05, 0x40, 0x40} /* 160x120 */634 };635 636 if (sd->subtype == Nxultra)637 write_vector(gspca_dev, spca505b_open_data_ccd);638 else639 write_vector(gspca_dev, spca505_open_data_ccd);640 ret = reg_read(gspca_dev, 0x06, 0x16);641 642 if (ret < 0) {643 gspca_err(gspca_dev, "register read failed err: %d\n", ret);644 return ret;645 }646 if (ret != 0x0101) {647 pr_err("After vector read returns 0x%04x should be 0x0101\n",648 ret);649 }650 651 ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);652 if (ret < 0)653 return ret;654 reg_write(gspca_dev, 0x05, 0xc2, 0x12);655 656 /* necessary because without it we can see stream657 * only once after loading module */658 /* stopping usb registers Tomasz change */659 reg_write(gspca_dev, 0x02, 0x00, 0x00);660 661 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;662 reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);663 reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);664 reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);665 666 return reg_write(gspca_dev, SPCA50X_REG_USB,667 SPCA50X_USB_CTRL,668 SPCA50X_CUSB_ENABLE);669}670 671static void sd_stopN(struct gspca_dev *gspca_dev)672{673 /* Disable ISO packet machine */674 reg_write(gspca_dev, 0x02, 0x00, 0x00);675}676 677/* called on streamoff with alt 0 and on disconnect */678static void sd_stop0(struct gspca_dev *gspca_dev)679{680 if (!gspca_dev->present)681 return;682 683 /* This maybe reset or power control */684 reg_write(gspca_dev, 0x03, 0x03, 0x20);685 reg_write(gspca_dev, 0x03, 0x01, 0x00);686 reg_write(gspca_dev, 0x03, 0x00, 0x01);687 reg_write(gspca_dev, 0x05, 0x10, 0x01);688 reg_write(gspca_dev, 0x05, 0x11, 0x0f);689}690 691static void sd_pkt_scan(struct gspca_dev *gspca_dev,692 u8 *data, /* isoc packet */693 int len) /* iso packet length */694{695 switch (data[0]) {696 case 0: /* start of frame */697 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);698 data += SPCA50X_OFFSET_DATA;699 len -= SPCA50X_OFFSET_DATA;700 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);701 break;702 case 0xff: /* drop */703 break;704 default:705 data += 1;706 len -= 1;707 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);708 break;709 }710}711 712static int sd_s_ctrl(struct v4l2_ctrl *ctrl)713{714 struct gspca_dev *gspca_dev =715 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);716 717 gspca_dev->usb_err = 0;718 719 if (!gspca_dev->streaming)720 return 0;721 722 switch (ctrl->id) {723 case V4L2_CID_BRIGHTNESS:724 setbrightness(gspca_dev, ctrl->val);725 break;726 }727 return gspca_dev->usb_err;728}729 730static const struct v4l2_ctrl_ops sd_ctrl_ops = {731 .s_ctrl = sd_s_ctrl,732};733 734static int sd_init_controls(struct gspca_dev *gspca_dev)735{736 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;737 738 gspca_dev->vdev.ctrl_handler = hdl;739 v4l2_ctrl_handler_init(hdl, 5);740 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,741 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);742 743 if (hdl->error) {744 pr_err("Could not initialize controls\n");745 return hdl->error;746 }747 return 0;748}749 750/* sub-driver description */751static const struct sd_desc sd_desc = {752 .name = MODULE_NAME,753 .config = sd_config,754 .init_controls = sd_init_controls,755 .init = sd_init,756 .start = sd_start,757 .stopN = sd_stopN,758 .stop0 = sd_stop0,759 .pkt_scan = sd_pkt_scan,760};761 762/* -- module initialisation -- */763static const struct usb_device_id device_table[] = {764 {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},765 {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},766/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */767 {}768};769MODULE_DEVICE_TABLE(usb, device_table);770 771/* -- device connect -- */772static int sd_probe(struct usb_interface *intf,773 const struct usb_device_id *id)774{775 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),776 THIS_MODULE);777}778 779static struct usb_driver sd_driver = {780 .name = MODULE_NAME,781 .id_table = device_table,782 .probe = sd_probe,783 .disconnect = gspca_disconnect,784#ifdef CONFIG_PM785 .suspend = gspca_suspend,786 .resume = gspca_resume,787 .reset_resume = gspca_resume,788#endif789};790 791module_usb_driver(sd_driver);792