Commit 458efe2d558b51fff38026e8ede9374899340e60

Authored by Jean-François Moine
Committed by Mauro Carvalho Chehab
1 parent 228dd2660c

[media] gspca - ov534: Add the webcam 06f8:3002 and sensor ov767x

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Showing 2 changed files with 459 additions and 60 deletions Side-by-side Diff

Documentation/video4linux/gspca.txt
... ... @@ -199,6 +199,7 @@
199 199 spca500 06be:0800 Optimedia
200 200 sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
201 201 spca506 06e1:a190 ADS Instant VCD
  202 +ov534 06f8:3002 Hercules Blog Webcam
202 203 ov534_9 06f8:3003 Hercules Dualpix HD Weblog
203 204 sonixj 06f8:3004 Hercules Classic Silver
204 205 sonixj 06f8:3008 Hercules Deluxe Optical Glass
drivers/media/video/gspca/ov534.c
1 1 /*
2   - * ov534-ov772x gspca driver
  2 + * ov534-ov7xxx gspca driver
3 3 *
4 4 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
5 5 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
6 6  
... ... @@ -75,7 +75,13 @@
75 75 u16 last_fid;
76 76 u8 frame_rate;
77 77  
  78 + u8 sensor;
78 79 };
  80 +enum sensors {
  81 + SENSOR_OV767x,
  82 + SENSOR_OV772x,
  83 + NSENSORS
  84 +};
79 85  
80 86 /* V4L2 controls supported by the driver */
81 87 static void setbrightness(struct gspca_dev *gspca_dev);
... ... @@ -239,6 +245,16 @@
239 245 .colorspace = V4L2_COLORSPACE_SRGB,
240 246 .priv = 0},
241 247 };
  248 +static const struct v4l2_pix_format ov767x_mode[] = {
  249 + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  250 + .bytesperline = 320,
  251 + .sizeimage = 320 * 240 * 3 / 8 + 590,
  252 + .colorspace = V4L2_COLORSPACE_JPEG},
  253 + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  254 + .bytesperline = 640,
  255 + .sizeimage = 640 * 480 * 3 / 8 + 590,
  256 + .colorspace = V4L2_COLORSPACE_JPEG},
  257 +};
242 258  
243 259 static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
244 260 static const u8 vga_rates[] = {60, 50, 40, 30, 15};
... ... @@ -254,7 +270,288 @@
254 270 },
255 271 };
256 272  
257   -static const u8 bridge_init[][2] = {
  273 +struct reg_array {
  274 + const u8 (*val)[2];
  275 + int len;
  276 +};
  277 +
  278 +static const u8 bridge_init_767x[][2] = {
  279 +/* comments from the ms-win file apollo7670.set */
  280 +/* str1 */
  281 + {0xf1, 0x42},
  282 + {0x88, 0xf8},
  283 + {0x89, 0xff},
  284 + {0x76, 0x03},
  285 + {0x92, 0x03},
  286 + {0x95, 0x10},
  287 + {0xe2, 0x00},
  288 + {0xe7, 0x3e},
  289 + {0x8d, 0x1c},
  290 + {0x8e, 0x00},
  291 + {0x8f, 0x00},
  292 + {0x1f, 0x00},
  293 + {0xc3, 0xf9},
  294 + {0x89, 0xff},
  295 + {0x88, 0xf8},
  296 + {0x76, 0x03},
  297 + {0x92, 0x01},
  298 + {0x93, 0x18},
  299 + {0x1c, 0x00},
  300 + {0x1d, 0x48},
  301 + {0x1d, 0x00},
  302 + {0x1d, 0xff},
  303 + {0x1d, 0x02},
  304 + {0x1d, 0x58},
  305 + {0x1d, 0x00},
  306 + {0x1c, 0x0a},
  307 + {0x1d, 0x0a},
  308 + {0x1d, 0x0e},
  309 + {0xc0, 0x50}, /* HSize 640 */
  310 + {0xc1, 0x3c}, /* VSize 480 */
  311 + {0x34, 0x05}, /* enable Audio Suspend mode */
  312 + {0xc2, 0x0c}, /* Input YUV */
  313 + {0xc3, 0xf9}, /* enable PRE */
  314 + {0x34, 0x05}, /* enable Audio Suspend mode */
  315 + {0xe7, 0x2e}, /* this solves failure of "SuspendResumeTest" */
  316 + {0x31, 0xf9}, /* enable 1.8V Suspend */
  317 + {0x35, 0x02}, /* turn on JPEG */
  318 + {0xd9, 0x10},
  319 + {0x25, 0x42}, /* GPIO[8]:Input */
  320 + {0x94, 0x11}, /* If the default setting is loaded when
  321 + * system boots up, this flag is closed here */
  322 +};
  323 +static const u8 sensor_init_767x[][2] = {
  324 + {0x12, 0x80},
  325 + {0x11, 0x03},
  326 + {0x3a, 0x04},
  327 + {0x12, 0x00},
  328 + {0x17, 0x13},
  329 + {0x18, 0x01},
  330 + {0x32, 0xb6},
  331 + {0x19, 0x02},
  332 + {0x1a, 0x7a},
  333 + {0x03, 0x0a},
  334 + {0x0c, 0x00},
  335 + {0x3e, 0x00},
  336 + {0x70, 0x3a},
  337 + {0x71, 0x35},
  338 + {0x72, 0x11},
  339 + {0x73, 0xf0},
  340 + {0xa2, 0x02},
  341 + {0x7a, 0x2a}, /* set Gamma=1.6 below */
  342 + {0x7b, 0x12},
  343 + {0x7c, 0x1d},
  344 + {0x7d, 0x2d},
  345 + {0x7e, 0x45},
  346 + {0x7f, 0x50},
  347 + {0x80, 0x59},
  348 + {0x81, 0x62},
  349 + {0x82, 0x6b},
  350 + {0x83, 0x73},
  351 + {0x84, 0x7b},
  352 + {0x85, 0x8a},
  353 + {0x86, 0x98},
  354 + {0x87, 0xb2},
  355 + {0x88, 0xca},
  356 + {0x89, 0xe0},
  357 + {0x13, 0xe0},
  358 + {0x00, 0x00},
  359 + {0x10, 0x00},
  360 + {0x0d, 0x40},
  361 + {0x14, 0x38}, /* gain max 16x */
  362 + {0xa5, 0x05},
  363 + {0xab, 0x07},
  364 + {0x24, 0x95},
  365 + {0x25, 0x33},
  366 + {0x26, 0xe3},
  367 + {0x9f, 0x78},
  368 + {0xa0, 0x68},
  369 + {0xa1, 0x03},
  370 + {0xa6, 0xd8},
  371 + {0xa7, 0xd8},
  372 + {0xa8, 0xf0},
  373 + {0xa9, 0x90},
  374 + {0xaa, 0x94},
  375 + {0x13, 0xe5},
  376 + {0x0e, 0x61},
  377 + {0x0f, 0x4b},
  378 + {0x16, 0x02},
  379 + {0x21, 0x02},
  380 + {0x22, 0x91},
  381 + {0x29, 0x07},
  382 + {0x33, 0x0b},
  383 + {0x35, 0x0b},
  384 + {0x37, 0x1d},
  385 + {0x38, 0x71},
  386 + {0x39, 0x2a},
  387 + {0x3c, 0x78},
  388 + {0x4d, 0x40},
  389 + {0x4e, 0x20},
  390 + {0x69, 0x00},
  391 + {0x6b, 0x4a},
  392 + {0x74, 0x10},
  393 + {0x8d, 0x4f},
  394 + {0x8e, 0x00},
  395 + {0x8f, 0x00},
  396 + {0x90, 0x00},
  397 + {0x91, 0x00},
  398 + {0x96, 0x00},
  399 + {0x9a, 0x80},
  400 + {0xb0, 0x84},
  401 + {0xb1, 0x0c},
  402 + {0xb2, 0x0e},
  403 + {0xb3, 0x82},
  404 + {0xb8, 0x0a},
  405 + {0x43, 0x0a},
  406 + {0x44, 0xf0},
  407 + {0x45, 0x34},
  408 + {0x46, 0x58},
  409 + {0x47, 0x28},
  410 + {0x48, 0x3a},
  411 + {0x59, 0x88},
  412 + {0x5a, 0x88},
  413 + {0x5b, 0x44},
  414 + {0x5c, 0x67},
  415 + {0x5d, 0x49},
  416 + {0x5e, 0x0e},
  417 + {0x6c, 0x0a},
  418 + {0x6d, 0x55},
  419 + {0x6e, 0x11},
  420 + {0x6f, 0x9f},
  421 + {0x6a, 0x40},
  422 + {0x01, 0x40},
  423 + {0x02, 0x40},
  424 + {0x13, 0xe7},
  425 + {0x4f, 0x80},
  426 + {0x50, 0x80},
  427 + {0x51, 0x00},
  428 + {0x52, 0x22},
  429 + {0x53, 0x5e},
  430 + {0x54, 0x80},
  431 + {0x58, 0x9e},
  432 + {0x41, 0x08},
  433 + {0x3f, 0x00},
  434 + {0x75, 0x04},
  435 + {0x76, 0xe1},
  436 + {0x4c, 0x00},
  437 + {0x77, 0x01},
  438 + {0x3d, 0xc2},
  439 + {0x4b, 0x09},
  440 + {0xc9, 0x60},
  441 + {0x41, 0x38}, /* jfm: auto sharpness + auto de-noise */
  442 + {0x56, 0x40},
  443 + {0x34, 0x11},
  444 + {0x3b, 0xc2},
  445 + {0xa4, 0x8a}, /* Night mode trigger point */
  446 + {0x96, 0x00},
  447 + {0x97, 0x30},
  448 + {0x98, 0x20},
  449 + {0x99, 0x20},
  450 + {0x9a, 0x84},
  451 + {0x9b, 0x29},
  452 + {0x9c, 0x03},
  453 + {0x9d, 0x4c},
  454 + {0x9e, 0x3f},
  455 + {0x78, 0x04},
  456 + {0x79, 0x01},
  457 + {0xc8, 0xf0},
  458 + {0x79, 0x0f},
  459 + {0xc8, 0x00},
  460 + {0x79, 0x10},
  461 + {0xc8, 0x7e},
  462 + {0x79, 0x0a},
  463 + {0xc8, 0x80},
  464 + {0x79, 0x0b},
  465 + {0xc8, 0x01},
  466 + {0x79, 0x0c},
  467 + {0xc8, 0x0f},
  468 + {0x79, 0x0d},
  469 + {0xc8, 0x20},
  470 + {0x79, 0x09},
  471 + {0xc8, 0x80},
  472 + {0x79, 0x02},
  473 + {0xc8, 0xc0},
  474 + {0x79, 0x03},
  475 + {0xc8, 0x20},
  476 + {0x79, 0x26},
  477 +};
  478 +static const u8 bridge_start_vga_767x[][2] = {
  479 +/* str59 JPG */
  480 + {0x94, 0xaa},
  481 + {0xf1, 0x42},
  482 + {0xe5, 0x04},
  483 + {0xc0, 0x50},
  484 + {0xc1, 0x3c},
  485 + {0xc2, 0x0c},
  486 + {0x35, 0x02}, /* turn on JPEG */
  487 + {0xd9, 0x10},
  488 + {0xda, 0x00}, /* for higher clock rate(30fps) */
  489 + {0x34, 0x05}, /* enable Audio Suspend mode */
  490 + {0xc3, 0xf9}, /* enable PRE */
  491 + {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
  492 + {0x8d, 0x1c}, /* output YUV */
  493 +/* {0x34, 0x05}, * enable Audio Suspend mode (?) */
  494 + {0x50, 0x00}, /* H/V divider=0 */
  495 + {0x51, 0xa0}, /* input H=640/4 */
  496 + {0x52, 0x3c}, /* input V=480/4 */
  497 + {0x53, 0x00}, /* offset X=0 */
  498 + {0x54, 0x00}, /* offset Y=0 */
  499 + {0x55, 0x00}, /* H/V size[8]=0 */
  500 + {0x57, 0x00}, /* H-size[9]=0 */
  501 + {0x5c, 0x00}, /* output size[9:8]=0 */
  502 + {0x5a, 0xa0}, /* output H=640/4 */
  503 + {0x5b, 0x78}, /* output V=480/4 */
  504 + {0x1c, 0x0a},
  505 + {0x1d, 0x0a},
  506 + {0x94, 0x11},
  507 +};
  508 +static const u8 sensor_start_vga_767x[][2] = {
  509 + {0x11, 0x01},
  510 + {0x1e, 0x04},
  511 + {0x19, 0x02},
  512 + {0x1a, 0x7a},
  513 +};
  514 +static const u8 bridge_start_qvga_767x[][2] = {
  515 +/* str86 JPG */
  516 + {0x94, 0xaa},
  517 + {0xf1, 0x42},
  518 + {0xe5, 0x04},
  519 + {0xc0, 0x80},
  520 + {0xc1, 0x60},
  521 + {0xc2, 0x0c},
  522 + {0x35, 0x02}, /* turn on JPEG */
  523 + {0xd9, 0x10},
  524 + {0xc0, 0x50}, /* CIF HSize 640 */
  525 + {0xc1, 0x3c}, /* CIF VSize 480 */
  526 + {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
  527 + {0x8d, 0x1c}, /* output YUV */
  528 + {0x34, 0x05}, /* enable Audio Suspend mode */
  529 + {0xc2, 0x4c}, /* output YUV and Enable DCW */
  530 + {0xc3, 0xf9}, /* enable PRE */
  531 + {0x1c, 0x00}, /* indirect addressing */
  532 + {0x1d, 0x48}, /* output YUV422 */
  533 + {0x50, 0x89}, /* H/V divider=/2; plus DCW AVG */
  534 + {0x51, 0xa0}, /* DCW input H=640/4 */
  535 + {0x52, 0x78}, /* DCW input V=480/4 */
  536 + {0x53, 0x00}, /* offset X=0 */
  537 + {0x54, 0x00}, /* offset Y=0 */
  538 + {0x55, 0x00}, /* H/V size[8]=0 */
  539 + {0x57, 0x00}, /* H-size[9]=0 */
  540 + {0x5c, 0x00}, /* DCW output size[9:8]=0 */
  541 + {0x5a, 0x50}, /* DCW output H=320/4 */
  542 + {0x5b, 0x3c}, /* DCW output V=240/4 */
  543 + {0x1c, 0x0a},
  544 + {0x1d, 0x0a},
  545 + {0x94, 0x11},
  546 +};
  547 +static const u8 sensor_start_qvga_767x[][2] = {
  548 + {0x11, 0x01},
  549 + {0x1e, 0x04},
  550 + {0x19, 0x02},
  551 + {0x1a, 0x7a},
  552 +};
  553 +
  554 +static const u8 bridge_init_772x[][2] = {
258 555 { 0xc2, 0x0c },
259 556 { 0x88, 0xf8 },
260 557 { 0xc3, 0x69 },
... ... @@ -312,7 +609,7 @@
312 609 { 0xc1, 0x3c },
313 610 { 0xc2, 0x0c },
314 611 };
315   -static const u8 sensor_init[][2] = {
  612 +static const u8 sensor_init_772x[][2] = {
316 613 { 0x12, 0x80 },
317 614 { 0x11, 0x01 },
318 615 /*fixme: better have a delay?*/
... ... @@ -405,7 +702,7 @@
405 702 { 0x8e, 0x00 }, /* De-noise threshold */
406 703 { 0x0c, 0xd0 }
407 704 };
408   -static const u8 bridge_start_vga[][2] = {
  705 +static const u8 bridge_start_vga_772x[][2] = {
409 706 {0x1c, 0x00},
410 707 {0x1d, 0x40},
411 708 {0x1d, 0x02},
... ... @@ -416,7 +713,7 @@
416 713 {0xc0, 0x50},
417 714 {0xc1, 0x3c},
418 715 };
419   -static const u8 sensor_start_vga[][2] = {
  716 +static const u8 sensor_start_vga_772x[][2] = {
420 717 {0x12, 0x00},
421 718 {0x17, 0x26},
422 719 {0x18, 0xa0},
... ... @@ -426,7 +723,7 @@
426 723 {0x2c, 0xf0},
427 724 {0x65, 0x20},
428 725 };
429   -static const u8 bridge_start_qvga[][2] = {
  726 +static const u8 bridge_start_qvga_772x[][2] = {
430 727 {0x1c, 0x00},
431 728 {0x1d, 0x40},
432 729 {0x1d, 0x02},
... ... @@ -437,7 +734,7 @@
437 734 {0xc0, 0x28},
438 735 {0xc1, 0x1e},
439 736 };
440   -static const u8 sensor_start_qvga[][2] = {
  737 +static const u8 sensor_start_qvga_772x[][2] = {
441 738 {0x12, 0x40},
442 739 {0x17, 0x3f},
443 740 {0x18, 0x50},
... ... @@ -620,6 +917,8 @@
620 917 {30, 0x04, 0x41, 0x04},
621 918 };
622 919  
  920 + if (sd->sensor != SENSOR_OV772x)
  921 + return;
623 922 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
624 923 r = rate_0;
625 924 i = ARRAY_SIZE(rate_0);
626 925  
627 926  
628 927  
... ... @@ -643,15 +942,28 @@
643 942 static void setbrightness(struct gspca_dev *gspca_dev)
644 943 {
645 944 struct sd *sd = (struct sd *) gspca_dev;
  945 + int val;
646 946  
647   - sccb_reg_write(gspca_dev, 0x9b, sd->ctrls[BRIGHTNESS].val);
  947 + val = sd->ctrls[BRIGHTNESS].val;
  948 + if (sd->sensor == SENSOR_OV767x) {
  949 + if (val < 0)
  950 + val = 0x80 - val;
  951 + sccb_reg_write(gspca_dev, 0x55, val); /* bright */
  952 + } else {
  953 + sccb_reg_write(gspca_dev, 0x9b, val);
  954 + }
648 955 }
649 956  
650 957 static void setcontrast(struct gspca_dev *gspca_dev)
651 958 {
652 959 struct sd *sd = (struct sd *) gspca_dev;
  960 + u8 val;
653 961  
654   - sccb_reg_write(gspca_dev, 0x9c, sd->ctrls[CONTRAST].val);
  962 + val = sd->ctrls[CONTRAST].val;
  963 + if (sd->sensor == SENSOR_OV767x)
  964 + sccb_reg_write(gspca_dev, 0x56, val); /* contras */
  965 + else
  966 + sccb_reg_write(gspca_dev, 0x9c, val);
655 967 }
656 968  
657 969 static void setgain(struct gspca_dev *gspca_dev)
658 970  
... ... @@ -692,15 +1004,22 @@
692 1004 if (sd->ctrls[AEC].val)
693 1005 return;
694 1006  
695   - /* 'val' is one byte and represents half of the exposure value we are
696   - * going to set into registers, a two bytes value:
697   - *
698   - * MSB: ((u16) val << 1) >> 8 == val >> 7
699   - * LSB: ((u16) val << 1) & 0xff == val << 1
700   - */
701 1007 val = sd->ctrls[EXPOSURE].val;
702   - sccb_reg_write(gspca_dev, 0x08, val >> 7);
703   - sccb_reg_write(gspca_dev, 0x10, val << 1);
  1008 + if (sd->sensor == SENSOR_OV767x) {
  1009 +
  1010 + /* set only aec[9:2] */
  1011 + sccb_reg_write(gspca_dev, 0x10, val); /* aech */
  1012 + } else {
  1013 +
  1014 + /* 'val' is one byte and represents half of the exposure value
  1015 + * we are going to set into registers, a two bytes value:
  1016 + *
  1017 + * MSB: ((u16) val << 1) >> 8 == val >> 7
  1018 + * LSB: ((u16) val << 1) & 0xff == val << 1
  1019 + */
  1020 + sccb_reg_write(gspca_dev, 0x08, val >> 7);
  1021 + sccb_reg_write(gspca_dev, 0x10, val << 1);
  1022 + }
704 1023 }
705 1024  
706 1025 static void setagc(struct gspca_dev *gspca_dev)
707 1026  
... ... @@ -729,12 +1048,14 @@
729 1048 if (sd->ctrls[AWB].val) {
730 1049 sccb_reg_write(gspca_dev, 0x13,
731 1050 sccb_reg_read(gspca_dev, 0x13) | 0x02);
732   - sccb_reg_write(gspca_dev, 0x63,
  1051 + if (sd->sensor == SENSOR_OV772x)
  1052 + sccb_reg_write(gspca_dev, 0x63,
733 1053 sccb_reg_read(gspca_dev, 0x63) | 0xc0);
734 1054 } else {
735 1055 sccb_reg_write(gspca_dev, 0x13,
736 1056 sccb_reg_read(gspca_dev, 0x13) & ~0x02);
737   - sccb_reg_write(gspca_dev, 0x63,
  1057 + if (sd->sensor == SENSOR_OV772x)
  1058 + sccb_reg_write(gspca_dev, 0x63,
738 1059 sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
739 1060 }
740 1061 }
741 1062  
742 1063  
743 1064  
... ... @@ -742,14 +1063,22 @@
742 1063 static void setaec(struct gspca_dev *gspca_dev)
743 1064 {
744 1065 struct sd *sd = (struct sd *) gspca_dev;
  1066 + u8 data;
745 1067  
  1068 + data = sd->sensor == SENSOR_OV767x ?
  1069 + 0x05 : /* agc + aec */
  1070 + 0x01; /* agc */
746 1071 if (sd->ctrls[AEC].val)
747 1072 sccb_reg_write(gspca_dev, 0x13,
748   - sccb_reg_read(gspca_dev, 0x13) | 0x01);
  1073 + sccb_reg_read(gspca_dev, 0x13) | data);
749 1074 else {
750 1075 sccb_reg_write(gspca_dev, 0x13,
751   - sccb_reg_read(gspca_dev, 0x13) & ~0x01);
752   - setexposure(gspca_dev);
  1076 + sccb_reg_read(gspca_dev, 0x13) & ~data);
  1077 + if (sd->sensor == SENSOR_OV767x)
  1078 + sd->ctrls[EXPOSURE].val =
  1079 + sccb_reg_read(gspca_dev, 10); /* aech */
  1080 + else
  1081 + setexposure(gspca_dev);
753 1082 }
754 1083 }
755 1084  
756 1085  
757 1086  
... ... @@ -768,23 +1097,37 @@
768 1097 struct sd *sd = (struct sd *) gspca_dev;
769 1098 u8 val;
770 1099  
771   - val = sccb_reg_read(gspca_dev, 0x0c);
772   - val &= ~0xc0;
773   - if (sd->ctrls[HFLIP].val == 0)
774   - val |= 0x40;
775   - if (sd->ctrls[VFLIP].val == 0)
776   - val |= 0x80;
777   - sccb_reg_write(gspca_dev, 0x0c, val);
  1100 + if (sd->sensor == SENSOR_OV767x) {
  1101 + val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */
  1102 + val &= ~0x30;
  1103 + if (sd->ctrls[HFLIP].val)
  1104 + val |= 0x20;
  1105 + if (sd->ctrls[VFLIP].val)
  1106 + val |= 0x10;
  1107 + sccb_reg_write(gspca_dev, 0x1e, val);
  1108 + } else {
  1109 + val = sccb_reg_read(gspca_dev, 0x0c);
  1110 + val &= ~0xc0;
  1111 + if (sd->ctrls[HFLIP].val == 0)
  1112 + val |= 0x40;
  1113 + if (sd->ctrls[VFLIP].val == 0)
  1114 + val |= 0x80;
  1115 + sccb_reg_write(gspca_dev, 0x0c, val);
  1116 + }
778 1117 }
779 1118  
780 1119 static void setlightfreq(struct gspca_dev *gspca_dev)
781 1120 {
782 1121 struct sd *sd = (struct sd *) gspca_dev;
  1122 + u8 val;
783 1123  
784   - if (sd->ctrls[LIGHTFREQ].val == 0)
785   - sccb_reg_write(gspca_dev, 0x2b, 0x00);
786   - else
787   - sccb_reg_write(gspca_dev, 0x2b, 0x9e);
  1124 + val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
  1125 + if (sd->sensor == SENSOR_OV767x) {
  1126 + sccb_reg_write(gspca_dev, 0x2a, 0x00);
  1127 + if (val)
  1128 + val = 0x9d; /* insert dummy to 25fps for 50Hz */
  1129 + }
  1130 + sccb_reg_write(gspca_dev, 0x2b, val);
788 1131 }
789 1132  
790 1133  
791 1134  
... ... @@ -805,12 +1148,7 @@
805 1148  
806 1149 cam->cam_mode = ov772x_mode;
807 1150 cam->nmodes = ARRAY_SIZE(ov772x_mode);
808   - cam->mode_framerates = ov772x_framerates;
809 1151  
810   - cam->bulk = 1;
811   - cam->bulk_size = 16384;
812   - cam->bulk_nurbs = 2;
813   -
814 1152 sd->frame_rate = 30;
815 1153  
816 1154 return 0;
817 1155  
... ... @@ -819,7 +1157,16 @@
819 1157 /* this function is called at probe and resume time */
820 1158 static int sd_init(struct gspca_dev *gspca_dev)
821 1159 {
  1160 + struct sd *sd = (struct sd *) gspca_dev;
822 1161 u16 sensor_id;
  1162 + static const struct reg_array bridge_init[NSENSORS] = {
  1163 + [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
  1164 + [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
  1165 + };
  1166 + static const struct reg_array sensor_init[NSENSORS] = {
  1167 + [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
  1168 + [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
  1169 + };
823 1170  
824 1171 /* reset bridge */
825 1172 ov534_reg_write(gspca_dev, 0xe7, 0x3a);
826 1173  
827 1174  
828 1175  
829 1176  
830 1177  
... ... @@ -840,35 +1187,82 @@
840 1187 sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
841 1188 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
842 1189  
  1190 + if ((sensor_id & 0xfff0) == 0x7670) {
  1191 + sd->sensor = SENSOR_OV767x;
  1192 + gspca_dev->ctrl_dis = (1 << GAIN) |
  1193 + (1 << AGC) |
  1194 + (1 << SHARPNESS); /* auto */
  1195 + sd->ctrls[BRIGHTNESS].min = -127;
  1196 + sd->ctrls[BRIGHTNESS].max = 127;
  1197 + sd->ctrls[BRIGHTNESS].def = 0;
  1198 + sd->ctrls[CONTRAST].max = 0x80;
  1199 + sd->ctrls[CONTRAST].def = 0x40;
  1200 + sd->ctrls[EXPOSURE].min = 0x08;
  1201 + sd->ctrls[EXPOSURE].max = 0x60;
  1202 + sd->ctrls[EXPOSURE].def = 0x13;
  1203 + sd->ctrls[SHARPNESS].max = 9;
  1204 + sd->ctrls[SHARPNESS].def = 4;
  1205 + sd->ctrls[HFLIP].def = 1;
  1206 + gspca_dev->cam.cam_mode = ov767x_mode;
  1207 + gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
  1208 + } else {
  1209 + sd->sensor = SENSOR_OV772x;
  1210 + gspca_dev->cam.bulk = 1;
  1211 + gspca_dev->cam.bulk_size = 16384;
  1212 + gspca_dev->cam.bulk_nurbs = 2;
  1213 + gspca_dev->cam.mode_framerates = ov772x_framerates;
  1214 + }
  1215 +
843 1216 /* initialize */
844   - reg_w_array(gspca_dev, bridge_init,
845   - ARRAY_SIZE(bridge_init));
  1217 + reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
  1218 + bridge_init[sd->sensor].len);
846 1219 ov534_set_led(gspca_dev, 1);
847   - sccb_w_array(gspca_dev, sensor_init,
848   - ARRAY_SIZE(sensor_init));
849   - ov534_reg_write(gspca_dev, 0xe0, 0x09);
850   - ov534_set_led(gspca_dev, 0);
851   - set_frame_rate(gspca_dev);
  1220 + sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
  1221 + sensor_init[sd->sensor].len);
  1222 + if (sd->sensor == SENSOR_OV767x)
  1223 + sd_start(gspca_dev);
  1224 + sd_stopN(gspca_dev);
  1225 +/* set_frame_rate(gspca_dev); */
852 1226  
853 1227 return gspca_dev->usb_err;
854 1228 }
855 1229  
856 1230 static int sd_start(struct gspca_dev *gspca_dev)
857 1231 {
  1232 + struct sd *sd = (struct sd *) gspca_dev;
858 1233 int mode;
  1234 + static const struct reg_array bridge_start[NSENSORS][2] = {
  1235 + [SENSOR_OV767x] = {{bridge_start_qvga_767x,
  1236 + ARRAY_SIZE(bridge_start_qvga_767x)},
  1237 + {bridge_start_vga_767x,
  1238 + ARRAY_SIZE(bridge_start_vga_767x)}},
  1239 + [SENSOR_OV772x] = {{bridge_start_qvga_772x,
  1240 + ARRAY_SIZE(bridge_start_qvga_772x)},
  1241 + {bridge_start_vga_772x,
  1242 + ARRAY_SIZE(bridge_start_vga_772x)}},
  1243 + };
  1244 + static const struct reg_array sensor_start[NSENSORS][2] = {
  1245 + [SENSOR_OV767x] = {{sensor_start_qvga_767x,
  1246 + ARRAY_SIZE(sensor_start_qvga_767x)},
  1247 + {sensor_start_vga_767x,
  1248 + ARRAY_SIZE(sensor_start_vga_767x)}},
  1249 + [SENSOR_OV772x] = {{sensor_start_qvga_772x,
  1250 + ARRAY_SIZE(sensor_start_qvga_772x)},
  1251 + {sensor_start_vga_772x,
  1252 + ARRAY_SIZE(sensor_start_vga_772x)}},
  1253 + };
859 1254  
860   - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
861   - if (mode != 0) { /* 320x240 */
862   - reg_w_array(gspca_dev, bridge_start_qvga,
863   - ARRAY_SIZE(bridge_start_qvga));
864   - sccb_w_array(gspca_dev, sensor_start_qvga,
865   - ARRAY_SIZE(sensor_start_qvga));
866   - } else { /* 640x480 */
867   - reg_w_array(gspca_dev, bridge_start_vga,
868   - ARRAY_SIZE(bridge_start_vga));
869   - sccb_w_array(gspca_dev, sensor_start_vga,
870   - ARRAY_SIZE(sensor_start_vga));
871   - }
  1255 + /* (from ms-win trace) */
  1256 + if (sd->sensor == SENSOR_OV767x)
  1257 + sccb_reg_write(gspca_dev, 0x1e, 0x04);
  1258 + /* black sun enable ? */
  1259 +
  1260 + mode = gspca_dev->curr_mode; /* 0: 320x240, 1: 640x480 */
  1261 + reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
  1262 + bridge_start[sd->sensor][mode].len);
  1263 + sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
  1264 + sensor_start[sd->sensor][mode].len);
  1265 +
872 1266 set_frame_rate(gspca_dev);
873 1267  
874 1268 if (!(gspca_dev->ctrl_dis & (1 << AGC)))
875 1269  
876 1270  
... ... @@ -913,9 +1307,11 @@
913 1307 __u32 this_pts;
914 1308 u16 this_fid;
915 1309 int remaining_len = len;
  1310 + int payload_len;
916 1311  
  1312 + payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
917 1313 do {
918   - len = min(remaining_len, 2048);
  1314 + len = min(remaining_len, payload_len);
919 1315  
920 1316 /* Payloads are prefixed with a UVC-style header. We
921 1317 consider a frame to start when the FID toggles, or the PTS
... ... @@ -955,8 +1351,9 @@
955 1351 /* If this packet is marked as EOF, end the frame */
956 1352 } else if (data[1] & UVC_STREAM_EOF) {
957 1353 sd->last_pts = 0;
958   - if (gspca_dev->image_len + len - 12 !=
959   - gspca_dev->width * gspca_dev->height * 2) {
  1354 + if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
  1355 + && gspca_dev->image_len + len - 12 !=
  1356 + gspca_dev->width * gspca_dev->height * 2) {
960 1357 PDEBUG(D_PACK, "wrong sized frame");
961 1358 goto discard;
962 1359 }
... ... @@ -1073,6 +1470,7 @@
1073 1470 /* -- module initialisation -- */
1074 1471 static const struct usb_device_id device_table[] = {
1075 1472 {USB_DEVICE(0x1415, 0x2000)},
  1473 + {USB_DEVICE(0x06f8, 0x3002)},
1076 1474 {}
1077 1475 };
1078 1476