aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca561.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-09-03 15:47:32 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-03 17:36:36 -0400
commit7879d459f1601be742d0d63930d17cd4aac956fd (patch)
tree0dfcf9f60c015413bb5b507c99bb16186ebd191b /drivers/media/video/gspca/spca561.c
parenta0b508c2d7d0de0e46555793e334e35381716825 (diff)
V4L/DVB (8672): gspca: Big rewrite of spca561.
Bug register/value inversions in USB exchanges. Exposure and gain controls added for rev 12a. Separate the functions and controls of the revisions 12a and 72a. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r--drivers/media/video/gspca/spca561.c596
1 files changed, 336 insertions, 260 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index a9f7c99e6f5..0a2b8bc5b85 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -32,85 +32,44 @@ MODULE_LICENSE("GPL");
32struct sd { 32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */ 33 struct gspca_dev gspca_dev; /* !! must be the first item */
34 34
35 unsigned short contrast; 35 __u16 contrast; /* rev72a only */
36 __u8 brightness; 36#define CONTRAST_MIN 0x0000
37 __u8 white; 37#define CONTRAST_DEF 0x2000
38#define CONTRAST_MAX 0x3fff
39
40 __u16 exposure; /* rev12a only */
41#define EXPOSURE_MIN 0x0120
42#define EXPOSURE_DEF 0x20ae
43#define EXPOSURE_MAX 0x5720
44
45 __u8 brightness; /* rev72a only */
46#define BRIGHTNESS_MIN 0
47#define BRIGHTNESS_DEF 32
48#define BRIGHTNESS_MAX 63
49
50 __u8 white; /* rev12a only */
51#define WHITE_MIN 0
52#define WHITE_DEF 0x40
53#define WHITE_MAX 0x7f
54
38 __u8 autogain; 55 __u8 autogain;
56#define AUTOGAIN_MIN 0
57#define AUTOGAIN_DEF 1
58#define AUTOGAIN_MAX 1
59
60 __u8 gain; /* rev12a only */
61#define GAIN_MIN 0x0
62#define GAIN_DEF 0x24
63#define GAIN_MAX 0x24
39 64
40 __u8 chip_revision; 65 __u8 chip_revision;
66#define Rev012A 0
67#define Rev072A 1
68
41 signed char ag_cnt; 69 signed char ag_cnt;
42#define AG_CNT_START 13 70#define AG_CNT_START 13
43}; 71};
44 72
45/* V4L2 controls supported by the driver */
46static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
47static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
48static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
54
55static struct ctrl sd_ctrls[] = {
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 63,
63 .step = 1,
64#define BRIGHTNESS_DEF 32
65 .default_value = BRIGHTNESS_DEF,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70 {
71 {
72 .id = V4L2_CID_CONTRAST,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Contrast",
75 .minimum = 0,
76 .maximum = 0x3fff,
77 .step = 1,
78#define CONTRAST_DEF 0x2000
79 .default_value = CONTRAST_DEF,
80 },
81 .set = sd_setcontrast,
82 .get = sd_getcontrast,
83 },
84 {
85 {
86 .id = V4L2_CID_DO_WHITE_BALANCE,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "While Balance",
89 .minimum = 0,
90 .maximum = 0x7f,
91 .step = 1,
92#define WHITE_DEF 40
93 .default_value = WHITE_DEF,
94 },
95 .set = sd_setwhite,
96 .get = sd_getwhite,
97 },
98 {
99 {
100 .id = V4L2_CID_AUTOGAIN,
101 .type = V4L2_CTRL_TYPE_BOOLEAN,
102 .name = "Auto Gain",
103 .minimum = 0,
104 .maximum = 1,
105 .step = 1,
106#define AUTOGAIN_DEF 1
107 .default_value = AUTOGAIN_DEF,
108 },
109 .set = sd_setautogain,
110 .get = sd_getautogain,
111 },
112};
113
114static struct v4l2_pix_format sif_mode[] = { 73static struct v4l2_pix_format sif_mode[] = {
115 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 74 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
116 .bytesperline = 160, 75 .bytesperline = 160,
@@ -160,12 +119,8 @@ static struct v4l2_pix_format sif_mode[] = {
160#define SPCA561_INDEX_I2C_BASE 0x8800 119#define SPCA561_INDEX_I2C_BASE 0x8800
161#define SPCA561_SNAPBIT 0x20 120#define SPCA561_SNAPBIT 0x20
162#define SPCA561_SNAPCTRL 0x40 121#define SPCA561_SNAPCTRL 0x40
163enum {
164 Rev072A = 0,
165 Rev012A,
166};
167 122
168static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value) 123static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
169{ 124{
170 int ret; 125 int ret;
171 126
@@ -215,12 +170,6 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
215 index, gspca_dev->usb_buf, len, 500); 170 index, gspca_dev->usb_buf, len, 500);
216} 171}
217 172
218static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode)
219{
220 reg_w_val(gspca_dev->dev, 0x92, 0x8804);
221 reg_w_val(gspca_dev->dev, mode, 0x8802);
222}
223
224static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) 173static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
225{ 174{
226 int retry = 60; 175 int retry = 60;
@@ -229,9 +178,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
229 178
230 DataLow = valeur; 179 DataLow = valeur;
231 DataHight = valeur >> 8; 180 DataHight = valeur >> 8;
232 reg_w_val(gspca_dev->dev, reg, 0x8801); 181 reg_w_val(gspca_dev->dev, 0x8801, reg);
233 reg_w_val(gspca_dev->dev, DataLow, 0x8805); 182 reg_w_val(gspca_dev->dev, 0x8805, DataLow);
234 reg_w_val(gspca_dev->dev, DataHight, 0x8800); 183 reg_w_val(gspca_dev->dev, 0x8800, DataHight);
235 while (retry--) { 184 while (retry--) {
236 reg_r(gspca_dev, 0x8803, 1); 185 reg_r(gspca_dev, 0x8803, 1);
237 if (!gspca_dev->usb_buf[0]) 186 if (!gspca_dev->usb_buf[0])
@@ -245,9 +194,9 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
245 __u8 value; 194 __u8 value;
246 __u8 vallsb; 195 __u8 vallsb;
247 196
248 reg_w_val(gspca_dev->dev, 0x92, 0x8804); 197 reg_w_val(gspca_dev->dev, 0x8804, 0x92);
249 reg_w_val(gspca_dev->dev, reg, 0x8801); 198 reg_w_val(gspca_dev->dev, 0x8801, reg);
250 reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802); 199 reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
251 while (retry--) { 200 while (retry--) {
252 reg_r(gspca_dev, 0x8803, 1); 201 reg_r(gspca_dev, 0x8803, 1);
253 if (!gspca_dev->usb_buf) 202 if (!gspca_dev->usb_buf)
@@ -459,17 +408,6 @@ static const __u16 spca561_init_data[][2] = {
459 {} 408 {}
460}; 409};
461 410
462static void sensor_reset(struct gspca_dev *gspca_dev)
463{
464 reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
465 reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
466 reg_w_val(gspca_dev->dev, 0x8112, 0x00);
467 reg_w_val(gspca_dev->dev, 0x8114, 0x00);
468 reg_w_val(gspca_dev->dev, 0x8118, 0x21);
469 i2c_init(gspca_dev, 0x14);
470 i2c_write(gspca_dev, 1, 0x0d);
471 i2c_write(gspca_dev, 0, 0x0d);
472}
473 411
474/******************** QC Express etch2 stuff ********************/ 412/******************** QC Express etch2 stuff ********************/
475static const __u16 Pb100_1map8300[][2] = { 413static const __u16 Pb100_1map8300[][2] = {
@@ -479,9 +417,9 @@ static const __u16 Pb100_1map8300[][2] = {
479 {0x8303, 0x0125}, /* image area */ 417 {0x8303, 0x0125}, /* image area */
480 {0x8304, 0x0169}, 418 {0x8304, 0x0169},
481 {0x8328, 0x000b}, 419 {0x8328, 0x000b},
482 {0x833c, 0x0001}, 420 {0x833c, 0x0001}, /*fixme: win:07*/
483 421
484 {0x832f, 0x0419}, 422 {0x832f, 0x1904}, /*fixme: was 0419*/
485 {0x8307, 0x00aa}, 423 {0x8307, 0x00aa},
486 {0x8301, 0x0003}, 424 {0x8301, 0x0003},
487 {0x8302, 0x000e}, 425 {0x8302, 0x000e},
@@ -547,7 +485,7 @@ static const __u16 spca561_161rev12A_data2[][2] = {
547 {0xdf, 0x863c}, /* df */ 485 {0xdf, 0x863c}, /* df */
548 {0xf0, 0x8505}, 486 {0xf0, 0x8505},
549 {0x32, 0x850a}, 487 {0x32, 0x850a},
550 {0x99, 0x8700}, /* - white balance - new */ 488/* {0x99, 0x8700}, * - white balance - new (removed) */
551 {} 489 {}
552}; 490};
553 491
@@ -566,9 +504,10 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev,
566} 504}
567static void init_161rev12A(struct gspca_dev *gspca_dev) 505static void init_161rev12A(struct gspca_dev *gspca_dev)
568{ 506{
569 sensor_reset(gspca_dev); 507/* sensor_reset(gspca_dev); (not in win) */
570 write_vector(gspca_dev, spca561_161rev12A_data1); 508 write_vector(gspca_dev, spca561_161rev12A_data1);
571 sensor_mapwrite(gspca_dev, Pb100_1map8300); 509 sensor_mapwrite(gspca_dev, Pb100_1map8300);
510/*fixme: should be in sd_start*/
572 write_vector(gspca_dev, spca561_161rev12A_data2); 511 write_vector(gspca_dev, spca561_161rev12A_data2);
573 sensor_mapwrite(gspca_dev, Pb100_2map8300); 512 sensor_mapwrite(gspca_dev, Pb100_2map8300);
574} 513}
@@ -605,32 +544,29 @@ static int sd_config(struct gspca_dev *gspca_dev,
605 cam->epaddr = 0x01; 544 cam->epaddr = 0x01;
606 gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ 545 gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
607 cam->cam_mode = sif_mode; 546 cam->cam_mode = sif_mode;
608 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; 547 cam->nmodes = ARRAY_SIZE(sif_mode);
609 548
610 sd->chip_revision = id->driver_info; 549 sd->chip_revision = id->driver_info;
611 sd->brightness = BRIGHTNESS_DEF; 550 sd->brightness = BRIGHTNESS_DEF;
612 sd->contrast = CONTRAST_DEF; 551 sd->contrast = CONTRAST_DEF;
613 sd->autogain = AUTOGAIN_DEF;
614 sd->white = WHITE_DEF; 552 sd->white = WHITE_DEF;
553 sd->exposure = EXPOSURE_DEF;
554 sd->autogain = AUTOGAIN_DEF;
555 sd->gain = GAIN_DEF;
615 return 0; 556 return 0;
616} 557}
617 558
618/* this function is called at open time */ 559/* this function is called at open time */
619static int sd_open(struct gspca_dev *gspca_dev) 560static int sd_open_12a(struct gspca_dev *gspca_dev)
620{ 561{
621 struct sd *sd = (struct sd *) gspca_dev; 562 PDEBUG(D_STREAM, "Chip revision: 012a");
622 563 init_161rev12A(gspca_dev);
623 switch (sd->chip_revision) { 564 return 0;
624 case Rev072A: 565}
625 PDEBUG(D_STREAM, "Chip revision id: 072a"); 566static int sd_open_72a(struct gspca_dev *gspca_dev)
626 write_vector(gspca_dev, spca561_init_data); 567{
627 break; 568 PDEBUG(D_STREAM, "Chip revision: 072a");
628 default: 569 write_vector(gspca_dev, spca561_init_data);
629/* case Rev012A: */
630 PDEBUG(D_STREAM, "Chip revision id: 012a");
631 init_161rev12A(gspca_dev);
632 break;
633 }
634 return 0; 570 return 0;
635} 571}
636 572
@@ -639,28 +575,20 @@ static void setcontrast(struct gspca_dev *gspca_dev)
639 struct sd *sd = (struct sd *) gspca_dev; 575 struct sd *sd = (struct sd *) gspca_dev;
640 struct usb_device *dev = gspca_dev->dev; 576 struct usb_device *dev = gspca_dev->dev;
641 __u8 lowb; 577 __u8 lowb;
642 int expotimes;
643 578
644 switch (sd->chip_revision) { 579 switch (sd->chip_revision) {
645 case Rev072A: 580 case Rev072A:
646 lowb = sd->contrast >> 8; 581 lowb = sd->contrast >> 8;
647 reg_w_val(dev, lowb, 0x8651); 582 reg_w_val(dev, 0x8651, lowb);
648 reg_w_val(dev, lowb, 0x8652); 583 reg_w_val(dev, 0x8652, lowb);
649 reg_w_val(dev, lowb, 0x8653); 584 reg_w_val(dev, 0x8653, lowb);
650 reg_w_val(dev, lowb, 0x8654); 585 reg_w_val(dev, 0x8654, lowb);
651 break; 586 break;
652 default: { 587 default: {
653/* case Rev012A: { */ 588/* case Rev012A: { */
654 __u8 Reg8391[] = 589 static const __u8 Reg8391[] =
655 { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; 590 { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
656 591
657 /* Write camera sensor settings */
658 expotimes = (sd->contrast >> 5) & 0x07ff;
659 /* exposure is in 8309 2b, range 0120 - 5720 */
660 Reg8391[0] = expotimes & 0xff; /* exposure */
661 Reg8391[1] = 0x18 | (expotimes >> 8);
662 Reg8391[2] = sd->brightness; /* gain */
663 /* gain in 8335, 2b range 0000 - 2400 */
664 reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); 592 reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
665 reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); 593 reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
666 break; 594 break;
@@ -668,32 +596,44 @@ static void setcontrast(struct gspca_dev *gspca_dev)
668 } 596 }
669} 597}
670 598
599/* rev12a only */
671static void setwhite(struct gspca_dev *gspca_dev) 600static void setwhite(struct gspca_dev *gspca_dev)
672{ 601{
673 struct sd *sd = (struct sd *) gspca_dev; 602 struct sd *sd = (struct sd *) gspca_dev;
674 __u16 white; 603 __u16 white;
675 __u8 reg8614, reg8616; 604 __u8 reg8614, reg8616;
676 605
677 switch (sd->chip_revision) { 606 white = sd->white;
678 case Rev072A: 607 if (sd->white == 0) {
679 /* no such hardware */ 608 PDEBUG(D_CONF, "Discarding null whiteness");
680 break; 609 return;
681 default:
682/* case Rev012A: */
683 white = sd->white;
684 if (sd->white == 0) {
685 PDEBUG(D_CONF, "Discarding null whiteness");
686 break;
687 }
688 /* try to emulate MS-win as possible */
689 if (white < 0x45)
690 reg8616 = white;
691 else
692 reg8616 = 0x93 + (white >> 2);
693 reg8614 = 0x28 + (white >> 4);
694 reg_w_val(gspca_dev->dev, reg8616, 0x8616);
695 reg_w_val(gspca_dev->dev, reg8614, 0x8614);
696 } 610 }
611 /* try to emulate MS-win as possible */
612 if (white < 0x45)
613 reg8616 = white;
614 else
615 reg8616 = 0x93 + (white >> 2);
616 reg8614 = 0x28 + (white >> 4);
617 reg_w_val(gspca_dev->dev, 0x8616, reg8616);
618 reg_w_val(gspca_dev->dev, 0x8614, reg8614);
619}
620
621/* rev 12a only */
622static void setexposure(struct gspca_dev *gspca_dev)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625 struct usb_device *dev = gspca_dev->dev;
626
627 reg_w_val(dev, 0x8309, sd->gain);
628}
629
630/* rev 12a only */
631static void setgain(struct gspca_dev *gspca_dev)
632{
633 struct sd *sd = (struct sd *) gspca_dev;
634 struct usb_device *dev = gspca_dev->dev;
635
636 reg_w_val(dev, 0x8335, sd->gain);
697} 637}
698 638
699static void setautogain(struct gspca_dev *gspca_dev) 639static void setautogain(struct gspca_dev *gspca_dev)
@@ -708,67 +648,67 @@ static void setautogain(struct gspca_dev *gspca_dev)
708 } 648 }
709} 649}
710 650
711static void sd_start(struct gspca_dev *gspca_dev) 651static void sd_start_12a(struct gspca_dev *gspca_dev)
712{ 652{
713 struct sd *sd = (struct sd *) gspca_dev;
714 struct usb_device *dev = gspca_dev->dev; 653 struct usb_device *dev = gspca_dev->dev;
715 int Clck; 654 int Clck;
716 __u8 Reg8307[] = { 0xaa, 0x00 }; 655 __u8 Reg8307[] = { 0xaa, 0x00 };
717 int mode; 656 int mode;
718 657
719 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; 658 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
720 switch (sd->chip_revision) { 659 switch (mode) {
721 case Rev072A: 660 case 0:
722 switch (mode) { 661 case 1:
723 default: 662 Clck = 0x8a;
724/* case 0: 663 break;
725 case 1: */ 664 case 2:
726 Clck = 0x25; 665 Clck = 0x85;
727 break;
728 case 2:
729 Clck = 0x22;
730 break;
731 case 3:
732 Clck = 0x21;
733 break;
734 }
735 reg_w_val(dev, 0x8500, mode); /* mode */
736 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
737 reg_w_val(dev, 0x8112, 0x10 | 0x20);
738 setautogain(gspca_dev);
739 break; 666 break;
740 default: 667 default:
741/* case Rev012A: */ 668 Clck = 0x83;
742 switch (mode) { 669 break;
743 case 0: 670 }
744 case 1: 671 if (mode <= 1) {
745 Clck = 0x8a; 672 /* Use compression on 320x240 and above */
746 break; 673 reg_w_val(dev, 0x8500, 0x10 | mode);
747 case 2: 674 } else {
748 Clck = 0x85; 675 /* I couldn't get the compression to work below 320x240
749 break; 676 * Fortunately at these resolutions the bandwidth
750 default: 677 * is sufficient to push raw frames at ~20fps */
751 Clck = 0x83; 678 reg_w_val(dev, 0x8500, mode);
752 break; 679 } /* -- qq@kuku.eu.org */
753 } 680 reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
754 if (mode <= 1) { 681 reg_w_val(gspca_dev->dev, 0x8700, Clck);
755 /* Use compression on 320x240 and above */ 682 /* 0x8f 0x85 0x27 clock */
756 reg_w_val(dev, 0x8500, 0x10 | mode); 683 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
757 } else { 684 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
758 /* I couldn't get the compression to work below 320x240 685 setcontrast(gspca_dev);
759 * Fortunately at these resolutions the bandwidth 686 setwhite(gspca_dev);
760 * is sufficient to push raw frames at ~20fps */ 687}
761 reg_w_val(dev, 0x8500, mode); 688static void sd_start_72a(struct gspca_dev *gspca_dev)
762 } /* -- qq@kuku.eu.org */ 689{
763 reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); 690 struct usb_device *dev = gspca_dev->dev;
764 reg_w_val(gspca_dev->dev, 0x8700, Clck); 691 int Clck;
765 /* 0x8f 0x85 0x27 clock */ 692 int mode;
766 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); 693
767 reg_w_val(gspca_dev->dev, 0x850b, 0x03); 694 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
768 setcontrast(gspca_dev); 695 switch (mode) {
769 setwhite(gspca_dev); 696 default:
697/* case 0:
698 case 1: */
699 Clck = 0x25;
700 break;
701 case 2:
702 Clck = 0x22;
703 break;
704 case 3:
705 Clck = 0x21;
770 break; 706 break;
771 } 707 }
708 reg_w_val(dev, 0x8500, mode); /* mode */
709 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
710 reg_w_val(dev, 0x8112, 0x10 | 0x20);
711 setautogain(gspca_dev);
772} 712}
773 713
774static void sd_stopN(struct gspca_dev *gspca_dev) 714static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -787,6 +727,7 @@ static void sd_close(struct gspca_dev *gspca_dev)
787 reg_w_val(gspca_dev->dev, 0x8114, 0); 727 reg_w_val(gspca_dev->dev, 0x8114, 0);
788} 728}
789 729
730/* rev72a only */
790static void do_autogain(struct gspca_dev *gspca_dev) 731static void do_autogain(struct gspca_dev *gspca_dev)
791{ 732{
792 struct sd *sd = (struct sd *) gspca_dev; 733 struct sd *sd = (struct sd *) gspca_dev;
@@ -895,24 +836,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
895 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); 836 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
896} 837}
897 838
839/* rev 72a only */
898static void setbrightness(struct gspca_dev *gspca_dev) 840static void setbrightness(struct gspca_dev *gspca_dev)
899{ 841{
900 struct sd *sd = (struct sd *) gspca_dev; 842 struct sd *sd = (struct sd *) gspca_dev;
901 __u8 value; 843 __u8 value;
902 844
903 switch (sd->chip_revision) { 845 value = sd->brightness;
904 case Rev072A: 846 reg_w_val(gspca_dev->dev, 0x8611, value);
905 value = sd->brightness; 847 reg_w_val(gspca_dev->dev, 0x8612, value);
906 reg_w_val(gspca_dev->dev, value, 0x8611); 848 reg_w_val(gspca_dev->dev, 0x8613, value);
907 reg_w_val(gspca_dev->dev, value, 0x8612); 849 reg_w_val(gspca_dev->dev, 0x8614, value);
908 reg_w_val(gspca_dev->dev, value, 0x8613);
909 reg_w_val(gspca_dev->dev, value, 0x8614);
910 break;
911 default:
912/* case Rev012A: */
913 setcontrast(gspca_dev);
914 break;
915 }
916} 850}
917 851
918static void getbrightness(struct gspca_dev *gspca_dev) 852static void getbrightness(struct gspca_dev *gspca_dev)
@@ -920,52 +854,38 @@ static void getbrightness(struct gspca_dev *gspca_dev)
920 struct sd *sd = (struct sd *) gspca_dev; 854 struct sd *sd = (struct sd *) gspca_dev;
921 __u16 tot; 855 __u16 tot;
922 856
923 switch (sd->chip_revision) { 857 tot = 0;
924 case Rev072A: 858 reg_r(gspca_dev, 0x8611, 1);
925 tot = 0; 859 tot += gspca_dev->usb_buf[0];
926 reg_r(gspca_dev, 0x8611, 1); 860 reg_r(gspca_dev, 0x8612, 1);
927 tot += gspca_dev->usb_buf[0]; 861 tot += gspca_dev->usb_buf[0];
928 reg_r(gspca_dev, 0x8612, 1); 862 reg_r(gspca_dev, 0x8613, 1);
929 tot += gspca_dev->usb_buf[0]; 863 tot += gspca_dev->usb_buf[0];
930 reg_r(gspca_dev, 0x8613, 1); 864 reg_r(gspca_dev, 0x8614, 1);
931 tot += gspca_dev->usb_buf[0]; 865 tot += gspca_dev->usb_buf[0];
932 reg_r(gspca_dev, 0x8614, 1); 866 sd->brightness = tot >> 2;
933 tot += gspca_dev->usb_buf[0];
934 sd->brightness = tot >> 2;
935 break;
936 default:
937/* case Rev012A: */
938 /* no way to read sensor settings */
939 break;
940 }
941} 867}
942 868
869/* rev72a only */
943static void getcontrast(struct gspca_dev *gspca_dev) 870static void getcontrast(struct gspca_dev *gspca_dev)
944{ 871{
945 struct sd *sd = (struct sd *) gspca_dev; 872 struct sd *sd = (struct sd *) gspca_dev;
946 __u16 tot; 873 __u16 tot;
947 874
948 switch (sd->chip_revision) { 875 tot = 0;
949 case Rev072A: 876 reg_r(gspca_dev, 0x8651, 1);
950 tot = 0; 877 tot += gspca_dev->usb_buf[0];
951 reg_r(gspca_dev, 0x8651, 1); 878 reg_r(gspca_dev, 0x8652, 1);
952 tot += gspca_dev->usb_buf[0]; 879 tot += gspca_dev->usb_buf[0];
953 reg_r(gspca_dev, 0x8652, 1); 880 reg_r(gspca_dev, 0x8653, 1);
954 tot += gspca_dev->usb_buf[0]; 881 tot += gspca_dev->usb_buf[0];
955 reg_r(gspca_dev, 0x8653, 1); 882 reg_r(gspca_dev, 0x8654, 1);
956 tot += gspca_dev->usb_buf[0]; 883 tot += gspca_dev->usb_buf[0];
957 reg_r(gspca_dev, 0x8654, 1); 884 sd->contrast = tot << 6;
958 tot += gspca_dev->usb_buf[0];
959 sd->contrast = tot << 6;
960 break;
961 default:
962/* case Rev012A: */
963 /* no way to read sensor settings */
964 break;
965 }
966 PDEBUG(D_CONF, "get contrast %d", sd->contrast); 885 PDEBUG(D_CONF, "get contrast %d", sd->contrast);
967} 886}
968 887
888/* rev 72a only */
969static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 889static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
970{ 890{
971 struct sd *sd = (struct sd *) gspca_dev; 891 struct sd *sd = (struct sd *) gspca_dev;
@@ -985,6 +905,7 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
985 return 0; 905 return 0;
986} 906}
987 907
908/* rev 72a only */
988static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 909static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
989{ 910{
990 struct sd *sd = (struct sd *) gspca_dev; 911 struct sd *sd = (struct sd *) gspca_dev;
@@ -1022,7 +943,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1022 return 0; 943 return 0;
1023} 944}
1024 945
1025/* white balance - new */ 946/* rev12a only */
1026static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) 947static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
1027{ 948{
1028 struct sd *sd = (struct sd *) gspca_dev; 949 struct sd *sd = (struct sd *) gspca_dev;
@@ -1041,20 +962,173 @@ static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
1041 return 0; 962 return 0;
1042} 963}
1043 964
965/* rev12a only */
966static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
967{
968 struct sd *sd = (struct sd *) gspca_dev;
969
970 sd->exposure = val;
971 if (gspca_dev->streaming)
972 setexposure(gspca_dev);
973 return 0;
974}
975
976static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
977{
978 struct sd *sd = (struct sd *) gspca_dev;
979
980 *val = sd->exposure;
981 return 0;
982}
983
984/* rev12a only */
985static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 sd->gain = val;
990 if (gspca_dev->streaming)
991 setgain(gspca_dev);
992 return 0;
993}
994
995static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 *val = sd->gain;
1000 return 0;
1001}
1002
1003/* control tables */
1004static struct ctrl sd_ctrls_12a[] = {
1005 {
1006 {
1007 .id = V4L2_CID_DO_WHITE_BALANCE,
1008 .type = V4L2_CTRL_TYPE_INTEGER,
1009 .name = "While Balance",
1010 .minimum = WHITE_MIN,
1011 .maximum = WHITE_MAX,
1012 .step = 1,
1013 .default_value = WHITE_DEF,
1014 },
1015 .set = sd_setwhite,
1016 .get = sd_getwhite,
1017 },
1018 {
1019 {
1020 .id = V4L2_CID_EXPOSURE,
1021 .type = V4L2_CTRL_TYPE_INTEGER,
1022 .name = "Exposure",
1023 .minimum = EXPOSURE_MIN,
1024 .maximum = EXPOSURE_MAX,
1025 .step = 1,
1026 .default_value = EXPOSURE_DEF,
1027 },
1028 .set = sd_setexposure,
1029 .get = sd_getexposure,
1030 },
1031 {
1032 {
1033 .id = V4L2_CID_AUTOGAIN,
1034 .type = V4L2_CTRL_TYPE_BOOLEAN,
1035 .name = "Auto Gain",
1036 .minimum = AUTOGAIN_MIN,
1037 .maximum = AUTOGAIN_MAX,
1038 .step = 1,
1039 .default_value = AUTOGAIN_DEF,
1040 },
1041 .set = sd_setautogain,
1042 .get = sd_getautogain,
1043 },
1044 {
1045 {
1046 .id = V4L2_CID_GAIN,
1047 .type = V4L2_CTRL_TYPE_INTEGER,
1048 .name = "Gain",
1049 .minimum = GAIN_MIN,
1050 .maximum = GAIN_MAX,
1051 .step = 1,
1052 .default_value = GAIN_DEF,
1053 },
1054 .set = sd_setgain,
1055 .get = sd_getgain,
1056 },
1057};
1058
1059static struct ctrl sd_ctrls_72a[] = {
1060 {
1061 {
1062 .id = V4L2_CID_BRIGHTNESS,
1063 .type = V4L2_CTRL_TYPE_INTEGER,
1064 .name = "Brightness",
1065 .minimum = BRIGHTNESS_MIN,
1066 .maximum = BRIGHTNESS_MAX,
1067 .step = 1,
1068 .default_value = BRIGHTNESS_DEF,
1069 },
1070 .set = sd_setbrightness,
1071 .get = sd_getbrightness,
1072 },
1073 {
1074 {
1075 .id = V4L2_CID_CONTRAST,
1076 .type = V4L2_CTRL_TYPE_INTEGER,
1077 .name = "Contrast",
1078 .minimum = CONTRAST_MIN,
1079 .maximum = CONTRAST_MAX,
1080 .step = 1,
1081 .default_value = CONTRAST_DEF,
1082 },
1083 .set = sd_setcontrast,
1084 .get = sd_getcontrast,
1085 },
1086 {
1087 {
1088 .id = V4L2_CID_AUTOGAIN,
1089 .type = V4L2_CTRL_TYPE_BOOLEAN,
1090 .name = "Auto Gain",
1091 .minimum = AUTOGAIN_MIN,
1092 .maximum = AUTOGAIN_MAX,
1093 .step = 1,
1094 .default_value = AUTOGAIN_DEF,
1095 },
1096 .set = sd_setautogain,
1097 .get = sd_getautogain,
1098 },
1099};
1100
1044/* sub-driver description */ 1101/* sub-driver description */
1045static const struct sd_desc sd_desc = { 1102static const struct sd_desc sd_desc_12a = {
1046 .name = MODULE_NAME, 1103 .name = MODULE_NAME,
1047 .ctrls = sd_ctrls, 1104 .ctrls = sd_ctrls_12a,
1048 .nctrls = ARRAY_SIZE(sd_ctrls), 1105 .nctrls = ARRAY_SIZE(sd_ctrls_12a),
1049 .config = sd_config, 1106 .config = sd_config,
1050 .open = sd_open, 1107 .open = sd_open_12a,
1051 .start = sd_start, 1108 .start = sd_start_12a,
1109 .stopN = sd_stopN,
1110 .stop0 = sd_stop0,
1111 .close = sd_close,
1112 .pkt_scan = sd_pkt_scan,
1113/* .dq_callback = do_autogain, * fixme */
1114};
1115static const struct sd_desc sd_desc_72a = {
1116 .name = MODULE_NAME,
1117 .ctrls = sd_ctrls_72a,
1118 .nctrls = ARRAY_SIZE(sd_ctrls_72a),
1119 .config = sd_config,
1120 .open = sd_open_72a,
1121 .start = sd_start_72a,
1052 .stopN = sd_stopN, 1122 .stopN = sd_stopN,
1053 .stop0 = sd_stop0, 1123 .stop0 = sd_stop0,
1054 .close = sd_close, 1124 .close = sd_close,
1055 .pkt_scan = sd_pkt_scan, 1125 .pkt_scan = sd_pkt_scan,
1056 .dq_callback = do_autogain, 1126 .dq_callback = do_autogain,
1057}; 1127};
1128static const struct sd_desc *sd_desc[2] = {
1129 &sd_desc_12a,
1130 &sd_desc_72a
1131};
1058 1132
1059/* -- module initialisation -- */ 1133/* -- module initialisation -- */
1060static const __devinitdata struct usb_device_id device_table[] = { 1134static const __devinitdata struct usb_device_id device_table[] = {
@@ -1082,7 +1156,9 @@ MODULE_DEVICE_TABLE(usb, device_table);
1082static int sd_probe(struct usb_interface *intf, 1156static int sd_probe(struct usb_interface *intf,
1083 const struct usb_device_id *id) 1157 const struct usb_device_id *id)
1084{ 1158{
1085 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1159 return gspca_dev_probe(intf, id,
1160 sd_desc[id->driver_info],
1161 sizeof(struct sd),
1086 THIS_MODULE); 1162 THIS_MODULE);
1087} 1163}
1088 1164