1 /* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip 2 * Subdriver core 3 * 4 * 2009/09/24 Olivier Lorin <o.lorin@laposte.net> 5 * GSPCA by Jean-Francois Moine <http://moinejf.free.fr> 6 * Thanks BUGabundo and Malmostoso for your amazing help! 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23 24 #include "gspca.h" 25 #include "gl860.h" 26 27 MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>"); 28 MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver"); 29 MODULE_LICENSE("GPL"); 30 31 /*======================== static function declarations ====================*/ 32 33 static void (*dev_init_settings)(struct gspca_dev *gspca_dev); 34 35 static int sd_config(struct gspca_dev *gspca_dev, 36 const struct usb_device_id *id); 37 static int sd_init(struct gspca_dev *gspca_dev); 38 static int sd_isoc_init(struct gspca_dev *gspca_dev); 39 static int sd_start(struct gspca_dev *gspca_dev); 40 static void sd_stop0(struct gspca_dev *gspca_dev); 41 static void sd_pkt_scan(struct gspca_dev *gspca_dev, 42 u8 *data, int len); 43 static void sd_callback(struct gspca_dev *gspca_dev); 44 45 static int gl860_guess_sensor(struct gspca_dev *gspca_dev, 46 u16 vendor_id, u16 product_id); 47 48 /*============================ driver options ==============================*/ 49 50 static s32 AC50Hz = 0xff; 51 module_param(AC50Hz, int, 0644); 52 MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)"); 53 54 static char sensor[7]; 55 module_param_string(sensor, sensor, sizeof(sensor), 0644); 56 MODULE_PARM_DESC(sensor, 57 " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')"); 58 59 /*============================ webcam controls =============================*/ 60 61 /* Functions to get and set a control value */ 62 #define SD_SETGET(thename) \ 63 static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\ 64 {\ 65 struct sd *sd = (struct sd *) gspca_dev;\ 66 \ 67 sd->vcur.thename = val;\ 68 if (gspca_dev->streaming)\ 69 sd->waitSet = 1;\ 70 return 0;\ 71 } \ 72 static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\ 73 {\ 74 struct sd *sd = (struct sd *) gspca_dev;\ 75 \ 76 *val = sd->vcur.thename;\ 77 return 0;\ 78 } 79 80 SD_SETGET(mirror) 81 SD_SETGET(flip) 82 SD_SETGET(AC50Hz) 83 SD_SETGET(backlight) 84 SD_SETGET(brightness) 85 SD_SETGET(gamma) 86 SD_SETGET(hue) 87 SD_SETGET(saturation) 88 SD_SETGET(sharpness) 89 SD_SETGET(whitebal) 90 SD_SETGET(contrast) 91 92 #define GL860_NCTRLS 11 93 94 /* control table */ 95 static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; 96 static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; 97 static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; 98 static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS]; 99 100 #define SET_MY_CTRL(theid, \ 101 thetype, thelabel, thename) \ 102 if (sd->vmax.thename != 0) {\ 103 sd_ctrls[nCtrls].qctrl.id = theid;\ 104 sd_ctrls[nCtrls].qctrl.type = thetype;\ 105 strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\ 106 sd_ctrls[nCtrls].qctrl.minimum = 0;\ 107 sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\ 108 sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\ 109 sd_ctrls[nCtrls].qctrl.step = \ 110 (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\ 111 sd_ctrls[nCtrls].set = sd_set_##thename;\ 112 sd_ctrls[nCtrls].get = sd_get_##thename;\ 113 nCtrls++;\ 114 } 115 116 static int gl860_build_control_table(struct gspca_dev *gspca_dev) 117 { 118 struct sd *sd = (struct sd *) gspca_dev; 119 struct ctrl *sd_ctrls; 120 int nCtrls = 0; 121 122 if (_MI1320_) 123 sd_ctrls = sd_ctrls_mi1320; 124 else if (_MI2020_) 125 sd_ctrls = sd_ctrls_mi2020; 126 else if (_OV2640_) 127 sd_ctrls = sd_ctrls_ov2640; 128 else if (_OV9655_) 129 sd_ctrls = sd_ctrls_ov9655; 130 else 131 return 0; 132 133 memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl)); 134 135 SET_MY_CTRL(V4L2_CID_BRIGHTNESS, 136 V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness) 137 SET_MY_CTRL(V4L2_CID_SHARPNESS, 138 V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness) 139 SET_MY_CTRL(V4L2_CID_CONTRAST, 140 V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast) 141 SET_MY_CTRL(V4L2_CID_GAMMA, 142 V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma) 143 SET_MY_CTRL(V4L2_CID_HUE, 144 V4L2_CTRL_TYPE_INTEGER, "Palette", hue) 145 SET_MY_CTRL(V4L2_CID_SATURATION, 146 V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation) 147 SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE, 148 V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal) 149 SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION, 150 V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight) 151 152 SET_MY_CTRL(V4L2_CID_HFLIP, 153 V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror) 154 SET_MY_CTRL(V4L2_CID_VFLIP, 155 V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) 156 SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, 157 V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz) 158 159 return nCtrls; 160 } 161 162 /*==================== sud-driver structure initialisation =================*/ 163 164 static const struct sd_desc sd_desc_mi1320 = { 165 .name = MODULE_NAME, 166 .ctrls = sd_ctrls_mi1320, 167 .nctrls = GL860_NCTRLS, 168 .config = sd_config, 169 .init = sd_init, 170 .isoc_init = sd_isoc_init, 171 .start = sd_start, 172 .stop0 = sd_stop0, 173 .pkt_scan = sd_pkt_scan, 174 .dq_callback = sd_callback, 175 }; 176 177 static const struct sd_desc sd_desc_mi2020 = { 178 .name = MODULE_NAME, 179 .ctrls = sd_ctrls_mi2020, 180 .nctrls = GL860_NCTRLS, 181 .config = sd_config, 182 .init = sd_init, 183 .isoc_init = sd_isoc_init, 184 .start = sd_start, 185 .stop0 = sd_stop0, 186 .pkt_scan = sd_pkt_scan, 187 .dq_callback = sd_callback, 188 }; 189 190 static const struct sd_desc sd_desc_ov2640 = { 191 .name = MODULE_NAME, 192 .ctrls = sd_ctrls_ov2640, 193 .nctrls = GL860_NCTRLS, 194 .config = sd_config, 195 .init = sd_init, 196 .isoc_init = sd_isoc_init, 197 .start = sd_start, 198 .stop0 = sd_stop0, 199 .pkt_scan = sd_pkt_scan, 200 .dq_callback = sd_callback, 201 }; 202 203 static const struct sd_desc sd_desc_ov9655 = { 204 .name = MODULE_NAME, 205 .ctrls = sd_ctrls_ov9655, 206 .nctrls = GL860_NCTRLS, 207 .config = sd_config, 208 .init = sd_init, 209 .isoc_init = sd_isoc_init, 210 .start = sd_start, 211 .stop0 = sd_stop0, 212 .pkt_scan = sd_pkt_scan, 213 .dq_callback = sd_callback, 214 }; 215 216 /*=========================== sub-driver image sizes =======================*/ 217 218 static struct v4l2_pix_format mi2020_mode[] = { 219 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 220 .bytesperline = 640, 221 .sizeimage = 640 * 480, 222 .colorspace = V4L2_COLORSPACE_SRGB, 223 .priv = 0 224 }, 225 { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 226 .bytesperline = 800, 227 .sizeimage = 800 * 598, 228 .colorspace = V4L2_COLORSPACE_SRGB, 229 .priv = 1 230 }, 231 {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 232 .bytesperline = 1280, 233 .sizeimage = 1280 * 1024, 234 .colorspace = V4L2_COLORSPACE_SRGB, 235 .priv = 2 236 }, 237 {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 238 .bytesperline = 1600, 239 .sizeimage = 1600 * 1198, 240 .colorspace = V4L2_COLORSPACE_SRGB, 241 .priv = 3 242 }, 243 }; 244 245 static struct v4l2_pix_format ov2640_mode[] = { 246 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 247 .bytesperline = 640, 248 .sizeimage = 640 * 480, 249 .colorspace = V4L2_COLORSPACE_SRGB, 250 .priv = 0 251 }, 252 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 253 .bytesperline = 800, 254 .sizeimage = 800 * 600, 255 .colorspace = V4L2_COLORSPACE_SRGB, 256 .priv = 1 257 }, 258 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 259 .bytesperline = 1280, 260 .sizeimage = 1280 * 960, 261 .colorspace = V4L2_COLORSPACE_SRGB, 262 .priv = 2 263 }, 264 {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 265 .bytesperline = 1600, 266 .sizeimage = 1600 * 1200, 267 .colorspace = V4L2_COLORSPACE_SRGB, 268 .priv = 3 269 }, 270 }; 271 272 static struct v4l2_pix_format mi1320_mode[] = { 273 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 274 .bytesperline = 640, 275 .sizeimage = 640 * 480, 276 .colorspace = V4L2_COLORSPACE_SRGB, 277 .priv = 0 278 }, 279 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 280 .bytesperline = 800, 281 .sizeimage = 800 * 600, 282 .colorspace = V4L2_COLORSPACE_SRGB, 283 .priv = 1 284 }, 285 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 286 .bytesperline = 1280, 287 .sizeimage = 1280 * 960, 288 .colorspace = V4L2_COLORSPACE_SRGB, 289 .priv = 2 290 }, 291 }; 292 293 static struct v4l2_pix_format ov9655_mode[] = { 294 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 295 .bytesperline = 640, 296 .sizeimage = 640 * 480, 297 .colorspace = V4L2_COLORSPACE_SRGB, 298 .priv = 0 299 }, 300 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 301 .bytesperline = 1280, 302 .sizeimage = 1280 * 960, 303 .colorspace = V4L2_COLORSPACE_SRGB, 304 .priv = 1 305 }, 306 }; 307 308 /*========================= sud-driver functions ===========================*/ 309 310 /* This function is called at probe time */ 311 static int sd_config(struct gspca_dev *gspca_dev, 312 const struct usb_device_id *id) 313 { 314 struct sd *sd = (struct sd *) gspca_dev; 315 struct cam *cam; 316 u16 vendor_id, product_id; 317 318 /* Get USB VendorID and ProductID */ 319 vendor_id = id->idVendor; 320 product_id = id->idProduct; 321 322 sd->nbRightUp = 1; 323 sd->nbIm = -1; 324 325 sd->sensor = 0xff; 326 if (strcmp(sensor, "MI1320") == 0) 327 sd->sensor = ID_MI1320; 328 else if (strcmp(sensor, "OV2640") == 0) 329 sd->sensor = ID_OV2640; 330 else if (strcmp(sensor, "OV9655") == 0) 331 sd->sensor = ID_OV9655; 332 else if (strcmp(sensor, "MI2020") == 0) 333 sd->sensor = ID_MI2020; 334 335 /* Get sensor and set the suitable init/start/../stop functions */ 336 if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1) 337 return -1; 338 339 cam = &gspca_dev->cam; 340 341 switch (sd->sensor) { 342 case ID_MI1320: 343 gspca_dev->sd_desc = &sd_desc_mi1320; 344 cam->cam_mode = mi1320_mode; 345 cam->nmodes = ARRAY_SIZE(mi1320_mode); 346 dev_init_settings = mi1320_init_settings; 347 break; 348 349 case ID_MI2020: 350 gspca_dev->sd_desc = &sd_desc_mi2020; 351 cam->cam_mode = mi2020_mode; 352 cam->nmodes = ARRAY_SIZE(mi2020_mode); 353 dev_init_settings = mi2020_init_settings; 354 break; 355 356 case ID_OV2640: 357 gspca_dev->sd_desc = &sd_desc_ov2640; 358 cam->cam_mode = ov2640_mode; 359 cam->nmodes = ARRAY_SIZE(ov2640_mode); 360 dev_init_settings = ov2640_init_settings; 361 break; 362 363 case ID_OV9655: 364 gspca_dev->sd_desc = &sd_desc_ov9655; 365 cam->cam_mode = ov9655_mode; 366 cam->nmodes = ARRAY_SIZE(ov9655_mode); 367 dev_init_settings = ov9655_init_settings; 368 break; 369 } 370 371 dev_init_settings(gspca_dev); 372 if (AC50Hz != 0xff) 373 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz; 374 gl860_build_control_table(gspca_dev); 375 376 return 0; 377 } 378 379 /* This function is called at probe time after sd_config */ 380 static int sd_init(struct gspca_dev *gspca_dev) 381 { 382 struct sd *sd = (struct sd *) gspca_dev; 383 384 return sd->dev_init_at_startup(gspca_dev); 385 } 386 387 /* This function is called before to choose the alt setting */ 388 static int sd_isoc_init(struct gspca_dev *gspca_dev) 389 { 390 struct sd *sd = (struct sd *) gspca_dev; 391 392 return sd->dev_configure_alt(gspca_dev); 393 } 394 395 /* This function is called to start the webcam */ 396 static int sd_start(struct gspca_dev *gspca_dev) 397 { 398 struct sd *sd = (struct sd *) gspca_dev; 399 400 return sd->dev_init_pre_alt(gspca_dev); 401 } 402 403 /* This function is called to stop the webcam */ 404 static void sd_stop0(struct gspca_dev *gspca_dev) 405 { 406 struct sd *sd = (struct sd *) gspca_dev; 407 408 if (!sd->gspca_dev.present) 409 return; 410 411 return sd->dev_post_unset_alt(gspca_dev); 412 } 413 414 /* This function is called when an image is being received */ 415 static void sd_pkt_scan(struct gspca_dev *gspca_dev, 416 u8 *data, int len) 417 { 418 struct sd *sd = (struct sd *) gspca_dev; 419 static s32 nSkipped; 420 421 s32 mode = (s32) gspca_dev->curr_mode; 422 s32 nToSkip = 423 sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1); 424 425 /* Test only against 0202h, so endianess does not matter */ 426 switch (*(s16 *) data) { 427 case 0x0202: /* End of frame, start a new one */ 428 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 429 nSkipped = 0; 430 if (sd->nbIm >= 0 && sd->nbIm < 10) 431 sd->nbIm++; 432 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); 433 break; 434 435 default: 436 data += 2; 437 len -= 2; 438 if (nSkipped + len <= nToSkip) 439 nSkipped += len; 440 else { 441 if (nSkipped < nToSkip && nSkipped + len > nToSkip) { 442 data += nToSkip - nSkipped; 443 len -= nToSkip - nSkipped; 444 nSkipped = nToSkip + 1; 445 } 446 gspca_frame_add(gspca_dev, 447 INTER_PACKET, data, len); 448 } 449 break; 450 } 451 } 452 453 /* This function is called when an image has been read */ 454 /* This function is used to monitor webcam orientation */ 455 static void sd_callback(struct gspca_dev *gspca_dev) 456 { 457 struct sd *sd = (struct sd *) gspca_dev; 458 459 if (!_OV9655_) { 460 u8 state; 461 u8 upsideDown; 462 463 /* Probe sensor orientation */ 464 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state); 465 466 /* C8/40 means upside-down (looking backwards) */ 467 /* D8/50 means right-up (looking onwards) */ 468 upsideDown = (state == 0xc8 || state == 0x40); 469 470 if (upsideDown && sd->nbRightUp > -4) { 471 if (sd->nbRightUp > 0) 472 sd->nbRightUp = 0; 473 if (sd->nbRightUp == -3) { 474 sd->mirrorMask = 1; 475 sd->waitSet = 1; 476 } 477 sd->nbRightUp--; 478 } 479 if (!upsideDown && sd->nbRightUp < 4) { 480 if (sd->nbRightUp < 0) 481 sd->nbRightUp = 0; 482 if (sd->nbRightUp == 3) { 483 sd->mirrorMask = 0; 484 sd->waitSet = 1; 485 } 486 sd->nbRightUp++; 487 } 488 } 489 490 if (sd->waitSet) 491 sd->dev_camera_settings(gspca_dev); 492 } 493 494 /*=================== USB driver structure initialisation ==================*/ 495 496 static const struct usb_device_id device_table[] = { 497 {USB_DEVICE(0x05e3, 0x0503)}, 498 {USB_DEVICE(0x05e3, 0xf191)}, 499 {} 500 }; 501 502 MODULE_DEVICE_TABLE(usb, device_table); 503 504 static int sd_probe(struct usb_interface *intf, 505 const struct usb_device_id *id) 506 { 507 return gspca_dev_probe(intf, id, 508 &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE); 509 } 510 511 static void sd_disconnect(struct usb_interface *intf) 512 { 513 gspca_disconnect(intf); 514 } 515 516 static struct usb_driver sd_driver = { 517 .name = MODULE_NAME, 518 .id_table = device_table, 519 .probe = sd_probe, 520 .disconnect = sd_disconnect, 521 #ifdef CONFIG_PM 522 .suspend = gspca_suspend, 523 .resume = gspca_resume, 524 .reset_resume = gspca_resume, 525 #endif 526 }; 527 528 /*====================== Init and Exit module functions ====================*/ 529 530 module_usb_driver(sd_driver); 531 532 /*==========================================================================*/ 533 534 int gl860_RTx(struct gspca_dev *gspca_dev, 535 unsigned char pref, u32 req, u16 val, u16 index, 536 s32 len, void *pdata) 537 { 538 struct usb_device *udev = gspca_dev->dev; 539 s32 r = 0; 540 541 if (pref == 0x40) { /* Send */ 542 if (len > 0) { 543 memcpy(gspca_dev->usb_buf, pdata, len); 544 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 545 req, pref, val, index, 546 gspca_dev->usb_buf, 547 len, 400 + 200 * (len > 1)); 548 } else { 549 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 550 req, pref, val, index, NULL, len, 400); 551 } 552 } else { /* Receive */ 553 if (len > 0) { 554 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 555 req, pref, val, index, 556 gspca_dev->usb_buf, 557 len, 400 + 200 * (len > 1)); 558 memcpy(pdata, gspca_dev->usb_buf, len); 559 } else { 560 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 561 req, pref, val, index, NULL, len, 400); 562 } 563 } 564 565 if (r < 0) 566 pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n", 567 r, pref, req, val, index, len); 568 else if (len > 1 && r < len) 569 PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len); 570 571 msleep(1); 572 573 return r; 574 } 575 576 int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len) 577 { 578 int n; 579 580 for (n = 0; n < len; n++) { 581 if (tbl[n].idx != 0xffff) 582 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, 583 tbl[n].idx, 0, NULL); 584 else if (tbl[n].val == 0xffff) 585 break; 586 else 587 msleep(tbl[n].val); 588 } 589 return n; 590 } 591 592 int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl, 593 int len, int n) 594 { 595 while (++n < len) { 596 if (tbl[n].idx != 0xffff) 597 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx, 598 0, NULL); 599 else if (tbl[n].val == 0xffff) 600 break; 601 else 602 msleep(tbl[n].val); 603 } 604 return n; 605 } 606 607 void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len) 608 { 609 int n; 610 611 for (n = 0; n < len; n++) { 612 if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0) 613 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx, 614 3, tbl[n].data); 615 else 616 msleep(tbl[n].idx); 617 } 618 } 619 620 static int gl860_guess_sensor(struct gspca_dev *gspca_dev, 621 u16 vendor_id, u16 product_id) 622 { 623 struct sd *sd = (struct sd *) gspca_dev; 624 u8 probe, nb26, nb96, nOV, ntry; 625 626 if (product_id == 0xf191) 627 sd->sensor = ID_MI1320; 628 629 if (sd->sensor == 0xff) { 630 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe); 631 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe); 632 633 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL); 634 msleep(3); 635 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); 636 msleep(3); 637 ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL); 638 msleep(3); 639 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL); 640 msleep(3); 641 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL); 642 msleep(3); 643 ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL); 644 msleep(3); 645 ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); 646 msleep(56); 647 648 PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX"); 649 nOV = 0; 650 for (ntry = 0; ntry < 4; ntry++) { 651 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); 652 msleep(3); 653 ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL); 654 msleep(3); 655 ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); 656 msleep(10); 657 ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe); 658 PDEBUG(D_PROBE, "probe=0x%02x", probe); 659 if (probe == 0xff) 660 nOV++; 661 } 662 663 if (nOV) { 664 PDEBUG(D_PROBE, "0xff -> OVXXXX"); 665 PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655"); 666 667 nb26 = nb96 = 0; 668 for (ntry = 0; ntry < 4; ntry++) { 669 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 670 0, NULL); 671 msleep(3); 672 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a, 673 0, NULL); 674 msleep(10); 675 676 /* Wait for 26(OV2640) or 96(OV9655) */ 677 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a, 678 1, &probe); 679 680 if (probe == 0x26 || probe == 0x40) { 681 PDEBUG(D_PROBE, 682 "probe=0x%02x -> OV2640", 683 probe); 684 sd->sensor = ID_OV2640; 685 nb26 += 4; 686 break; 687 } 688 if (probe == 0x96 || probe == 0x55) { 689 PDEBUG(D_PROBE, 690 "probe=0x%02x -> OV9655", 691 probe); 692 sd->sensor = ID_OV9655; 693 nb96 += 4; 694 break; 695 } 696 PDEBUG(D_PROBE, "probe=0x%02x", probe); 697 if (probe == 0x00) 698 nb26++; 699 if (probe == 0xff) 700 nb96++; 701 msleep(3); 702 } 703 if (nb26 < 4 && nb96 < 4) 704 return -1; 705 } else { 706 PDEBUG(D_PROBE, "Not any 0xff -> MI2020"); 707 sd->sensor = ID_MI2020; 708 } 709 } 710 711 if (_MI1320_) { 712 PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)"); 713 } else if (_MI2020_) { 714 PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)"); 715 } else if (_OV9655_) { 716 PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)"); 717 } else if (_OV2640_) { 718 PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)"); 719 } else { 720 PDEBUG(D_PROBE, "***** Unknown sensor *****"); 721 return -1; 722 } 723 724 return 0; 725 } 726