aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca561.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r--drivers/media/video/gspca/spca561.c105
1 files changed, 46 insertions, 59 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index c99c5e34e211..27e82b35f3e7 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -34,8 +34,8 @@ struct sd {
34 34
35 __u16 exposure; /* rev12a only */ 35 __u16 exposure; /* rev12a only */
36#define EXPOSURE_MIN 1 36#define EXPOSURE_MIN 1
37#define EXPOSURE_DEF 200 37#define EXPOSURE_DEF 700 /* == 10 fps */
38#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ 38#define EXPOSURE_MAX (2047 + 325) /* see setexposure */
39 39
40 __u8 contrast; /* rev72a only */ 40 __u8 contrast; /* rev72a only */
41#define CONTRAST_MIN 0x00 41#define CONTRAST_MIN 0x00
@@ -48,9 +48,9 @@ struct sd {
48#define BRIGHTNESS_MAX 0x3f 48#define BRIGHTNESS_MAX 0x3f
49 49
50 __u8 white; 50 __u8 white;
51#define WHITE_MIN 1 51#define HUE_MIN 1
52#define WHITE_DEF 0x40 52#define HUE_DEF 0x40
53#define WHITE_MAX 0x7f 53#define HUE_MAX 0x7f
54 54
55 __u8 autogain; 55 __u8 autogain;
56#define AUTOGAIN_MIN 0 56#define AUTOGAIN_MIN 0
@@ -58,9 +58,9 @@ struct sd {
58#define AUTOGAIN_MAX 1 58#define AUTOGAIN_MAX 1
59 59
60 __u8 gain; /* rev12a only */ 60 __u8 gain; /* rev12a only */
61#define GAIN_MIN 0x0 61#define GAIN_MIN 0
62#define GAIN_DEF 0x24 62#define GAIN_DEF 63
63#define GAIN_MAX 0x24 63#define GAIN_MAX 255
64 64
65#define EXPO12A_DEF 3 65#define EXPO12A_DEF 3
66 __u8 expo12a; /* expo/gain? for rev 12a */ 66 __u8 expo12a; /* expo/gain? for rev 12a */
@@ -461,7 +461,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
461 } 461 }
462 sd->brightness = BRIGHTNESS_DEF; 462 sd->brightness = BRIGHTNESS_DEF;
463 sd->contrast = CONTRAST_DEF; 463 sd->contrast = CONTRAST_DEF;
464 sd->white = WHITE_DEF; 464 sd->white = HUE_DEF;
465 sd->exposure = EXPOSURE_DEF; 465 sd->exposure = EXPOSURE_DEF;
466 sd->autogain = AUTOGAIN_DEF; 466 sd->autogain = AUTOGAIN_DEF;
467 sd->gain = GAIN_DEF; 467 sd->gain = GAIN_DEF;
@@ -549,8 +549,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
549static void setexposure(struct gspca_dev *gspca_dev) 549static void setexposure(struct gspca_dev *gspca_dev)
550{ 550{
551 struct sd *sd = (struct sd *) gspca_dev; 551 struct sd *sd = (struct sd *) gspca_dev;
552 int expo; 552 int i, expo = 0;
553 int clock_divider;
554 553
555 /* Register 0x8309 controls exposure for the spca561, 554 /* Register 0x8309 controls exposure for the spca561,
556 the basic exposure setting goes from 1-2047, where 1 is completely 555 the basic exposure setting goes from 1-2047, where 1 is completely
@@ -564,16 +563,22 @@ static void setexposure(struct gspca_dev *gspca_dev)
564 configure a divider for the base framerate which us used at the 563 configure a divider for the base framerate which us used at the
565 exposure setting of 1-300. These bits configure the base framerate 564 exposure setting of 1-300. These bits configure the base framerate
566 according to the following formula: fps = 60 / (value + 2) */ 565 according to the following formula: fps = 60 / (value + 2) */
567 if (sd->exposure < 2048) { 566
568 expo = sd->exposure; 567 /* We choose to use the high bits setting the fixed framerate divisor
569 clock_divider = 0; 568 asap, as setting high basic exposure setting without the fixed
570 } else { 569 divider in combination with high gains makes the cam stop */
571 /* Add 900 to make the 0 setting of the second part of the 570 int table[] = { 0, 450, 550, 625, EXPOSURE_MAX };
572 exposure equal to the 2047 setting of the first part. */ 571
573 expo = (sd->exposure - 2048) + 900; 572 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
574 clock_divider = 3; 573 if (sd->exposure <= table[i + 1]) {
574 expo = sd->exposure - table[i];
575 if (i)
576 expo += 300;
577 expo |= i << 11;
578 break;
579 }
575 } 580 }
576 expo |= clock_divider << 11; 581
577 gspca_dev->usb_buf[0] = expo; 582 gspca_dev->usb_buf[0] = expo;
578 gspca_dev->usb_buf[1] = expo >> 8; 583 gspca_dev->usb_buf[1] = expo >> 8;
579 reg_w_buf(gspca_dev, 0x8309, 2); 584 reg_w_buf(gspca_dev, 0x8309, 2);
@@ -584,7 +589,16 @@ static void setgain(struct gspca_dev *gspca_dev)
584{ 589{
585 struct sd *sd = (struct sd *) gspca_dev; 590 struct sd *sd = (struct sd *) gspca_dev;
586 591
587 gspca_dev->usb_buf[0] = sd->gain; 592 /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the
593 sensitivity when set, so 31 + one of them set == 63, and 15
594 with both of them set == 63 */
595 if (sd->gain < 64)
596 gspca_dev->usb_buf[0] = sd->gain;
597 else if (sd->gain < 128)
598 gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40;
599 else
600 gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0;
601
588 gspca_dev->usb_buf[1] = 0; 602 gspca_dev->usb_buf[1] = 0;
589 reg_w_buf(gspca_dev, 0x8335, 2); 603 reg_w_buf(gspca_dev, 0x8335, 2);
590} 604}
@@ -629,8 +643,7 @@ static int sd_start_12a(struct gspca_dev *gspca_dev)
629 reg_w_buf(gspca_dev, 0x8391, 8); 643 reg_w_buf(gspca_dev, 0x8391, 8);
630 reg_w_buf(gspca_dev, 0x8390, 8); 644 reg_w_buf(gspca_dev, 0x8390, 8);
631 setwhite(gspca_dev); 645 setwhite(gspca_dev);
632 setautogain(gspca_dev); 646 setgain(gspca_dev);
633/* setgain(gspca_dev); */
634 setexposure(gspca_dev); 647 setexposure(gspca_dev);
635 return 0; 648 return 0;
636} 649}
@@ -762,18 +775,6 @@ static void do_autogain(struct gspca_dev *gspca_dev)
762 i2c_write(gspca_dev, expotimes | pixelclk, 0x09); 775 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
763 } 776 }
764 break; 777 break;
765 case Rev012A:
766 reg_r(gspca_dev, 0x8330, 2);
767 if (gspca_dev->usb_buf[1] > 0x08) {
768 gspca_dev->usb_buf[0] = ++sd->expo12a;
769 gspca_dev->usb_buf[1] = 0;
770 reg_w_buf(gspca_dev, 0x8339, 2);
771 } else if (gspca_dev->usb_buf[1] < 0x02) {
772 gspca_dev->usb_buf[0] = --sd->expo12a;
773 gspca_dev->usb_buf[1] = 0;
774 reg_w_buf(gspca_dev, 0x8339, 2);
775 }
776 break;
777 } 778 }
778} 779}
779 780
@@ -928,13 +929,13 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
928static struct ctrl sd_ctrls_12a[] = { 929static struct ctrl sd_ctrls_12a[] = {
929 { 930 {
930 { 931 {
931 .id = V4L2_CID_DO_WHITE_BALANCE, 932 .id = V4L2_CID_HUE,
932 .type = V4L2_CTRL_TYPE_INTEGER, 933 .type = V4L2_CTRL_TYPE_INTEGER,
933 .name = "White Balance", 934 .name = "Hue",
934 .minimum = WHITE_MIN, 935 .minimum = HUE_MIN,
935 .maximum = WHITE_MAX, 936 .maximum = HUE_MAX,
936 .step = 1, 937 .step = 1,
937 .default_value = WHITE_DEF, 938 .default_value = HUE_DEF,
938 }, 939 },
939 .set = sd_setwhite, 940 .set = sd_setwhite,
940 .get = sd_getwhite, 941 .get = sd_getwhite,
@@ -954,19 +955,6 @@ static struct ctrl sd_ctrls_12a[] = {
954 }, 955 },
955 { 956 {
956 { 957 {
957 .id = V4L2_CID_AUTOGAIN,
958 .type = V4L2_CTRL_TYPE_BOOLEAN,
959 .name = "Auto Gain",
960 .minimum = AUTOGAIN_MIN,
961 .maximum = AUTOGAIN_MAX,
962 .step = 1,
963 .default_value = AUTOGAIN_DEF,
964 },
965 .set = sd_setautogain,
966 .get = sd_getautogain,
967 },
968 {
969 {
970 .id = V4L2_CID_GAIN, 958 .id = V4L2_CID_GAIN,
971 .type = V4L2_CTRL_TYPE_INTEGER, 959 .type = V4L2_CTRL_TYPE_INTEGER,
972 .name = "Gain", 960 .name = "Gain",
@@ -983,13 +971,13 @@ static struct ctrl sd_ctrls_12a[] = {
983static struct ctrl sd_ctrls_72a[] = { 971static struct ctrl sd_ctrls_72a[] = {
984 { 972 {
985 { 973 {
986 .id = V4L2_CID_DO_WHITE_BALANCE, 974 .id = V4L2_CID_HUE,
987 .type = V4L2_CTRL_TYPE_INTEGER, 975 .type = V4L2_CTRL_TYPE_INTEGER,
988 .name = "White Balance", 976 .name = "Hue",
989 .minimum = WHITE_MIN, 977 .minimum = HUE_MIN,
990 .maximum = WHITE_MAX, 978 .maximum = HUE_MAX,
991 .step = 1, 979 .step = 1,
992 .default_value = WHITE_DEF, 980 .default_value = HUE_DEF,
993 }, 981 },
994 .set = sd_setwhite, 982 .set = sd_setwhite,
995 .get = sd_getwhite, 983 .get = sd_getwhite,
@@ -1046,7 +1034,6 @@ static const struct sd_desc sd_desc_12a = {
1046 .stopN = sd_stopN, 1034 .stopN = sd_stopN,
1047 .stop0 = sd_stop0, 1035 .stop0 = sd_stop0,
1048 .pkt_scan = sd_pkt_scan, 1036 .pkt_scan = sd_pkt_scan,
1049/* .dq_callback = do_autogain, * fixme */
1050}; 1037};
1051static const struct sd_desc sd_desc_72a = { 1038static const struct sd_desc sd_desc_72a = {
1052 .name = MODULE_NAME, 1039 .name = MODULE_NAME,