diff options
author | Jean-François Moine <moinejf@free.fr> | 2011-03-13 15:36:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-22 03:54:49 -0400 |
commit | 58c92d37e7d34433cfbc3989bec20e48fba0799e (patch) | |
tree | 4caccbda16d5f5dcceeb5a924c64f1359ad07650 | |
parent | 7d47b789ceb456d90a3ace522dbcb2a94d2693ca (diff) |
[media] gspca - ov519: Add exposure and autogain controls for ov2610/2610ae
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 120 |
1 files changed, 106 insertions, 14 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 42670ec7ef3b..fd1b6082c96d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * OV519 driver | 2 | * OV519 driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> |
5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> | 5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> |
6 | * | 6 | * |
7 | * This module is adapted from the ov51x-jpeg package, which itself | 7 | * This module is adapted from the ov51x-jpeg package, which itself |
@@ -61,10 +61,12 @@ static int i2c_detect_tries = 10; | |||
61 | enum e_ctrl { | 61 | enum e_ctrl { |
62 | BRIGHTNESS, | 62 | BRIGHTNESS, |
63 | CONTRAST, | 63 | CONTRAST, |
64 | EXPOSURE, | ||
64 | COLORS, | 65 | COLORS, |
65 | HFLIP, | 66 | HFLIP, |
66 | VFLIP, | 67 | VFLIP, |
67 | AUTOBRIGHT, | 68 | AUTOBRIGHT, |
69 | AUTOGAIN, | ||
68 | FREQ, | 70 | FREQ, |
69 | NCTRL /* number of controls */ | 71 | NCTRL /* number of controls */ |
70 | }; | 72 | }; |
@@ -142,9 +144,11 @@ enum sensors { | |||
142 | /* V4L2 controls supported by the driver */ | 144 | /* V4L2 controls supported by the driver */ |
143 | static void setbrightness(struct gspca_dev *gspca_dev); | 145 | static void setbrightness(struct gspca_dev *gspca_dev); |
144 | static void setcontrast(struct gspca_dev *gspca_dev); | 146 | static void setcontrast(struct gspca_dev *gspca_dev); |
147 | static void setexposure(struct gspca_dev *gspca_dev); | ||
145 | static void setcolors(struct gspca_dev *gspca_dev); | 148 | static void setcolors(struct gspca_dev *gspca_dev); |
146 | static void sethvflip(struct gspca_dev *gspca_dev); | 149 | static void sethvflip(struct gspca_dev *gspca_dev); |
147 | static void setautobright(struct gspca_dev *gspca_dev); | 150 | static void setautobright(struct gspca_dev *gspca_dev); |
151 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
148 | static void setfreq(struct gspca_dev *gspca_dev); | 152 | static void setfreq(struct gspca_dev *gspca_dev); |
149 | static void setfreq_i(struct sd *sd); | 153 | static void setfreq_i(struct sd *sd); |
150 | 154 | ||
@@ -173,6 +177,18 @@ static const struct ctrl sd_ctrls[] = { | |||
173 | }, | 177 | }, |
174 | .set_control = setcontrast, | 178 | .set_control = setcontrast, |
175 | }, | 179 | }, |
180 | [EXPOSURE] = { | ||
181 | { | ||
182 | .id = V4L2_CID_EXPOSURE, | ||
183 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
184 | .name = "Exposure", | ||
185 | .minimum = 0, | ||
186 | .maximum = 255, | ||
187 | .step = 1, | ||
188 | .default_value = 127, | ||
189 | }, | ||
190 | .set_control = setexposure, | ||
191 | }, | ||
176 | [COLORS] = { | 192 | [COLORS] = { |
177 | { | 193 | { |
178 | .id = V4L2_CID_SATURATION, | 194 | .id = V4L2_CID_SATURATION, |
@@ -222,6 +238,19 @@ static const struct ctrl sd_ctrls[] = { | |||
222 | }, | 238 | }, |
223 | .set_control = setautobright, | 239 | .set_control = setautobright, |
224 | }, | 240 | }, |
241 | [AUTOGAIN] = { | ||
242 | { | ||
243 | .id = V4L2_CID_AUTOGAIN, | ||
244 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
245 | .name = "Auto Gain", | ||
246 | .minimum = 0, | ||
247 | .maximum = 1, | ||
248 | .step = 1, | ||
249 | .default_value = 1, | ||
250 | .flags = V4L2_CTRL_FLAG_UPDATE | ||
251 | }, | ||
252 | .set = sd_setautogain, | ||
253 | }, | ||
225 | [FREQ] = { | 254 | [FREQ] = { |
226 | { | 255 | { |
227 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 256 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -238,50 +267,78 @@ static const struct ctrl sd_ctrls[] = { | |||
238 | 267 | ||
239 | /* table of the disabled controls */ | 268 | /* table of the disabled controls */ |
240 | static const unsigned ctrl_dis[] = { | 269 | static const unsigned ctrl_dis[] = { |
241 | [SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ | 270 | [SEN_OV2610] = ((1 << NCTRL) - 1) /* no control */ |
271 | ^ ((1 << EXPOSURE) /* but exposure */ | ||
272 | | (1 << AUTOGAIN)), /* and autogain */ | ||
242 | 273 | ||
243 | [SEN_OV2610AE] = (1 << NCTRL) - 1, /* no control */ | 274 | [SEN_OV2610AE] = ((1 << NCTRL) - 1) /* no control */ |
275 | ^ ((1 << EXPOSURE) /* but exposure */ | ||
276 | | (1 << AUTOGAIN)), /* and autogain */ | ||
244 | 277 | ||
245 | [SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ | 278 | [SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ |
246 | 279 | ||
247 | [SEN_OV6620] = (1 << HFLIP) | | 280 | [SEN_OV6620] = (1 << HFLIP) | |
248 | (1 << VFLIP), | 281 | (1 << VFLIP) | |
282 | (1 << EXPOSURE) | | ||
283 | (1 << AUTOGAIN), | ||
249 | 284 | ||
250 | [SEN_OV6630] = (1 << HFLIP) | | 285 | [SEN_OV6630] = (1 << HFLIP) | |
251 | (1 << VFLIP), | 286 | (1 << VFLIP) | |
287 | (1 << EXPOSURE) | | ||
288 | (1 << AUTOGAIN), | ||
252 | 289 | ||
253 | [SEN_OV66308AF] = (1 << HFLIP) | | 290 | [SEN_OV66308AF] = (1 << HFLIP) | |
254 | (1 << VFLIP), | 291 | (1 << VFLIP) | |
292 | (1 << EXPOSURE) | | ||
293 | (1 << AUTOGAIN), | ||
255 | 294 | ||
256 | [SEN_OV7610] = (1 << HFLIP) | | 295 | [SEN_OV7610] = (1 << HFLIP) | |
257 | (1 << VFLIP), | 296 | (1 << VFLIP) | |
297 | (1 << EXPOSURE) | | ||
298 | (1 << AUTOGAIN), | ||
258 | 299 | ||
259 | [SEN_OV7620] = (1 << HFLIP) | | 300 | [SEN_OV7620] = (1 << HFLIP) | |
260 | (1 << VFLIP), | 301 | (1 << VFLIP) | |
302 | (1 << EXPOSURE) | | ||
303 | (1 << AUTOGAIN), | ||
261 | 304 | ||
262 | [SEN_OV7620AE] = (1 << HFLIP) | | 305 | [SEN_OV7620AE] = (1 << HFLIP) | |
263 | (1 << VFLIP), | 306 | (1 << VFLIP) | |
307 | (1 << EXPOSURE) | | ||
308 | (1 << AUTOGAIN), | ||
264 | 309 | ||
265 | [SEN_OV7640] = (1 << HFLIP) | | 310 | [SEN_OV7640] = (1 << HFLIP) | |
266 | (1 << VFLIP) | | 311 | (1 << VFLIP) | |
267 | (1 << AUTOBRIGHT) | | 312 | (1 << AUTOBRIGHT) | |
268 | (1 << CONTRAST), | 313 | (1 << CONTRAST) | |
314 | (1 << EXPOSURE) | | ||
315 | (1 << AUTOGAIN), | ||
269 | 316 | ||
270 | [SEN_OV7648] = (1 << HFLIP) | | 317 | [SEN_OV7648] = (1 << HFLIP) | |
271 | (1 << VFLIP) | | 318 | (1 << VFLIP) | |
272 | (1 << AUTOBRIGHT) | | 319 | (1 << AUTOBRIGHT) | |
273 | (1 << CONTRAST), | 320 | (1 << CONTRAST) | |
321 | (1 << EXPOSURE) | | ||
322 | (1 << AUTOGAIN), | ||
274 | 323 | ||
275 | [SEN_OV7660] = (1 << AUTOBRIGHT), | 324 | [SEN_OV7660] = (1 << AUTOBRIGHT) | |
325 | (1 << EXPOSURE) | | ||
326 | (1 << AUTOGAIN), | ||
276 | 327 | ||
277 | [SEN_OV7670] = (1 << COLORS) | | 328 | [SEN_OV7670] = (1 << COLORS) | |
278 | (1 << AUTOBRIGHT), | 329 | (1 << AUTOBRIGHT) | |
330 | (1 << EXPOSURE) | | ||
331 | (1 << AUTOGAIN), | ||
279 | 332 | ||
280 | [SEN_OV76BE] = (1 << HFLIP) | | 333 | [SEN_OV76BE] = (1 << HFLIP) | |
281 | (1 << VFLIP), | 334 | (1 << VFLIP) | |
335 | (1 << EXPOSURE) | | ||
336 | (1 << AUTOGAIN), | ||
282 | 337 | ||
283 | [SEN_OV8610] = (1 << HFLIP) | | 338 | [SEN_OV8610] = (1 << HFLIP) | |
284 | (1 << VFLIP) | | 339 | (1 << VFLIP) | |
340 | (1 << EXPOSURE) | | ||
341 | (1 << AUTOGAIN) | | ||
285 | (1 << FREQ), | 342 | (1 << FREQ), |
286 | }; | 343 | }; |
287 | 344 | ||
@@ -3201,6 +3258,13 @@ static void ov519_set_fr(struct sd *sd) | |||
3201 | ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); | 3258 | ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); |
3202 | } | 3259 | } |
3203 | 3260 | ||
3261 | static void setautogain(struct gspca_dev *gspca_dev) | ||
3262 | { | ||
3263 | struct sd *sd = (struct sd *) gspca_dev; | ||
3264 | |||
3265 | i2c_w_mask(sd, 0x13, sd->ctrls[AUTOGAIN].val ? 0x05 : 0x00, 0x05); | ||
3266 | } | ||
3267 | |||
3204 | /* this function is called at probe time */ | 3268 | /* this function is called at probe time */ |
3205 | static int sd_config(struct gspca_dev *gspca_dev, | 3269 | static int sd_config(struct gspca_dev *gspca_dev, |
3206 | const struct usb_device_id *id) | 3270 | const struct usb_device_id *id) |
@@ -4189,12 +4253,16 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
4189 | setcontrast(gspca_dev); | 4253 | setcontrast(gspca_dev); |
4190 | if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) | 4254 | if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) |
4191 | setbrightness(gspca_dev); | 4255 | setbrightness(gspca_dev); |
4256 | if (!(sd->gspca_dev.ctrl_dis & (1 << EXPOSURE))) | ||
4257 | setexposure(gspca_dev); | ||
4192 | if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) | 4258 | if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) |
4193 | setcolors(gspca_dev); | 4259 | setcolors(gspca_dev); |
4194 | if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) | 4260 | if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) |
4195 | sethvflip(gspca_dev); | 4261 | sethvflip(gspca_dev); |
4196 | if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) | 4262 | if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) |
4197 | setautobright(gspca_dev); | 4263 | setautobright(gspca_dev); |
4264 | if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOGAIN))) | ||
4265 | setautogain(gspca_dev); | ||
4198 | if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) | 4266 | if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) |
4199 | setfreq_i(sd); | 4267 | setfreq_i(sd); |
4200 | 4268 | ||
@@ -4608,6 +4676,14 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4608 | } | 4676 | } |
4609 | } | 4677 | } |
4610 | 4678 | ||
4679 | static void setexposure(struct gspca_dev *gspca_dev) | ||
4680 | { | ||
4681 | struct sd *sd = (struct sd *) gspca_dev; | ||
4682 | |||
4683 | if (!sd->ctrls[AUTOGAIN].val) | ||
4684 | i2c_w(sd, 0x10, sd->ctrls[EXPOSURE].val); | ||
4685 | } | ||
4686 | |||
4611 | static void setcolors(struct gspca_dev *gspca_dev) | 4687 | static void setcolors(struct gspca_dev *gspca_dev) |
4612 | { | 4688 | { |
4613 | struct sd *sd = (struct sd *) gspca_dev; | 4689 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -4666,6 +4742,22 @@ static void setautobright(struct gspca_dev *gspca_dev) | |||
4666 | i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); | 4742 | i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); |
4667 | } | 4743 | } |
4668 | 4744 | ||
4745 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
4746 | { | ||
4747 | struct sd *sd = (struct sd *) gspca_dev; | ||
4748 | |||
4749 | sd->ctrls[AUTOGAIN].val = val; | ||
4750 | if (val) { | ||
4751 | gspca_dev->ctrl_inac |= (1 << EXPOSURE); | ||
4752 | } else { | ||
4753 | gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); | ||
4754 | sd->ctrls[EXPOSURE].val = i2c_r(sd, 0x10); | ||
4755 | } | ||
4756 | if (gspca_dev->streaming) | ||
4757 | setautogain(gspca_dev); | ||
4758 | return gspca_dev->usb_err; | ||
4759 | } | ||
4760 | |||
4669 | static void setfreq_i(struct sd *sd) | 4761 | static void setfreq_i(struct sd *sd) |
4670 | { | 4762 | { |
4671 | if (sd->sensor == SEN_OV7660 | 4763 | if (sd->sensor == SEN_OV7660 |