diff options
author | Theodore Kilgore <kilgota@banach.math.auburn.edu> | 2010-02-09 16:05:25 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:11:09 -0500 |
commit | 9d3103d061224e939272d05d54192038f66ffd54 (patch) | |
tree | e8e62612089e374cf3f3b4e7d94cddb573e09336 /drivers/media | |
parent | 10bb7530108cc11fedd0d615467a54f341079778 (diff) |
V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix
This camera has a sensor type we did not support sofar, this patch adds
support for the new sensor type found in the Sakar 1638x CyberPix.
Signed-off-by: Theodore Kilgore <kilgota@banach.math.auburn.edu>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 197 |
1 files changed, 177 insertions, 20 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 959ea2a530a4..33744e724eaa 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -57,6 +57,14 @@ | |||
57 | #define MR97310A_GAIN_MAX 31 | 57 | #define MR97310A_GAIN_MAX 31 |
58 | #define MR97310A_GAIN_DEFAULT 25 | 58 | #define MR97310A_GAIN_DEFAULT 25 |
59 | 59 | ||
60 | #define MR97310A_CONTRAST_MIN 0 | ||
61 | #define MR97310A_CONTRAST_MAX 31 | ||
62 | #define MR97310A_CONTRAST_DEFAULT 23 | ||
63 | |||
64 | #define MR97310A_CS_GAIN_MIN 0 | ||
65 | #define MR97310A_CS_GAIN_MAX 0x7ff | ||
66 | #define MR97310A_CS_GAIN_DEFAULT 0x110 | ||
67 | |||
60 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | 68 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
61 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | 69 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
62 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | 70 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
@@ -82,7 +90,8 @@ struct sd { | |||
82 | 90 | ||
83 | int brightness; | 91 | int brightness; |
84 | u16 exposure; | 92 | u16 exposure; |
85 | u8 gain; | 93 | u32 gain; |
94 | u8 contrast; | ||
86 | u8 min_clockdiv; | 95 | u8 min_clockdiv; |
87 | }; | 96 | }; |
88 | 97 | ||
@@ -98,6 +107,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
98 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
99 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 108 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 109 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
110 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 112 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 113 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
103 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | 114 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); |
@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | |||
105 | static void setbrightness(struct gspca_dev *gspca_dev); | 116 | static void setbrightness(struct gspca_dev *gspca_dev); |
106 | static void setexposure(struct gspca_dev *gspca_dev); | 117 | static void setexposure(struct gspca_dev *gspca_dev); |
107 | static void setgain(struct gspca_dev *gspca_dev); | 118 | static void setgain(struct gspca_dev *gspca_dev); |
119 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
108 | 120 | ||
109 | /* V4L2 controls supported by the driver */ | 121 | /* V4L2 controls supported by the driver */ |
110 | static const struct ctrl sd_ctrls[] = { | 122 | static const struct ctrl sd_ctrls[] = { |
111 | /* Separate brightness control description for Argus QuickClix as it has | 123 | /* Separate brightness control description for Argus QuickClix as it has |
112 | different limits from the other mr97310a cameras */ | 124 | * different limits from the other mr97310a cameras, and separate gain |
125 | * control for Sakar CyberPix camera. */ | ||
113 | { | 126 | { |
114 | #define NORM_BRIGHTNESS_IDX 0 | 127 | #define NORM_BRIGHTNESS_IDX 0 |
115 | { | 128 | { |
@@ -171,7 +184,37 @@ static const struct ctrl sd_ctrls[] = { | |||
171 | .get = sd_getgain, | 184 | .get = sd_getgain, |
172 | }, | 185 | }, |
173 | { | 186 | { |
174 | #define MIN_CLOCKDIV_IDX 4 | 187 | #define SAKAR_CS_GAIN_IDX 4 |
188 | { | ||
189 | .id = V4L2_CID_GAIN, | ||
190 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
191 | .name = "Gain", | ||
192 | .minimum = MR97310A_CS_GAIN_MIN, | ||
193 | .maximum = MR97310A_CS_GAIN_MAX, | ||
194 | .step = 1, | ||
195 | .default_value = MR97310A_CS_GAIN_DEFAULT, | ||
196 | .flags = 0, | ||
197 | }, | ||
198 | .set = sd_setgain, | ||
199 | .get = sd_getgain, | ||
200 | }, | ||
201 | { | ||
202 | #define CONTRAST_IDX 5 | ||
203 | { | ||
204 | .id = V4L2_CID_CONTRAST, | ||
205 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
206 | .name = "Contrast", | ||
207 | .minimum = MR97310A_CONTRAST_MIN, | ||
208 | .maximum = MR97310A_CONTRAST_MAX, | ||
209 | .step = 1, | ||
210 | .default_value = MR97310A_CONTRAST_DEFAULT, | ||
211 | .flags = 0, | ||
212 | }, | ||
213 | .set = sd_setcontrast, | ||
214 | .get = sd_getcontrast, | ||
215 | }, | ||
216 | { | ||
217 | #define MIN_CLOCKDIV_IDX 6 | ||
175 | { | 218 | { |
176 | .id = V4L2_CID_PRIVATE_BASE, | 219 | .id = V4L2_CID_PRIVATE_BASE, |
177 | .type = V4L2_CTRL_TYPE_INTEGER, | 220 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -436,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
436 | { | 479 | { |
437 | struct sd *sd = (struct sd *) gspca_dev; | 480 | struct sd *sd = (struct sd *) gspca_dev; |
438 | struct cam *cam; | 481 | struct cam *cam; |
482 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
439 | int err_code; | 483 | int err_code; |
440 | 484 | ||
441 | cam = &gspca_dev->cam; | 485 | cam = &gspca_dev->cam; |
@@ -479,7 +523,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
479 | * | 523 | * |
480 | * Name sd->sensor_type reported by | 524 | * Name sd->sensor_type reported by |
481 | * | 525 | * |
482 | * Sakar Spy-shot 0 T. Kilgore | 526 | * Sakar 56379 Spy-shot 0 T. Kilgore |
483 | * Innovage 0 T. Kilgore | 527 | * Innovage 0 T. Kilgore |
484 | * Vivitar Mini 0 H. De Goede | 528 | * Vivitar Mini 0 H. De Goede |
485 | * Vivitar Mini 0 E. Rodriguez | 529 | * Vivitar Mini 0 E. Rodriguez |
@@ -507,14 +551,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
507 | 551 | ||
508 | /* | 552 | /* |
509 | * Here is a table of the responses to the query for sensor | 553 | * Here is a table of the responses to the query for sensor |
510 | * type, from the known MR97310A VGA cameras. | 554 | * type, from the known MR97310A VGA cameras. Six different |
555 | * cameras of which five share the same USB ID. | ||
511 | * | 556 | * |
512 | * Name gspca_dev->usb_buf[] sd->sensor_type | 557 | * Name gspca_dev->usb_buf[] sd->sensor_type |
513 | * sd->do_lcd_stop | 558 | * sd->do_lcd_stop |
514 | * Aiptek Pencam VGA+ 0300 0 1 | 559 | * Aiptek Pencam VGA+ 0300 0 1 |
515 | * ION digital 0350 0 1 | 560 | * ION digital 0300 0 1 |
516 | * Argus DC-1620 0450 1 0 | 561 | * Argus DC-1620 0450 1 0 |
517 | * Argus QuickClix 0420 1 1 | 562 | * Argus QuickClix 0420 1 1 |
563 | * Sakar 77379 Digital 0350 0 1 | ||
564 | * Sakar 1638x CyberPix 0120 0 2 | ||
518 | * | 565 | * |
519 | * Based upon these results, we assume default settings | 566 | * Based upon these results, we assume default settings |
520 | * and then correct as necessary, as follows. | 567 | * and then correct as necessary, as follows. |
@@ -524,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
524 | sd->sensor_type = 1; | 571 | sd->sensor_type = 1; |
525 | sd->do_lcd_stop = 0; | 572 | sd->do_lcd_stop = 0; |
526 | sd->adj_colors = 0; | 573 | sd->adj_colors = 0; |
527 | if ((gspca_dev->usb_buf[0] != 0x03) && | 574 | if (gspca_dev->usb_buf[0] == 0x01) { |
575 | sd->sensor_type = 2; | ||
576 | } else if ((gspca_dev->usb_buf[0] != 0x03) && | ||
528 | (gspca_dev->usb_buf[0] != 0x04)) { | 577 | (gspca_dev->usb_buf[0] != 0x04)) { |
529 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | 578 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", |
530 | gspca_dev->usb_buf[1]); | 579 | gspca_dev->usb_buf[0]); |
531 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | 580 | PDEBUG(D_ERR, "Defaults assumed, may not work"); |
532 | PDEBUG(D_ERR, "Please report this"); | 581 | PDEBUG(D_ERR, "Please report this"); |
533 | } | 582 | } |
@@ -571,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
571 | /* No brightness for sensor_type 0 */ | 620 | /* No brightness for sensor_type 0 */ |
572 | if (sd->sensor_type == 0) | 621 | if (sd->sensor_type == 0) |
573 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
574 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
624 | (1 << CONTRAST_IDX) | | ||
625 | (1 << SAKAR_CS_GAIN_IDX); | ||
575 | else | 626 | else |
576 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 627 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
628 | (1 << CONTRAST_IDX) | | ||
629 | (1 << SAKAR_CS_GAIN_IDX) | | ||
577 | (1 << MIN_CLOCKDIV_IDX); | 630 | (1 << MIN_CLOCKDIV_IDX); |
578 | } else { | 631 | } else { |
579 | /* All controls need to be disabled if VGA sensor_type is 0 */ | 632 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
@@ -582,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
582 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
583 | (1 << EXPOSURE_IDX) | | 636 | (1 << EXPOSURE_IDX) | |
584 | (1 << GAIN_IDX) | | 637 | (1 << GAIN_IDX) | |
638 | (1 << CONTRAST_IDX) | | ||
639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
585 | (1 << MIN_CLOCKDIV_IDX); | 640 | (1 << MIN_CLOCKDIV_IDX); |
586 | else if (sd->do_lcd_stop) | 641 | else if (sd->sensor_type == 2) { |
642 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
643 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
644 | (1 << GAIN_IDX) | | ||
645 | (1 << MIN_CLOCKDIV_IDX); | ||
646 | gain_default = MR97310A_CS_GAIN_DEFAULT; | ||
647 | } else if (sd->do_lcd_stop) | ||
587 | /* Argus QuickClix has different brightness limits */ | 648 | /* Argus QuickClix has different brightness limits */ |
588 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | 649 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
650 | (1 << CONTRAST_IDX) | | ||
651 | (1 << SAKAR_CS_GAIN_IDX); | ||
589 | else | 652 | else |
590 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | 653 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
654 | (1 << CONTRAST_IDX) | | ||
655 | (1 << SAKAR_CS_GAIN_IDX); | ||
591 | } | 656 | } |
592 | 657 | ||
593 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
594 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
595 | sd->gain = MR97310A_GAIN_DEFAULT; | 660 | sd->gain = gain_default; |
661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
596 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | 662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; |
597 | 663 | ||
598 | return 0; | 664 | return 0; |
@@ -720,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
720 | data[5] = 0x00; | 786 | data[5] = 0x00; |
721 | data[10] = 0x91; | 787 | data[10] = 0x91; |
722 | } | 788 | } |
789 | if (sd->sensor_type == 2) { | ||
790 | data[5] = 0x00; | ||
791 | data[10] = 0x18; | ||
792 | } | ||
723 | 793 | ||
724 | switch (gspca_dev->width) { | 794 | switch (gspca_dev->width) { |
725 | case 160: | 795 | case 160: |
@@ -734,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
734 | data[4] = 0x78; /* reg 3, V size/4 */ | 804 | data[4] = 0x78; /* reg 3, V size/4 */ |
735 | data[6] = 0x04; /* reg 5, H start */ | 805 | data[6] = 0x04; /* reg 5, H start */ |
736 | data[8] = 0x03; /* reg 7, V start */ | 806 | data[8] = 0x03; /* reg 7, V start */ |
807 | if (sd->sensor_type == 2) { | ||
808 | data[6] = 2; | ||
809 | data[8] = 1; | ||
810 | } | ||
737 | if (sd->do_lcd_stop) | 811 | if (sd->do_lcd_stop) |
738 | data[8] = 0x04; /* Bayer tile shifted */ | 812 | data[8] = 0x04; /* Bayer tile shifted */ |
739 | break; | 813 | break; |
@@ -756,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
756 | return err_code; | 830 | return err_code; |
757 | 831 | ||
758 | if (!sd->sensor_type) { | 832 | if (!sd->sensor_type) { |
759 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ | ||
760 | const struct sensor_w_data vga_sensor0_init_data[] = { | 833 | const struct sensor_w_data vga_sensor0_init_data[] = { |
761 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, | 834 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
762 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, | 835 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
@@ -767,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
767 | }; | 840 | }; |
768 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 841 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
769 | ARRAY_SIZE(vga_sensor0_init_data)); | 842 | ARRAY_SIZE(vga_sensor0_init_data)); |
770 | } else { /* sd->sensor_type = 1 */ | 843 | } else if (sd->sensor_type == 1) { |
771 | const struct sensor_w_data color_adj[] = { | 844 | const struct sensor_w_data color_adj[] = { |
772 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 845 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
773 | /* adjusted blue, green, red gain correct | 846 | /* adjusted blue, green, red gain correct |
@@ -805,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
805 | 878 | ||
806 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 879 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
807 | ARRAY_SIZE(vga_sensor1_init_data)); | 880 | ARRAY_SIZE(vga_sensor1_init_data)); |
881 | } else { /* sensor type == 2 */ | ||
882 | const struct sensor_w_data vga_sensor2_init_data[] = { | ||
883 | |||
884 | {0x01, 0x00, {0x48}, 1}, | ||
885 | {0x02, 0x00, {0x22}, 1}, | ||
886 | /* Reg 3 msb and 4 is lsb of the exposure setting*/ | ||
887 | {0x05, 0x00, {0x10}, 1}, | ||
888 | {0x06, 0x00, {0x00}, 1}, | ||
889 | {0x07, 0x00, {0x00}, 1}, | ||
890 | {0x08, 0x00, {0x00}, 1}, | ||
891 | {0x09, 0x00, {0x00}, 1}, | ||
892 | /* The following are used in the gain control | ||
893 | * which is BTW completely borked in the OEM driver | ||
894 | * The values for each color go from 0 to 0x7ff | ||
895 | *{0x0a, 0x00, {0x01}, 1}, green1 gain msb | ||
896 | *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb | ||
897 | *{0x0c, 0x00, {0x01}, 1}, red gain msb | ||
898 | *{0x0d, 0x00, {0x10}, 1}, red gain lsb | ||
899 | *{0x0e, 0x00, {0x01}, 1}, blue gain msb | ||
900 | *{0x0f, 0x00, {0x10}, 1}, blue gain lsb | ||
901 | *{0x10, 0x00, {0x01}, 1}, green2 gain msb | ||
902 | *{0x11, 0x00, {0x10}, 1}, green2 gain lsb | ||
903 | */ | ||
904 | {0x12, 0x00, {0x00}, 1}, | ||
905 | {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ | ||
906 | {0x14, 0x00, {0x00}, 1}, | ||
907 | {0x15, 0x00, {0x06}, 1}, | ||
908 | {0x16, 0x00, {0x01}, 1}, | ||
909 | {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ | ||
910 | {0x18, 0x00, {0x02}, 1}, | ||
911 | {0x19, 0x00, {0x82}, 1}, /* don't mess with */ | ||
912 | {0x1a, 0x00, {0x00}, 1}, | ||
913 | {0x1b, 0x00, {0x20}, 1}, | ||
914 | /* {0x1c, 0x00, {0x17}, 1}, contrast control */ | ||
915 | {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ | ||
916 | {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ | ||
917 | {0x1f, 0x00, {0x0c}, 1}, | ||
918 | {0x20, 0x00, {0x00}, 1}, | ||
919 | {0, 0, {0}, 0} | ||
920 | }; | ||
921 | err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data, | ||
922 | ARRAY_SIZE(vga_sensor2_init_data)); | ||
808 | } | 923 | } |
809 | return err_code; | 924 | return err_code; |
810 | } | 925 | } |
@@ -837,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
837 | return err_code; | 952 | return err_code; |
838 | 953 | ||
839 | setbrightness(gspca_dev); | 954 | setbrightness(gspca_dev); |
955 | setcontrast(gspca_dev); | ||
840 | setexposure(gspca_dev); | 956 | setexposure(gspca_dev); |
841 | setgain(gspca_dev); | 957 | setgain(gspca_dev); |
842 | 958 | ||
@@ -896,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
896 | static void setexposure(struct gspca_dev *gspca_dev) | 1012 | static void setexposure(struct gspca_dev *gspca_dev) |
897 | { | 1013 | { |
898 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
899 | int exposure; | 1015 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
900 | u8 buf[2]; | 1016 | u8 buf[2]; |
901 | 1017 | ||
902 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 1018 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
@@ -908,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
908 | exposure = (sd->exposure * 9267) / 10000 + 300; | 1024 | exposure = (sd->exposure * 9267) / 10000 + 300; |
909 | sensor_write1(gspca_dev, 3, exposure >> 4); | 1025 | sensor_write1(gspca_dev, 3, exposure >> 4); |
910 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | 1026 | sensor_write1(gspca_dev, 4, exposure & 0x0f); |
1027 | } else if (sd->sensor_type == 2) { | ||
1028 | exposure = sd->exposure; | ||
1029 | exposure >>= 3; | ||
1030 | sensor_write1(gspca_dev, 3, exposure >> 8); | ||
1031 | sensor_write1(gspca_dev, 4, exposure & 0xff); | ||
911 | } else { | 1032 | } else { |
912 | /* We have both a clock divider and an exposure register. | 1033 | /* We have both a clock divider and an exposure register. |
913 | We first calculate the clock divider, as that determines | 1034 | We first calculate the clock divider, as that determines |
@@ -946,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
946 | static void setgain(struct gspca_dev *gspca_dev) | 1067 | static void setgain(struct gspca_dev *gspca_dev) |
947 | { | 1068 | { |
948 | struct sd *sd = (struct sd *) gspca_dev; | 1069 | struct sd *sd = (struct sd *) gspca_dev; |
1070 | u8 gainreg; | ||
949 | 1071 | ||
950 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) | 1072 | if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && |
1073 | (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) | ||
951 | return; | 1074 | return; |
952 | 1075 | ||
953 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 1076 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
954 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 1077 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
955 | } else { | 1078 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
1079 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { | ||
1080 | sensor_write1(gspca_dev, gainreg, sd->gain >> 8); | ||
1081 | sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); | ||
1082 | } | ||
1083 | else | ||
956 | sensor_write1(gspca_dev, 0x10, sd->gain); | 1084 | sensor_write1(gspca_dev, 0x10, sd->gain); |
957 | } | ||
958 | } | 1085 | } |
959 | 1086 | ||
1087 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
1088 | { | ||
1089 | struct sd *sd = (struct sd *) gspca_dev; | ||
1090 | |||
1091 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
1092 | return; | ||
1093 | |||
1094 | sensor_write1(gspca_dev, 0x1c, sd->contrast); | ||
1095 | } | ||
1096 | |||
1097 | |||
960 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1098 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
961 | { | 1099 | { |
962 | struct sd *sd = (struct sd *) gspca_dev; | 1100 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1011,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
1011 | return 0; | 1149 | return 0; |
1012 | } | 1150 | } |
1013 | 1151 | ||
1152 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1153 | { | ||
1154 | struct sd *sd = (struct sd *) gspca_dev; | ||
1155 | |||
1156 | sd->contrast = val; | ||
1157 | if (gspca_dev->streaming) | ||
1158 | setcontrast(gspca_dev); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1164 | { | ||
1165 | struct sd *sd = (struct sd *) gspca_dev; | ||
1166 | |||
1167 | *val = sd->contrast; | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1014 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | 1171 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) |
1015 | { | 1172 | { |
1016 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |