diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-09-03 15:47:32 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-09-03 17:36:36 -0400 |
commit | 7879d459f1601be742d0d63930d17cd4aac956fd (patch) | |
tree | 0dfcf9f60c015413bb5b507c99bb16186ebd191b /drivers/media/video/gspca/spca561.c | |
parent | a0b508c2d7d0de0e46555793e334e35381716825 (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.c | 596 |
1 files changed, 336 insertions, 260 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index a9f7c99e6f56..0a2b8bc5b855 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -32,85 +32,44 @@ MODULE_LICENSE("GPL"); | |||
32 | struct sd { | 32 | struct 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 */ | ||
46 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
50 | static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val); | ||
51 | static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val); | ||
52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
54 | |||
55 | static 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 | |||
114 | static struct v4l2_pix_format sif_mode[] = { | 73 | static 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 |
163 | enum { | ||
164 | Rev072A = 0, | ||
165 | Rev012A, | ||
166 | }; | ||
167 | 122 | ||
168 | static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value) | 123 | static 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 | ||
218 | static 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 | |||
224 | static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) | 173 | static 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 | ||
462 | static 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 ********************/ |
475 | static const __u16 Pb100_1map8300[][2] = { | 413 | static 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 | } |
567 | static void init_161rev12A(struct gspca_dev *gspca_dev) | 505 | static 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 */ |
619 | static int sd_open(struct gspca_dev *gspca_dev) | 560 | static 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"); | 566 | static 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 */ | ||
671 | static void setwhite(struct gspca_dev *gspca_dev) | 600 | static 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 */ | ||
622 | static 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 */ | ||
631 | static 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 | ||
699 | static void setautogain(struct gspca_dev *gspca_dev) | 639 | static 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 | ||
711 | static void sd_start(struct gspca_dev *gspca_dev) | 651 | static 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); | 688 | static 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 | ||
774 | static void sd_stopN(struct gspca_dev *gspca_dev) | 714 | static 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 */ | ||
790 | static void do_autogain(struct gspca_dev *gspca_dev) | 731 | static 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 */ | ||
898 | static void setbrightness(struct gspca_dev *gspca_dev) | 840 | static 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 | ||
918 | static void getbrightness(struct gspca_dev *gspca_dev) | 852 | static 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 */ | ||
943 | static void getcontrast(struct gspca_dev *gspca_dev) | 870 | static 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 */ | ||
969 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 889 | static 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 */ | ||
988 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 909 | static 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 */ |
1026 | static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) | 947 | static 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 */ | ||
966 | static 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 | |||
976 | static 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 */ | ||
985 | static 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 | |||
995 | static 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 */ | ||
1004 | static 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 | |||
1059 | static 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 */ |
1045 | static const struct sd_desc sd_desc = { | 1102 | static 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 | }; | ||
1115 | static 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 | }; |
1128 | static const struct sd_desc *sd_desc[2] = { | ||
1129 | &sd_desc_12a, | ||
1130 | &sd_desc_72a | ||
1131 | }; | ||
1058 | 1132 | ||
1059 | /* -- module initialisation -- */ | 1133 | /* -- module initialisation -- */ |
1060 | static const __devinitdata struct usb_device_id device_table[] = { | 1134 | static const __devinitdata struct usb_device_id device_table[] = { |
@@ -1082,7 +1156,9 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
1082 | static int sd_probe(struct usb_interface *intf, | 1156 | static 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 | ||