0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011
0012 #include "gspca.h"
0013 #include "gl860.h"
0014
0015 MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
0016 MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
0017 MODULE_LICENSE("GPL");
0018
0019
0020
0021 static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
0022
0023 static int sd_config(struct gspca_dev *gspca_dev,
0024 const struct usb_device_id *id);
0025 static int sd_init(struct gspca_dev *gspca_dev);
0026 static int sd_isoc_init(struct gspca_dev *gspca_dev);
0027 static int sd_start(struct gspca_dev *gspca_dev);
0028 static void sd_stop0(struct gspca_dev *gspca_dev);
0029 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0030 u8 *data, int len);
0031 static void sd_callback(struct gspca_dev *gspca_dev);
0032
0033 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
0034 u16 vendor_id, u16 product_id);
0035
0036
0037
0038 static s32 AC50Hz = 0xff;
0039 module_param(AC50Hz, int, 0644);
0040 MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
0041
0042 static char sensor[7];
0043 module_param_string(sensor, sensor, sizeof(sensor), 0644);
0044 MODULE_PARM_DESC(sensor,
0045 " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
0046
0047
0048
0049 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0050 {
0051 struct gspca_dev *gspca_dev =
0052 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0053 struct sd *sd = (struct sd *) gspca_dev;
0054
0055 switch (ctrl->id) {
0056 case V4L2_CID_BRIGHTNESS:
0057 sd->vcur.brightness = ctrl->val;
0058 break;
0059 case V4L2_CID_CONTRAST:
0060 sd->vcur.contrast = ctrl->val;
0061 break;
0062 case V4L2_CID_SATURATION:
0063 sd->vcur.saturation = ctrl->val;
0064 break;
0065 case V4L2_CID_HUE:
0066 sd->vcur.hue = ctrl->val;
0067 break;
0068 case V4L2_CID_GAMMA:
0069 sd->vcur.gamma = ctrl->val;
0070 break;
0071 case V4L2_CID_HFLIP:
0072 sd->vcur.mirror = ctrl->val;
0073 break;
0074 case V4L2_CID_VFLIP:
0075 sd->vcur.flip = ctrl->val;
0076 break;
0077 case V4L2_CID_POWER_LINE_FREQUENCY:
0078 sd->vcur.AC50Hz = ctrl->val;
0079 break;
0080 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
0081 sd->vcur.whitebal = ctrl->val;
0082 break;
0083 case V4L2_CID_SHARPNESS:
0084 sd->vcur.sharpness = ctrl->val;
0085 break;
0086 case V4L2_CID_BACKLIGHT_COMPENSATION:
0087 sd->vcur.backlight = ctrl->val;
0088 break;
0089 default:
0090 return -EINVAL;
0091 }
0092
0093 if (gspca_dev->streaming)
0094 sd->waitSet = 1;
0095
0096 return 0;
0097 }
0098
0099 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0100 .s_ctrl = sd_s_ctrl,
0101 };
0102
0103 static int sd_init_controls(struct gspca_dev *gspca_dev)
0104 {
0105 struct sd *sd = (struct sd *) gspca_dev;
0106 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0107
0108 gspca_dev->vdev.ctrl_handler = hdl;
0109 v4l2_ctrl_handler_init(hdl, 11);
0110
0111 if (sd->vmax.brightness)
0112 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS,
0113 0, sd->vmax.brightness, 1,
0114 sd->vcur.brightness);
0115
0116 if (sd->vmax.contrast)
0117 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST,
0118 0, sd->vmax.contrast, 1,
0119 sd->vcur.contrast);
0120
0121 if (sd->vmax.saturation)
0122 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SATURATION,
0123 0, sd->vmax.saturation, 1,
0124 sd->vcur.saturation);
0125
0126 if (sd->vmax.hue)
0127 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HUE,
0128 0, sd->vmax.hue, 1, sd->vcur.hue);
0129
0130 if (sd->vmax.gamma)
0131 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAMMA,
0132 0, sd->vmax.gamma, 1, sd->vcur.gamma);
0133
0134 if (sd->vmax.mirror)
0135 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HFLIP,
0136 0, sd->vmax.mirror, 1, sd->vcur.mirror);
0137
0138 if (sd->vmax.flip)
0139 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_VFLIP,
0140 0, sd->vmax.flip, 1, sd->vcur.flip);
0141
0142 if (sd->vmax.AC50Hz)
0143 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
0144 V4L2_CID_POWER_LINE_FREQUENCY,
0145 sd->vmax.AC50Hz, 0, sd->vcur.AC50Hz);
0146
0147 if (sd->vmax.whitebal)
0148 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0149 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
0150 0, sd->vmax.whitebal, 1, sd->vcur.whitebal);
0151
0152 if (sd->vmax.sharpness)
0153 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SHARPNESS,
0154 0, sd->vmax.sharpness, 1,
0155 sd->vcur.sharpness);
0156
0157 if (sd->vmax.backlight)
0158 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0159 V4L2_CID_BACKLIGHT_COMPENSATION,
0160 0, sd->vmax.backlight, 1,
0161 sd->vcur.backlight);
0162
0163 if (hdl->error) {
0164 pr_err("Could not initialize controls\n");
0165 return hdl->error;
0166 }
0167
0168 return 0;
0169 }
0170
0171
0172
0173 static const struct sd_desc sd_desc_mi1320 = {
0174 .name = MODULE_NAME,
0175 .config = sd_config,
0176 .init = sd_init,
0177 .init_controls = sd_init_controls,
0178 .isoc_init = sd_isoc_init,
0179 .start = sd_start,
0180 .stop0 = sd_stop0,
0181 .pkt_scan = sd_pkt_scan,
0182 .dq_callback = sd_callback,
0183 };
0184
0185 static const struct sd_desc sd_desc_mi2020 = {
0186 .name = MODULE_NAME,
0187 .config = sd_config,
0188 .init = sd_init,
0189 .init_controls = sd_init_controls,
0190 .isoc_init = sd_isoc_init,
0191 .start = sd_start,
0192 .stop0 = sd_stop0,
0193 .pkt_scan = sd_pkt_scan,
0194 .dq_callback = sd_callback,
0195 };
0196
0197 static const struct sd_desc sd_desc_ov2640 = {
0198 .name = MODULE_NAME,
0199 .config = sd_config,
0200 .init = sd_init,
0201 .init_controls = sd_init_controls,
0202 .isoc_init = sd_isoc_init,
0203 .start = sd_start,
0204 .stop0 = sd_stop0,
0205 .pkt_scan = sd_pkt_scan,
0206 .dq_callback = sd_callback,
0207 };
0208
0209 static const struct sd_desc sd_desc_ov9655 = {
0210 .name = MODULE_NAME,
0211 .config = sd_config,
0212 .init = sd_init,
0213 .init_controls = sd_init_controls,
0214 .isoc_init = sd_isoc_init,
0215 .start = sd_start,
0216 .stop0 = sd_stop0,
0217 .pkt_scan = sd_pkt_scan,
0218 .dq_callback = sd_callback,
0219 };
0220
0221
0222
0223 static struct v4l2_pix_format mi2020_mode[] = {
0224 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0225 .bytesperline = 640,
0226 .sizeimage = 640 * 480,
0227 .colorspace = V4L2_COLORSPACE_SRGB,
0228 .priv = 0
0229 },
0230 { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0231 .bytesperline = 800,
0232 .sizeimage = 800 * 598,
0233 .colorspace = V4L2_COLORSPACE_SRGB,
0234 .priv = 1
0235 },
0236 {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0237 .bytesperline = 1280,
0238 .sizeimage = 1280 * 1024,
0239 .colorspace = V4L2_COLORSPACE_SRGB,
0240 .priv = 2
0241 },
0242 {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0243 .bytesperline = 1600,
0244 .sizeimage = 1600 * 1198,
0245 .colorspace = V4L2_COLORSPACE_SRGB,
0246 .priv = 3
0247 },
0248 };
0249
0250 static struct v4l2_pix_format ov2640_mode[] = {
0251 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0252 .bytesperline = 640,
0253 .sizeimage = 640 * 480,
0254 .colorspace = V4L2_COLORSPACE_SRGB,
0255 .priv = 0
0256 },
0257 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0258 .bytesperline = 800,
0259 .sizeimage = 800 * 600,
0260 .colorspace = V4L2_COLORSPACE_SRGB,
0261 .priv = 1
0262 },
0263 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0264 .bytesperline = 1280,
0265 .sizeimage = 1280 * 960,
0266 .colorspace = V4L2_COLORSPACE_SRGB,
0267 .priv = 2
0268 },
0269 {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0270 .bytesperline = 1600,
0271 .sizeimage = 1600 * 1200,
0272 .colorspace = V4L2_COLORSPACE_SRGB,
0273 .priv = 3
0274 },
0275 };
0276
0277 static struct v4l2_pix_format mi1320_mode[] = {
0278 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0279 .bytesperline = 640,
0280 .sizeimage = 640 * 480,
0281 .colorspace = V4L2_COLORSPACE_SRGB,
0282 .priv = 0
0283 },
0284 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0285 .bytesperline = 800,
0286 .sizeimage = 800 * 600,
0287 .colorspace = V4L2_COLORSPACE_SRGB,
0288 .priv = 1
0289 },
0290 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0291 .bytesperline = 1280,
0292 .sizeimage = 1280 * 960,
0293 .colorspace = V4L2_COLORSPACE_SRGB,
0294 .priv = 2
0295 },
0296 };
0297
0298 static struct v4l2_pix_format ov9655_mode[] = {
0299 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0300 .bytesperline = 640,
0301 .sizeimage = 640 * 480,
0302 .colorspace = V4L2_COLORSPACE_SRGB,
0303 .priv = 0
0304 },
0305 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0306 .bytesperline = 1280,
0307 .sizeimage = 1280 * 960,
0308 .colorspace = V4L2_COLORSPACE_SRGB,
0309 .priv = 1
0310 },
0311 };
0312
0313
0314
0315
0316 static int sd_config(struct gspca_dev *gspca_dev,
0317 const struct usb_device_id *id)
0318 {
0319 struct sd *sd = (struct sd *) gspca_dev;
0320 struct cam *cam;
0321 u16 vendor_id, product_id;
0322
0323
0324 vendor_id = id->idVendor;
0325 product_id = id->idProduct;
0326
0327 sd->nbRightUp = 1;
0328 sd->nbIm = -1;
0329
0330 sd->sensor = 0xff;
0331 if (strcmp(sensor, "MI1320") == 0)
0332 sd->sensor = ID_MI1320;
0333 else if (strcmp(sensor, "OV2640") == 0)
0334 sd->sensor = ID_OV2640;
0335 else if (strcmp(sensor, "OV9655") == 0)
0336 sd->sensor = ID_OV9655;
0337 else if (strcmp(sensor, "MI2020") == 0)
0338 sd->sensor = ID_MI2020;
0339
0340
0341 if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
0342 return -1;
0343
0344 cam = &gspca_dev->cam;
0345
0346 switch (sd->sensor) {
0347 case ID_MI1320:
0348 gspca_dev->sd_desc = &sd_desc_mi1320;
0349 cam->cam_mode = mi1320_mode;
0350 cam->nmodes = ARRAY_SIZE(mi1320_mode);
0351 dev_init_settings = mi1320_init_settings;
0352 break;
0353
0354 case ID_MI2020:
0355 gspca_dev->sd_desc = &sd_desc_mi2020;
0356 cam->cam_mode = mi2020_mode;
0357 cam->nmodes = ARRAY_SIZE(mi2020_mode);
0358 dev_init_settings = mi2020_init_settings;
0359 break;
0360
0361 case ID_OV2640:
0362 gspca_dev->sd_desc = &sd_desc_ov2640;
0363 cam->cam_mode = ov2640_mode;
0364 cam->nmodes = ARRAY_SIZE(ov2640_mode);
0365 dev_init_settings = ov2640_init_settings;
0366 break;
0367
0368 case ID_OV9655:
0369 gspca_dev->sd_desc = &sd_desc_ov9655;
0370 cam->cam_mode = ov9655_mode;
0371 cam->nmodes = ARRAY_SIZE(ov9655_mode);
0372 dev_init_settings = ov9655_init_settings;
0373 break;
0374 }
0375
0376 dev_init_settings(gspca_dev);
0377 if (AC50Hz != 0xff)
0378 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
0379
0380 return 0;
0381 }
0382
0383
0384 static int sd_init(struct gspca_dev *gspca_dev)
0385 {
0386 struct sd *sd = (struct sd *) gspca_dev;
0387
0388 return sd->dev_init_at_startup(gspca_dev);
0389 }
0390
0391
0392 static int sd_isoc_init(struct gspca_dev *gspca_dev)
0393 {
0394 struct sd *sd = (struct sd *) gspca_dev;
0395
0396 return sd->dev_configure_alt(gspca_dev);
0397 }
0398
0399
0400 static int sd_start(struct gspca_dev *gspca_dev)
0401 {
0402 struct sd *sd = (struct sd *) gspca_dev;
0403
0404 return sd->dev_init_pre_alt(gspca_dev);
0405 }
0406
0407
0408 static void sd_stop0(struct gspca_dev *gspca_dev)
0409 {
0410 struct sd *sd = (struct sd *) gspca_dev;
0411
0412 if (!sd->gspca_dev.present)
0413 return;
0414
0415 return sd->dev_post_unset_alt(gspca_dev);
0416 }
0417
0418
0419 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0420 u8 *data, int len)
0421 {
0422 struct sd *sd = (struct sd *) gspca_dev;
0423 static s32 nSkipped;
0424
0425 s32 mode = (s32) gspca_dev->curr_mode;
0426 s32 nToSkip =
0427 sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
0428
0429
0430 switch (*(s16 *) data) {
0431 case 0x0202:
0432 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0433 nSkipped = 0;
0434 if (sd->nbIm >= 0 && sd->nbIm < 10)
0435 sd->nbIm++;
0436 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
0437 break;
0438
0439 default:
0440 data += 2;
0441 len -= 2;
0442 if (nSkipped + len <= nToSkip)
0443 nSkipped += len;
0444 else {
0445 if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
0446 data += nToSkip - nSkipped;
0447 len -= nToSkip - nSkipped;
0448 nSkipped = nToSkip + 1;
0449 }
0450 gspca_frame_add(gspca_dev,
0451 INTER_PACKET, data, len);
0452 }
0453 break;
0454 }
0455 }
0456
0457
0458
0459 static void sd_callback(struct gspca_dev *gspca_dev)
0460 {
0461 struct sd *sd = (struct sd *) gspca_dev;
0462
0463 if (!_OV9655_) {
0464 u8 state;
0465 u8 upsideDown;
0466
0467
0468 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
0469
0470
0471
0472 upsideDown = (state == 0xc8 || state == 0x40);
0473
0474 if (upsideDown && sd->nbRightUp > -4) {
0475 if (sd->nbRightUp > 0)
0476 sd->nbRightUp = 0;
0477 if (sd->nbRightUp == -3) {
0478 sd->mirrorMask = 1;
0479 sd->waitSet = 1;
0480 }
0481 sd->nbRightUp--;
0482 }
0483 if (!upsideDown && sd->nbRightUp < 4) {
0484 if (sd->nbRightUp < 0)
0485 sd->nbRightUp = 0;
0486 if (sd->nbRightUp == 3) {
0487 sd->mirrorMask = 0;
0488 sd->waitSet = 1;
0489 }
0490 sd->nbRightUp++;
0491 }
0492 }
0493
0494 if (sd->waitSet)
0495 sd->dev_camera_settings(gspca_dev);
0496 }
0497
0498
0499
0500 static const struct usb_device_id device_table[] = {
0501 {USB_DEVICE(0x05e3, 0x0503)},
0502 {USB_DEVICE(0x05e3, 0xf191)},
0503 {}
0504 };
0505
0506 MODULE_DEVICE_TABLE(usb, device_table);
0507
0508 static int sd_probe(struct usb_interface *intf,
0509 const struct usb_device_id *id)
0510 {
0511 return gspca_dev_probe(intf, id,
0512 &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE);
0513 }
0514
0515 static void sd_disconnect(struct usb_interface *intf)
0516 {
0517 gspca_disconnect(intf);
0518 }
0519
0520 static struct usb_driver sd_driver = {
0521 .name = MODULE_NAME,
0522 .id_table = device_table,
0523 .probe = sd_probe,
0524 .disconnect = sd_disconnect,
0525 #ifdef CONFIG_PM
0526 .suspend = gspca_suspend,
0527 .resume = gspca_resume,
0528 .reset_resume = gspca_resume,
0529 #endif
0530 };
0531
0532
0533
0534 module_usb_driver(sd_driver);
0535
0536
0537
0538 int gl860_RTx(struct gspca_dev *gspca_dev,
0539 unsigned char pref, u32 req, u16 val, u16 index,
0540 s32 len, void *pdata)
0541 {
0542 struct usb_device *udev = gspca_dev->dev;
0543 s32 r = 0;
0544
0545 if (pref == 0x40) {
0546 if (len > 0) {
0547 memcpy(gspca_dev->usb_buf, pdata, len);
0548 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0549 req, pref, val, index,
0550 gspca_dev->usb_buf,
0551 len, 400 + 200 * (len > 1));
0552 } else {
0553 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0554 req, pref, val, index, NULL, len, 400);
0555 }
0556 } else {
0557 if (len > 0) {
0558 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0559 req, pref, val, index,
0560 gspca_dev->usb_buf,
0561 len, 400 + 200 * (len > 1));
0562 memcpy(pdata, gspca_dev->usb_buf, len);
0563 } else {
0564 gspca_err(gspca_dev, "zero-length read request\n");
0565 r = -EINVAL;
0566 }
0567 }
0568
0569 if (r < 0)
0570 pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
0571 r, pref, req, val, index, len);
0572 else if (len > 1 && r < len)
0573 gspca_err(gspca_dev, "short ctrl transfer %d/%d\n", r, len);
0574
0575 msleep(1);
0576
0577 return r;
0578 }
0579
0580 int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
0581 {
0582 int n;
0583
0584 for (n = 0; n < len; n++) {
0585 if (tbl[n].idx != 0xffff)
0586 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
0587 tbl[n].idx, 0, NULL);
0588 else if (tbl[n].val == 0xffff)
0589 break;
0590 else
0591 msleep(tbl[n].val);
0592 }
0593 return n;
0594 }
0595
0596 int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
0597 int len, int n)
0598 {
0599 while (++n < len) {
0600 if (tbl[n].idx != 0xffff)
0601 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
0602 0, NULL);
0603 else if (tbl[n].val == 0xffff)
0604 break;
0605 else
0606 msleep(tbl[n].val);
0607 }
0608 return n;
0609 }
0610
0611 void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
0612 {
0613 int n;
0614
0615 for (n = 0; n < len; n++) {
0616 if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
0617 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
0618 3, tbl[n].data);
0619 else
0620 msleep(tbl[n].idx);
0621 }
0622 }
0623
0624 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
0625 u16 vendor_id, u16 product_id)
0626 {
0627 struct sd *sd = (struct sd *) gspca_dev;
0628 u8 probe, nb26, nb96, nOV, ntry;
0629
0630 if (product_id == 0xf191)
0631 sd->sensor = ID_MI1320;
0632
0633 if (sd->sensor == 0xff) {
0634 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
0635 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
0636
0637 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
0638 msleep(3);
0639 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
0640 msleep(3);
0641 ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
0642 msleep(3);
0643 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
0644 msleep(3);
0645 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
0646 msleep(3);
0647 ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
0648 msleep(3);
0649 ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
0650 msleep(56);
0651
0652 gspca_dbg(gspca_dev, D_PROBE, "probing for sensor MI2020 or OVXXXX\n");
0653 nOV = 0;
0654 for (ntry = 0; ntry < 4; ntry++) {
0655 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
0656 msleep(3);
0657 ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
0658 msleep(3);
0659 ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
0660 msleep(10);
0661 ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
0662 gspca_dbg(gspca_dev, D_PROBE, "probe=0x%02x\n", probe);
0663 if (probe == 0xff)
0664 nOV++;
0665 }
0666
0667 if (nOV) {
0668 gspca_dbg(gspca_dev, D_PROBE, "0xff -> OVXXXX\n");
0669 gspca_dbg(gspca_dev, D_PROBE, "probing for sensor OV2640 or OV9655");
0670
0671 nb26 = nb96 = 0;
0672 for (ntry = 0; ntry < 4; ntry++) {
0673 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
0674 0, NULL);
0675 msleep(3);
0676 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
0677 0, NULL);
0678 msleep(10);
0679
0680
0681 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
0682 1, &probe);
0683
0684 if (probe == 0x26 || probe == 0x40) {
0685 gspca_dbg(gspca_dev, D_PROBE,
0686 "probe=0x%02x -> OV2640\n",
0687 probe);
0688 sd->sensor = ID_OV2640;
0689 nb26 += 4;
0690 break;
0691 }
0692 if (probe == 0x96 || probe == 0x55) {
0693 gspca_dbg(gspca_dev, D_PROBE,
0694 "probe=0x%02x -> OV9655\n",
0695 probe);
0696 sd->sensor = ID_OV9655;
0697 nb96 += 4;
0698 break;
0699 }
0700 gspca_dbg(gspca_dev, D_PROBE, "probe=0x%02x\n",
0701 probe);
0702 if (probe == 0x00)
0703 nb26++;
0704 if (probe == 0xff)
0705 nb96++;
0706 msleep(3);
0707 }
0708 if (nb26 < 4 && nb96 < 4)
0709 return -1;
0710 } else {
0711 gspca_dbg(gspca_dev, D_PROBE, "Not any 0xff -> MI2020\n");
0712 sd->sensor = ID_MI2020;
0713 }
0714 }
0715
0716 if (_MI1320_) {
0717 gspca_dbg(gspca_dev, D_PROBE, "05e3:f191 sensor MI1320 (1.3M)\n");
0718 } else if (_MI2020_) {
0719 gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor MI2020 (2.0M)\n");
0720 } else if (_OV9655_) {
0721 gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor OV9655 (1.3M)\n");
0722 } else if (_OV2640_) {
0723 gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor OV2640 (2.0M)\n");
0724 } else {
0725 gspca_dbg(gspca_dev, D_PROBE, "***** Unknown sensor *****\n");
0726 return -1;
0727 }
0728
0729 return 0;
0730 }