diff options
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r-- | drivers/media/video/gspca/spca561.c | 105 |
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) | |||
549 | static void setexposure(struct gspca_dev *gspca_dev) | 549 | static 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) | |||
928 | static struct ctrl sd_ctrls_12a[] = { | 929 | static 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[] = { | |||
983 | static struct ctrl sd_ctrls_72a[] = { | 971 | static 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 | }; |
1051 | static const struct sd_desc sd_desc_72a = { | 1038 | static const struct sd_desc sd_desc_72a = { |
1052 | .name = MODULE_NAME, | 1039 | .name = MODULE_NAME, |