diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-09-03 15:47:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-09-03 17:36:34 -0400 |
commit | 6c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36 (patch) | |
tree | 0bf575ddbaddcea670bd183853bd7a490023a448 /drivers/media/video/gspca/spca561.c | |
parent | 5bb0f21a46281b021897d2c56d50685c1939b5ee (diff) |
V4L/DVB (8669): gspca: Add white balance control for spca561 rev 012A.
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 | 110 |
1 files changed, 92 insertions, 18 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 1073ac3d2ec6..02e274452c46 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -34,6 +34,7 @@ struct sd { | |||
34 | 34 | ||
35 | unsigned short contrast; | 35 | unsigned short contrast; |
36 | __u8 brightness; | 36 | __u8 brightness; |
37 | __u8 white; | ||
37 | __u8 autogain; | 38 | __u8 autogain; |
38 | 39 | ||
39 | __u8 chip_revision; | 40 | __u8 chip_revision; |
@@ -46,11 +47,12 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 47 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
47 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 48 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
48 | static int sd_getcontrast(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); | ||
49 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
50 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
51 | 54 | ||
52 | static struct ctrl sd_ctrls[] = { | 55 | static struct ctrl sd_ctrls[] = { |
53 | #define SD_BRIGHTNESS 0 | ||
54 | { | 56 | { |
55 | { | 57 | { |
56 | .id = V4L2_CID_BRIGHTNESS, | 58 | .id = V4L2_CID_BRIGHTNESS, |
@@ -59,12 +61,12 @@ static struct ctrl sd_ctrls[] = { | |||
59 | .minimum = 0, | 61 | .minimum = 0, |
60 | .maximum = 63, | 62 | .maximum = 63, |
61 | .step = 1, | 63 | .step = 1, |
62 | .default_value = 32, | 64 | #define BRIGHTNESS_DEF 32 |
65 | .default_value = BRIGHTNESS_DEF, | ||
63 | }, | 66 | }, |
64 | .set = sd_setbrightness, | 67 | .set = sd_setbrightness, |
65 | .get = sd_getbrightness, | 68 | .get = sd_getbrightness, |
66 | }, | 69 | }, |
67 | #define SD_CONTRAST 1 | ||
68 | { | 70 | { |
69 | { | 71 | { |
70 | .id = V4L2_CID_CONTRAST, | 72 | .id = V4L2_CID_CONTRAST, |
@@ -73,12 +75,26 @@ static struct ctrl sd_ctrls[] = { | |||
73 | .minimum = 0, | 75 | .minimum = 0, |
74 | .maximum = 0x3fff, | 76 | .maximum = 0x3fff, |
75 | .step = 1, | 77 | .step = 1, |
76 | .default_value = 0x2000, | 78 | #define CONTRAST_DEF 0x2000 |
79 | .default_value = CONTRAST_DEF, | ||
77 | }, | 80 | }, |
78 | .set = sd_setcontrast, | 81 | .set = sd_setcontrast, |
79 | .get = sd_getcontrast, | 82 | .get = sd_getcontrast, |
80 | }, | 83 | }, |
81 | #define SD_AUTOGAIN 2 | 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 | }, | ||
82 | { | 98 | { |
83 | { | 99 | { |
84 | .id = V4L2_CID_AUTOGAIN, | 100 | .id = V4L2_CID_AUTOGAIN, |
@@ -87,7 +103,8 @@ static struct ctrl sd_ctrls[] = { | |||
87 | .minimum = 0, | 103 | .minimum = 0, |
88 | .maximum = 1, | 104 | .maximum = 1, |
89 | .step = 1, | 105 | .step = 1, |
90 | .default_value = 1, | 106 | #define AUTOGAIN_DEF 1 |
107 | .default_value = AUTOGAIN_DEF, | ||
91 | }, | 108 | }, |
92 | .set = sd_setautogain, | 109 | .set = sd_setautogain, |
93 | .get = sd_getautogain, | 110 | .get = sd_getautogain, |
@@ -438,7 +455,7 @@ static const __u16 spca561_init_data[][2] = { | |||
438 | {0x0035, 0x8801}, /* 0x14 - set gain general */ | 455 | {0x0035, 0x8801}, /* 0x14 - set gain general */ |
439 | {0x001f, 0x8805}, /* 0x14 */ | 456 | {0x001f, 0x8805}, /* 0x14 */ |
440 | {0x0000, 0x8800}, | 457 | {0x0000, 0x8800}, |
441 | {0x0030, 0x8112}, | 458 | {0x000e, 0x8112}, /* white balance - was 30 */ |
442 | {} | 459 | {} |
443 | }; | 460 | }; |
444 | 461 | ||
@@ -478,9 +495,10 @@ static const __u16 Pb100_2map8300[][2] = { | |||
478 | }; | 495 | }; |
479 | 496 | ||
480 | static const __u16 spca561_161rev12A_data1[][2] = { | 497 | static const __u16 spca561_161rev12A_data1[][2] = { |
481 | {0x21, 0x8118}, | 498 | {0x29, 0x8118}, /* white balance - was 21 */ |
482 | {0x01, 0x8114}, | 499 | {0x08, 0x8114}, /* white balance - was 01 */ |
483 | {0x00, 0x8112}, | 500 | {0x0e, 0x8112}, /* white balance - was 00 */ |
501 | {0x00, 0x8102}, /* white balance - new */ | ||
484 | {0x92, 0x8804}, | 502 | {0x92, 0x8804}, |
485 | {0x04, 0x8802}, /* windows uses 08 */ | 503 | {0x04, 0x8802}, /* windows uses 08 */ |
486 | {} | 504 | {} |
@@ -505,14 +523,16 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
505 | {0xb0, 0x8603}, | 523 | {0xb0, 0x8603}, |
506 | 524 | ||
507 | /* sensor gains */ | 525 | /* sensor gains */ |
526 | {0x07, 0x8601}, /* white balance - new */ | ||
527 | {0x07, 0x8602}, /* white balance - new */ | ||
508 | {0x00, 0x8610}, /* *red */ | 528 | {0x00, 0x8610}, /* *red */ |
509 | {0x00, 0x8611}, /* 3f *green */ | 529 | {0x00, 0x8611}, /* 3f *green */ |
510 | {0x00, 0x8612}, /* green *blue */ | 530 | {0x00, 0x8612}, /* green *blue */ |
511 | {0x00, 0x8613}, /* blue *green */ | 531 | {0x00, 0x8613}, /* blue *green */ |
512 | {0x35, 0x8614}, /* green *red */ | 532 | {0x43, 0x8614}, /* green *red - white balance - was 0x35 */ |
513 | {0x35, 0x8615}, /* 40 *green */ | 533 | {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */ |
514 | {0x35, 0x8616}, /* 7a *blue */ | 534 | {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */ |
515 | {0x35, 0x8617}, /* 40 *green */ | 535 | {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */ |
516 | 536 | ||
517 | {0x0c, 0x8620}, /* 0c */ | 537 | {0x0c, 0x8620}, /* 0c */ |
518 | {0xc8, 0x8631}, /* c8 */ | 538 | {0xc8, 0x8631}, /* c8 */ |
@@ -527,6 +547,7 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
527 | {0xdf, 0x863c}, /* df */ | 547 | {0xdf, 0x863c}, /* df */ |
528 | {0xf0, 0x8505}, | 548 | {0xf0, 0x8505}, |
529 | {0x32, 0x850a}, | 549 | {0x32, 0x850a}, |
550 | {0x99, 0x8700}, /* - white balance - new */ | ||
530 | {} | 551 | {} |
531 | }; | 552 | }; |
532 | 553 | ||
@@ -588,9 +609,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
588 | cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; | 609 | cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; |
589 | 610 | ||
590 | sd->chip_revision = id->driver_info; | 611 | sd->chip_revision = id->driver_info; |
591 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 612 | sd->brightness = BRIGHTNESS_DEF; |
592 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 613 | sd->contrast = CONTRAST_DEF; |
593 | sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; | 614 | sd->autogain = AUTOGAIN_DEF; |
615 | sd->white = WHITE_DEF; | ||
594 | return 0; | 616 | return 0; |
595 | } | 617 | } |
596 | 618 | ||
@@ -628,15 +650,18 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
628 | reg_w_val(dev, lowb, 0x8653); | 650 | reg_w_val(dev, lowb, 0x8653); |
629 | reg_w_val(dev, lowb, 0x8654); | 651 | reg_w_val(dev, lowb, 0x8654); |
630 | break; | 652 | break; |
631 | case Rev012A: { | 653 | default: { |
654 | /* case Rev012A: { */ | ||
632 | __u8 Reg8391[] = | 655 | __u8 Reg8391[] = |
633 | { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; | 656 | { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; |
634 | 657 | ||
635 | /* Write camera sensor settings */ | 658 | /* Write camera sensor settings */ |
636 | expotimes = (sd->contrast >> 5) & 0x07ff; | 659 | expotimes = (sd->contrast >> 5) & 0x07ff; |
660 | /* exposure is in 8309 2b, range 0120 - 5720 */ | ||
637 | Reg8391[0] = expotimes & 0xff; /* exposure */ | 661 | Reg8391[0] = expotimes & 0xff; /* exposure */ |
638 | Reg8391[1] = 0x18 | (expotimes >> 8); | 662 | Reg8391[1] = 0x18 | (expotimes >> 8); |
639 | Reg8391[2] = sd->brightness; /* gain */ | 663 | Reg8391[2] = sd->brightness; /* gain */ |
664 | /* gain in 8335, 2b range 0000 - 2400 */ | ||
640 | reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); | 665 | reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); |
641 | reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); | 666 | reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); |
642 | break; | 667 | break; |
@@ -644,6 +669,34 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
644 | } | 669 | } |
645 | } | 670 | } |
646 | 671 | ||
672 | static void setwhite(struct gspca_dev *gspca_dev) | ||
673 | { | ||
674 | struct sd *sd = (struct sd *) gspca_dev; | ||
675 | __u16 white; | ||
676 | __u8 reg8614, reg8616; | ||
677 | |||
678 | switch (sd->chip_revision) { | ||
679 | case Rev072A: | ||
680 | /* no such hardware */ | ||
681 | break; | ||
682 | default: | ||
683 | /* case Rev012A: */ | ||
684 | white = sd->white; | ||
685 | if (sd->white == 0) { | ||
686 | PDEBUG(D_CONF, "Discarding null whiteness"); | ||
687 | break; | ||
688 | } | ||
689 | /* try to emulate MS-win as possible */ | ||
690 | if (white < 0x45) | ||
691 | reg8616 = white; | ||
692 | else | ||
693 | reg8616 = 0x93 + (white >> 2); | ||
694 | reg8614 = 0x28 + (white >> 4); | ||
695 | reg_w_val(gspca_dev->dev, reg8616, 0x8616); | ||
696 | reg_w_val(gspca_dev->dev, reg8614, 0x8614); | ||
697 | } | ||
698 | } | ||
699 | |||
647 | static void setautogain(struct gspca_dev *gspca_dev) | 700 | static void setautogain(struct gspca_dev *gspca_dev) |
648 | { | 701 | { |
649 | struct sd *sd = (struct sd *) gspca_dev; | 702 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -714,6 +767,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
714 | reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); | 767 | reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); |
715 | reg_w_val(gspca_dev->dev, 0x850b, 0x03); | 768 | reg_w_val(gspca_dev->dev, 0x850b, 0x03); |
716 | setcontrast(gspca_dev); | 769 | setcontrast(gspca_dev); |
770 | setwhite(gspca_dev); | ||
717 | break; | 771 | break; |
718 | } | 772 | } |
719 | } | 773 | } |
@@ -721,6 +775,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
721 | static void sd_stopN(struct gspca_dev *gspca_dev) | 775 | static void sd_stopN(struct gspca_dev *gspca_dev) |
722 | { | 776 | { |
723 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); | 777 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); |
778 | reg_w_val(gspca_dev->dev, 0x8102, 0x00); /* white balance - new */ | ||
724 | } | 779 | } |
725 | 780 | ||
726 | static void sd_stop0(struct gspca_dev *gspca_dev) | 781 | static void sd_stop0(struct gspca_dev *gspca_dev) |
@@ -968,6 +1023,25 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
968 | return 0; | 1023 | return 0; |
969 | } | 1024 | } |
970 | 1025 | ||
1026 | /* white balance - new */ | ||
1027 | static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) | ||
1028 | { | ||
1029 | struct sd *sd = (struct sd *) gspca_dev; | ||
1030 | |||
1031 | sd->white = val; | ||
1032 | if (gspca_dev->streaming) | ||
1033 | setwhite(gspca_dev); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val) | ||
1038 | { | ||
1039 | struct sd *sd = (struct sd *) gspca_dev; | ||
1040 | |||
1041 | *val = sd->white; | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
971 | /* sub-driver description */ | 1045 | /* sub-driver description */ |
972 | static const struct sd_desc sd_desc = { | 1046 | static const struct sd_desc sd_desc = { |
973 | .name = MODULE_NAME, | 1047 | .name = MODULE_NAME, |