diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-12-18 10:38:15 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:39:41 -0500 |
commit | 5b7ed28ec5deb57f790e38af8d813310b830743c (patch) | |
tree | 2472a21d3cc74faf1421aaf11732dbd14fe63423 /drivers/media/video/gspca/spca561.c | |
parent | f4b59e353239d3c8e2456a986e42f4c87cfcef9f (diff) |
V4L/DVB (9987): gspca - spca561: Control changes for Rev72a.
- move the rev12a sequence from setcontrast to end of start
- add the white balance control for rev72a
- adjust the contrast formula
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r-- | drivers/media/video/gspca/spca561.c | 142 |
1 files changed, 82 insertions, 60 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index ee24629f0f5c..b31772c6ed32 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -32,22 +32,22 @@ 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 | __u16 contrast; /* rev72a only */ | ||
36 | #define CONTRAST_MIN 0x0000 | ||
37 | #define CONTRAST_DEF 0x2000 | ||
38 | #define CONTRAST_MAX 0x3fff | ||
39 | |||
40 | __u16 exposure; /* rev12a only */ | 35 | __u16 exposure; /* rev12a only */ |
41 | #define EXPOSURE_MIN 1 | 36 | #define EXPOSURE_MIN 1 |
42 | #define EXPOSURE_DEF 200 | 37 | #define EXPOSURE_DEF 200 |
43 | #define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ | 38 | #define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ |
44 | 39 | ||
40 | __u8 contrast; /* rev72a only */ | ||
41 | #define CONTRAST_MIN 0x00 | ||
42 | #define CONTRAST_DEF 0x20 | ||
43 | #define CONTRAST_MAX 0x3f | ||
44 | |||
45 | __u8 brightness; /* rev72a only */ | 45 | __u8 brightness; /* rev72a only */ |
46 | #define BRIGHTNESS_MIN 0 | 46 | #define BRIGHTNESS_MIN 0 |
47 | #define BRIGHTNESS_DEF 32 | 47 | #define BRIGHTNESS_DEF 0x20 |
48 | #define BRIGHTNESS_MAX 63 | 48 | #define BRIGHTNESS_MAX 0x3f |
49 | 49 | ||
50 | __u8 white; /* rev12a only */ | 50 | __u8 white; |
51 | #define WHITE_MIN 1 | 51 | #define WHITE_MIN 1 |
52 | #define WHITE_DEF 0x40 | 52 | #define WHITE_DEF 0x40 |
53 | #define WHITE_MAX 0x7f | 53 | #define WHITE_MAX 0x7f |
@@ -218,10 +218,11 @@ static const __u16 rev72a_init_data[][2] = { | |||
218 | {0x0004, 0x8612}, /* Gr offset for white balance */ | 218 | {0x0004, 0x8612}, /* Gr offset for white balance */ |
219 | {0x0007, 0x8613}, /* B offset for white balance */ | 219 | {0x0007, 0x8613}, /* B offset for white balance */ |
220 | {0x0000, 0x8614}, /* Gb offset for white balance */ | 220 | {0x0000, 0x8614}, /* Gb offset for white balance */ |
221 | {0x008c, 0x8651}, /* R gain for white balance */ | 221 | /* from ms-win */ |
222 | {0x008c, 0x8652}, /* Gr gain for white balance */ | 222 | {0x0035, 0x8651}, /* R gain for white balance */ |
223 | {0x00b5, 0x8653}, /* B gain for white balance */ | 223 | {0x0040, 0x8652}, /* Gr gain for white balance */ |
224 | {0x008c, 0x8654}, /* Gb gain for white balance */ | 224 | {0x005f, 0x8653}, /* B gain for white balance */ |
225 | {0x0040, 0x8654}, /* Gb gain for white balance */ | ||
225 | {0x0002, 0x8502}, /* Maximum average bit rate stuff */ | 226 | {0x0002, 0x8502}, /* Maximum average bit rate stuff */ |
226 | 227 | ||
227 | {0x0011, 0x8802}, | 228 | {0x0011, 0x8802}, |
@@ -591,46 +592,60 @@ static int sd_init_72a(struct gspca_dev *gspca_dev) | |||
591 | return 0; | 592 | return 0; |
592 | } | 593 | } |
593 | 594 | ||
594 | static void setcontrast(struct gspca_dev *gspca_dev) | 595 | /* rev 72a only */ |
596 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
595 | { | 597 | { |
596 | struct sd *sd = (struct sd *) gspca_dev; | 598 | struct sd *sd = (struct sd *) gspca_dev; |
597 | struct usb_device *dev = gspca_dev->dev; | 599 | struct usb_device *dev = gspca_dev->dev; |
598 | __u8 lowb; | 600 | __u8 value; |
599 | 601 | ||
600 | switch (sd->chip_revision) { | 602 | value = sd->brightness; |
601 | case Rev072A: | 603 | |
602 | lowb = sd->contrast >> 8; | 604 | /* offsets for white balance */ |
603 | reg_w_val(dev, 0x8651, lowb); | 605 | reg_w_val(dev, 0x8611, value); /* R */ |
604 | reg_w_val(dev, 0x8652, lowb); | 606 | reg_w_val(dev, 0x8612, value); /* Gr */ |
605 | reg_w_val(dev, 0x8653, lowb); | 607 | reg_w_val(dev, 0x8613, value); /* B */ |
606 | reg_w_val(dev, 0x8654, lowb); | 608 | reg_w_val(dev, 0x8614, value); /* Gb */ |
607 | break; | ||
608 | default: { | ||
609 | /* case Rev012A: { */ | ||
610 | static const __u8 Reg8391[] = | ||
611 | { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 }; | ||
612 | |||
613 | memcpy(gspca_dev->usb_buf, Reg8391, 8); | ||
614 | reg_w_buf(gspca_dev, 0x8391, 8); | ||
615 | reg_w_buf(gspca_dev, 0x8390, 8); | ||
616 | break; | ||
617 | } | ||
618 | } | ||
619 | } | 609 | } |
620 | 610 | ||
621 | /* rev12a only */ | ||
622 | static void setwhite(struct gspca_dev *gspca_dev) | 611 | static void setwhite(struct gspca_dev *gspca_dev) |
623 | { | 612 | { |
624 | struct sd *sd = (struct sd *) gspca_dev; | 613 | struct sd *sd = (struct sd *) gspca_dev; |
625 | __u16 white; | 614 | __u16 white; |
626 | __u8 reg8614, reg8616; | 615 | __u8 blue, red; |
616 | __u16 reg; | ||
627 | 617 | ||
628 | white = sd->white; | ||
629 | /* try to emulate MS-win as possible */ | 618 | /* try to emulate MS-win as possible */ |
630 | reg8616 = 0x90 - white * 5 / 8; | 619 | white = sd->white; |
631 | reg_w_val(gspca_dev->dev, 0x8616, reg8616); | 620 | red = 0x20 + white * 3 / 8; |
632 | reg8614 = 0x20 + white * 3 / 8; | 621 | blue = 0x90 - white * 5 / 8; |
633 | reg_w_val(gspca_dev->dev, 0x8614, reg8614); | 622 | if (sd->chip_revision == Rev012A) { |
623 | reg = 0x8614; | ||
624 | } else { | ||
625 | reg = 0x8651; | ||
626 | red += sd->contrast - 0x20; | ||
627 | blue += sd->contrast - 0x20; | ||
628 | } | ||
629 | reg_w_val(gspca_dev->dev, reg, red); | ||
630 | reg_w_val(gspca_dev->dev, reg + 2, blue); | ||
631 | } | ||
632 | |||
633 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
634 | { | ||
635 | struct sd *sd = (struct sd *) gspca_dev; | ||
636 | struct usb_device *dev = gspca_dev->dev; | ||
637 | __u8 value; | ||
638 | |||
639 | if (sd->chip_revision != Rev072A) | ||
640 | return; | ||
641 | value = sd->contrast + 0x20; | ||
642 | |||
643 | /* gains for white balance */ | ||
644 | setwhite(gspca_dev); | ||
645 | /* reg_w_val(dev, 0x8651, value); * R - done by setwhite */ | ||
646 | reg_w_val(dev, 0x8652, value); /* Gr */ | ||
647 | /* reg_w_val(dev, 0x8653, value); * B - done by setwhite */ | ||
648 | reg_w_val(dev, 0x8654, value); /* Gb */ | ||
634 | } | 649 | } |
635 | 650 | ||
636 | /* rev 12a only */ | 651 | /* rev 12a only */ |
@@ -690,9 +705,9 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
690 | static int sd_start_12a(struct gspca_dev *gspca_dev) | 705 | static int sd_start_12a(struct gspca_dev *gspca_dev) |
691 | { | 706 | { |
692 | struct usb_device *dev = gspca_dev->dev; | 707 | struct usb_device *dev = gspca_dev->dev; |
693 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ | ||
694 | __u8 Reg8307[] = { 0xaa, 0x00 }; | ||
695 | int mode; | 708 | int mode; |
709 | static const __u8 Reg8391[8] = | ||
710 | {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00}; | ||
696 | 711 | ||
697 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 712 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; |
698 | if (mode <= 1) { | 713 | if (mode <= 1) { |
@@ -705,15 +720,20 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) | |||
705 | reg_w_val(dev, 0x8500, mode); | 720 | reg_w_val(dev, 0x8500, mode); |
706 | } /* -- qq@kuku.eu.org */ | 721 | } /* -- qq@kuku.eu.org */ |
707 | 722 | ||
708 | memcpy(gspca_dev->usb_buf, Reg8307, sizeof Reg8307); | 723 | gspca_dev->usb_buf[0] = 0xaa; |
709 | reg_w_buf(gspca_dev, 0x8307, sizeof Reg8307); | 724 | gspca_dev->usb_buf[1] = 0x00; |
710 | reg_w_val(gspca_dev->dev, 0x8700, Clck); | 725 | reg_w_buf(gspca_dev, 0x8307, 2); |
726 | /* clock - lower 0x8X values lead to fps > 30 */ | ||
727 | reg_w_val(gspca_dev->dev, 0x8700, 0x8a); | ||
711 | /* 0x8f 0x85 0x27 clock */ | 728 | /* 0x8f 0x85 0x27 clock */ |
712 | reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); | 729 | reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); |
713 | reg_w_val(gspca_dev->dev, 0x850b, 0x03); | 730 | reg_w_val(gspca_dev->dev, 0x850b, 0x03); |
714 | setcontrast(gspca_dev); | 731 | memcpy(gspca_dev->usb_buf, Reg8391, 8); |
732 | reg_w_buf(gspca_dev, 0x8391, 8); | ||
733 | reg_w_buf(gspca_dev, 0x8390, 8); | ||
715 | setwhite(gspca_dev); | 734 | setwhite(gspca_dev); |
716 | setautogain(gspca_dev); | 735 | setautogain(gspca_dev); |
736 | /* setgain(gspca_dev); */ | ||
717 | setexposure(gspca_dev); | 737 | setexposure(gspca_dev); |
718 | return 0; | 738 | return 0; |
719 | } | 739 | } |
@@ -740,6 +760,9 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) | |||
740 | reg_w_val(dev, 0x8500, mode); /* mode */ | 760 | reg_w_val(dev, 0x8500, mode); /* mode */ |
741 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ | 761 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ |
742 | reg_w_val(dev, 0x8112, 0x10 | 0x20); | 762 | reg_w_val(dev, 0x8112, 0x10 | 0x20); |
763 | setcontrast(gspca_dev); | ||
764 | /* setbrightness(gspca_dev); * fixme: bad values */ | ||
765 | setwhite(gspca_dev); | ||
743 | setautogain(gspca_dev); | 766 | setautogain(gspca_dev); |
744 | return 0; | 767 | return 0; |
745 | } | 768 | } |
@@ -888,19 +911,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
888 | } | 911 | } |
889 | 912 | ||
890 | /* rev 72a only */ | 913 | /* rev 72a only */ |
891 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
892 | { | ||
893 | struct sd *sd = (struct sd *) gspca_dev; | ||
894 | __u8 value; | ||
895 | |||
896 | value = sd->brightness; | ||
897 | reg_w_val(gspca_dev->dev, 0x8611, value); | ||
898 | reg_w_val(gspca_dev->dev, 0x8612, value); | ||
899 | reg_w_val(gspca_dev->dev, 0x8613, value); | ||
900 | reg_w_val(gspca_dev->dev, 0x8614, value); | ||
901 | } | ||
902 | |||
903 | /* rev 72a only */ | ||
904 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 914 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
905 | { | 915 | { |
906 | struct sd *sd = (struct sd *) gspca_dev; | 916 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -956,7 +966,6 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
956 | return 0; | 966 | return 0; |
957 | } | 967 | } |
958 | 968 | ||
959 | /* rev12a only */ | ||
960 | static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) | 969 | static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) |
961 | { | 970 | { |
962 | struct sd *sd = (struct sd *) gspca_dev; | 971 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1071,6 +1080,19 @@ static struct ctrl sd_ctrls_12a[] = { | |||
1071 | 1080 | ||
1072 | static struct ctrl sd_ctrls_72a[] = { | 1081 | static struct ctrl sd_ctrls_72a[] = { |
1073 | { | 1082 | { |
1083 | { | ||
1084 | .id = V4L2_CID_DO_WHITE_BALANCE, | ||
1085 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1086 | .name = "White Balance", | ||
1087 | .minimum = WHITE_MIN, | ||
1088 | .maximum = WHITE_MAX, | ||
1089 | .step = 1, | ||
1090 | .default_value = WHITE_DEF, | ||
1091 | }, | ||
1092 | .set = sd_setwhite, | ||
1093 | .get = sd_getwhite, | ||
1094 | }, | ||
1095 | { | ||
1074 | { | 1096 | { |
1075 | .id = V4L2_CID_BRIGHTNESS, | 1097 | .id = V4L2_CID_BRIGHTNESS, |
1076 | .type = V4L2_CTRL_TYPE_INTEGER, | 1098 | .type = V4L2_CTRL_TYPE_INTEGER, |