diff options
author | Jean-François Moine <moinejf@free.fr> | 2011-03-22 05:47:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-22 15:38:27 -0400 |
commit | 590f21680616a78f7d6972b92ceb540e306452c1 (patch) | |
tree | 189c8a5c47d0aa02e41c640ca3e4a1382860fe26 /drivers/media | |
parent | 7106225a9e7d123ff87a6848972b6d28c8903940 (diff) |
[media] gspca - zc3xx: Add exposure control for sensor hv7131r
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 6dcb1cf11b5c..fa164e861cde 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -39,6 +39,7 @@ static int force_sensor = -1; | |||
39 | enum e_ctrl { | 39 | enum e_ctrl { |
40 | BRIGHTNESS, | 40 | BRIGHTNESS, |
41 | CONTRAST, | 41 | CONTRAST, |
42 | EXPOSURE, | ||
42 | GAMMA, | 43 | GAMMA, |
43 | AUTOGAIN, | 44 | AUTOGAIN, |
44 | LIGHTFREQ, | 45 | LIGHTFREQ, |
@@ -46,6 +47,8 @@ enum e_ctrl { | |||
46 | NCTRLS /* number of controls */ | 47 | NCTRLS /* number of controls */ |
47 | }; | 48 | }; |
48 | 49 | ||
50 | #define AUTOGAIN_DEF 1 | ||
51 | |||
49 | /* specific webcam descriptor */ | 52 | /* specific webcam descriptor */ |
50 | struct sd { | 53 | struct sd { |
51 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 54 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
@@ -92,7 +95,8 @@ enum sensors { | |||
92 | 95 | ||
93 | /* V4L2 controls supported by the driver */ | 96 | /* V4L2 controls supported by the driver */ |
94 | static void setcontrast(struct gspca_dev *gspca_dev); | 97 | static void setcontrast(struct gspca_dev *gspca_dev); |
95 | static void setautogain(struct gspca_dev *gspca_dev); | 98 | static void setexposure(struct gspca_dev *gspca_dev); |
99 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
96 | static void setlightfreq(struct gspca_dev *gspca_dev); | 100 | static void setlightfreq(struct gspca_dev *gspca_dev); |
97 | static void setsharpness(struct gspca_dev *gspca_dev); | 101 | static void setsharpness(struct gspca_dev *gspca_dev); |
98 | 102 | ||
@@ -121,6 +125,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
121 | }, | 125 | }, |
122 | .set_control = setcontrast | 126 | .set_control = setcontrast |
123 | }, | 127 | }, |
128 | [EXPOSURE] = { | ||
129 | { | ||
130 | .id = V4L2_CID_EXPOSURE, | ||
131 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
132 | .name = "Exposure", | ||
133 | .minimum = 0x30d, | ||
134 | .maximum = 0x493e, | ||
135 | .step = 1, | ||
136 | .default_value = 0x927 | ||
137 | }, | ||
138 | .set_control = setexposure | ||
139 | }, | ||
124 | [GAMMA] = { | 140 | [GAMMA] = { |
125 | { | 141 | { |
126 | .id = V4L2_CID_GAMMA, | 142 | .id = V4L2_CID_GAMMA, |
@@ -141,9 +157,10 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
141 | .minimum = 0, | 157 | .minimum = 0, |
142 | .maximum = 1, | 158 | .maximum = 1, |
143 | .step = 1, | 159 | .step = 1, |
144 | .default_value = 1, | 160 | .default_value = AUTOGAIN_DEF, |
161 | .flags = V4L2_CTRL_FLAG_UPDATE | ||
145 | }, | 162 | }, |
146 | .set_control = setautogain | 163 | .set = sd_setautogain |
147 | }, | 164 | }, |
148 | [LIGHTFREQ] = { | 165 | [LIGHTFREQ] = { |
149 | { | 166 | { |
@@ -5926,6 +5943,26 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
5926 | reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ | 5943 | reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ |
5927 | } | 5944 | } |
5928 | 5945 | ||
5946 | static void getexposure(struct gspca_dev *gspca_dev) | ||
5947 | { | ||
5948 | struct sd *sd = (struct sd *) gspca_dev; | ||
5949 | |||
5950 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) | ||
5951 | | (i2c_read(gspca_dev, 0x26) << 1) | ||
5952 | | (i2c_read(gspca_dev, 0x27) >> 7); | ||
5953 | } | ||
5954 | |||
5955 | static void setexposure(struct gspca_dev *gspca_dev) | ||
5956 | { | ||
5957 | struct sd *sd = (struct sd *) gspca_dev; | ||
5958 | int val; | ||
5959 | |||
5960 | val = sd->ctrls[EXPOSURE].val; | ||
5961 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); | ||
5962 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); | ||
5963 | i2c_write(gspca_dev, 0x27, val << 7, 0x00); | ||
5964 | } | ||
5965 | |||
5929 | static void setquality(struct gspca_dev *gspca_dev) | 5966 | static void setquality(struct gspca_dev *gspca_dev) |
5930 | { | 5967 | { |
5931 | struct sd *sd = (struct sd *) gspca_dev; | 5968 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -6623,10 +6660,19 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6623 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; | 6660 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; |
6624 | 6661 | ||
6625 | switch (sd->sensor) { | 6662 | switch (sd->sensor) { |
6663 | case SENSOR_HV7131R: | ||
6664 | break; | ||
6626 | case SENSOR_OV7630C: | 6665 | case SENSOR_OV7630C: |
6627 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ); | 6666 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); |
6667 | break; | ||
6668 | default: | ||
6669 | gspca_dev->ctrl_dis = (1 << EXPOSURE); | ||
6628 | break; | 6670 | break; |
6629 | } | 6671 | } |
6672 | #if AUTOGAIN_DEF | ||
6673 | if (sd->ctrls[AUTOGAIN].val) | ||
6674 | gspca_dev->ctrl_inac = (1 << EXPOSURE); | ||
6675 | #endif | ||
6630 | 6676 | ||
6631 | /* switch off the led */ | 6677 | /* switch off the led */ |
6632 | reg_w(gspca_dev, 0x01, 0x0000); | 6678 | reg_w(gspca_dev, 0x01, 0x0000); |
@@ -6772,9 +6818,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6772 | reg_w(gspca_dev, 0x40, 0x0117); | 6818 | reg_w(gspca_dev, 0x40, 0x0117); |
6773 | break; | 6819 | break; |
6774 | case SENSOR_HV7131R: | 6820 | case SENSOR_HV7131R: |
6775 | i2c_write(gspca_dev, 0x25, 0x04, 0x00); /* exposure */ | 6821 | if (!sd->ctrls[AUTOGAIN].val) |
6776 | i2c_write(gspca_dev, 0x26, 0x93, 0x00); | 6822 | setexposure(gspca_dev); |
6777 | i2c_write(gspca_dev, 0x27, 0xe0, 0x00); | ||
6778 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); | 6823 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); |
6779 | break; | 6824 | break; |
6780 | case SENSOR_GC0305: | 6825 | case SENSOR_GC0305: |
@@ -6852,6 +6897,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
6852 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 6897 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
6853 | } | 6898 | } |
6854 | 6899 | ||
6900 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
6901 | { | ||
6902 | struct sd *sd = (struct sd *) gspca_dev; | ||
6903 | |||
6904 | sd->ctrls[AUTOGAIN].val = val; | ||
6905 | if (val) { | ||
6906 | gspca_dev->ctrl_inac |= (1 << EXPOSURE); | ||
6907 | } else { | ||
6908 | gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); | ||
6909 | if (gspca_dev->streaming) | ||
6910 | getexposure(gspca_dev); | ||
6911 | } | ||
6912 | if (gspca_dev->streaming) | ||
6913 | setautogain(gspca_dev); | ||
6914 | return gspca_dev->usb_err; | ||
6915 | } | ||
6916 | |||
6855 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 6917 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
6856 | struct v4l2_querymenu *menu) | 6918 | struct v4l2_querymenu *menu) |
6857 | { | 6919 | { |