aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca561.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-12-18 10:38:15 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:39:41 -0500
commit5b7ed28ec5deb57f790e38af8d813310b830743c (patch)
tree2472a21d3cc74faf1421aaf11732dbd14fe63423 /drivers/media/video/gspca/spca561.c
parentf4b59e353239d3c8e2456a986e42f4c87cfcef9f (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.c142
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");
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 __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
594static void setcontrast(struct gspca_dev *gspca_dev) 595/* rev 72a only */
596static 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 */
622static void setwhite(struct gspca_dev *gspca_dev) 611static 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
633static 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)
690static int sd_start_12a(struct gspca_dev *gspca_dev) 705static 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 */
891static 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 */
904static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 914static 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 */
960static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) 969static 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
1072static struct ctrl sd_ctrls_72a[] = { 1081static 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,