Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Jean-François Moine and committed by
Mauro Carvalho Chehab
58c92d37 7d47b789

+106 -14
+106 -14
drivers/media/video/gspca/ov519.c
··· 1 1 /** 2 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 5 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> 6 6 * 7 7 * This module is adapted from the ov51x-jpeg package, which itself ··· 61 61 enum e_ctrl { 62 62 BRIGHTNESS, 63 63 CONTRAST, 64 + EXPOSURE, 64 65 COLORS, 65 66 HFLIP, 66 67 VFLIP, 67 68 AUTOBRIGHT, 69 + AUTOGAIN, 68 70 FREQ, 69 71 NCTRL /* number of controls */ 70 72 }; ··· 144 142 /* V4L2 controls supported by the driver */ 145 143 static void setbrightness(struct gspca_dev *gspca_dev); 146 144 static void setcontrast(struct gspca_dev *gspca_dev); 145 + static void setexposure(struct gspca_dev *gspca_dev); 147 146 static void setcolors(struct gspca_dev *gspca_dev); 148 147 static void sethvflip(struct gspca_dev *gspca_dev); 149 148 static void setautobright(struct gspca_dev *gspca_dev); 149 + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 150 150 static void setfreq(struct gspca_dev *gspca_dev); 151 151 static void setfreq_i(struct sd *sd); 152 152 ··· 176 172 .default_value = 127, 177 173 }, 178 174 .set_control = setcontrast, 175 + }, 176 + [EXPOSURE] = { 177 + { 178 + .id = V4L2_CID_EXPOSURE, 179 + .type = V4L2_CTRL_TYPE_INTEGER, 180 + .name = "Exposure", 181 + .minimum = 0, 182 + .maximum = 255, 183 + .step = 1, 184 + .default_value = 127, 185 + }, 186 + .set_control = setexposure, 179 187 }, 180 188 [COLORS] = { 181 189 { ··· 238 222 }, 239 223 .set_control = setautobright, 240 224 }, 225 + [AUTOGAIN] = { 226 + { 227 + .id = V4L2_CID_AUTOGAIN, 228 + .type = V4L2_CTRL_TYPE_BOOLEAN, 229 + .name = "Auto Gain", 230 + .minimum = 0, 231 + .maximum = 1, 232 + .step = 1, 233 + .default_value = 1, 234 + .flags = V4L2_CTRL_FLAG_UPDATE 235 + }, 236 + .set = sd_setautogain, 237 + }, 241 238 [FREQ] = { 242 239 { 243 240 .id = V4L2_CID_POWER_LINE_FREQUENCY, ··· 267 238 268 239 /* table of the disabled controls */ 269 240 static const unsigned ctrl_dis[] = { 270 - [SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ 241 + [SEN_OV2610] = ((1 << NCTRL) - 1) /* no control */ 242 + ^ ((1 << EXPOSURE) /* but exposure */ 243 + | (1 << AUTOGAIN)), /* and autogain */ 271 244 272 - [SEN_OV2610AE] = (1 << NCTRL) - 1, /* no control */ 245 + [SEN_OV2610AE] = ((1 << NCTRL) - 1) /* no control */ 246 + ^ ((1 << EXPOSURE) /* but exposure */ 247 + | (1 << AUTOGAIN)), /* and autogain */ 273 248 274 249 [SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ 275 250 276 251 [SEN_OV6620] = (1 << HFLIP) | 277 - (1 << VFLIP), 252 + (1 << VFLIP) | 253 + (1 << EXPOSURE) | 254 + (1 << AUTOGAIN), 278 255 279 256 [SEN_OV6630] = (1 << HFLIP) | 280 - (1 << VFLIP), 257 + (1 << VFLIP) | 258 + (1 << EXPOSURE) | 259 + (1 << AUTOGAIN), 281 260 282 261 [SEN_OV66308AF] = (1 << HFLIP) | 283 - (1 << VFLIP), 262 + (1 << VFLIP) | 263 + (1 << EXPOSURE) | 264 + (1 << AUTOGAIN), 284 265 285 266 [SEN_OV7610] = (1 << HFLIP) | 286 - (1 << VFLIP), 267 + (1 << VFLIP) | 268 + (1 << EXPOSURE) | 269 + (1 << AUTOGAIN), 287 270 288 271 [SEN_OV7620] = (1 << HFLIP) | 289 - (1 << VFLIP), 272 + (1 << VFLIP) | 273 + (1 << EXPOSURE) | 274 + (1 << AUTOGAIN), 290 275 291 276 [SEN_OV7620AE] = (1 << HFLIP) | 292 - (1 << VFLIP), 277 + (1 << VFLIP) | 278 + (1 << EXPOSURE) | 279 + (1 << AUTOGAIN), 293 280 294 281 [SEN_OV7640] = (1 << HFLIP) | 295 282 (1 << VFLIP) | 296 283 (1 << AUTOBRIGHT) | 297 - (1 << CONTRAST), 284 + (1 << CONTRAST) | 285 + (1 << EXPOSURE) | 286 + (1 << AUTOGAIN), 298 287 299 288 [SEN_OV7648] = (1 << HFLIP) | 300 289 (1 << VFLIP) | 301 290 (1 << AUTOBRIGHT) | 302 - (1 << CONTRAST), 291 + (1 << CONTRAST) | 292 + (1 << EXPOSURE) | 293 + (1 << AUTOGAIN), 303 294 304 - [SEN_OV7660] = (1 << AUTOBRIGHT), 295 + [SEN_OV7660] = (1 << AUTOBRIGHT) | 296 + (1 << EXPOSURE) | 297 + (1 << AUTOGAIN), 305 298 306 299 [SEN_OV7670] = (1 << COLORS) | 307 - (1 << AUTOBRIGHT), 300 + (1 << AUTOBRIGHT) | 301 + (1 << EXPOSURE) | 302 + (1 << AUTOGAIN), 308 303 309 304 [SEN_OV76BE] = (1 << HFLIP) | 310 - (1 << VFLIP), 305 + (1 << VFLIP) | 306 + (1 << EXPOSURE) | 307 + (1 << AUTOGAIN), 311 308 312 309 [SEN_OV8610] = (1 << HFLIP) | 313 310 (1 << VFLIP) | 311 + (1 << EXPOSURE) | 312 + (1 << AUTOGAIN) | 314 313 (1 << FREQ), 315 314 }; 316 315 ··· 3258 3201 ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); 3259 3202 } 3260 3203 3204 + static void setautogain(struct gspca_dev *gspca_dev) 3205 + { 3206 + struct sd *sd = (struct sd *) gspca_dev; 3207 + 3208 + i2c_w_mask(sd, 0x13, sd->ctrls[AUTOGAIN].val ? 0x05 : 0x00, 0x05); 3209 + } 3210 + 3261 3211 /* this function is called at probe time */ 3262 3212 static int sd_config(struct gspca_dev *gspca_dev, 3263 3213 const struct usb_device_id *id) ··· 4253 4189 setcontrast(gspca_dev); 4254 4190 if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) 4255 4191 setbrightness(gspca_dev); 4192 + if (!(sd->gspca_dev.ctrl_dis & (1 << EXPOSURE))) 4193 + setexposure(gspca_dev); 4256 4194 if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) 4257 4195 setcolors(gspca_dev); 4258 4196 if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) 4259 4197 sethvflip(gspca_dev); 4260 4198 if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) 4261 4199 setautobright(gspca_dev); 4200 + if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOGAIN))) 4201 + setautogain(gspca_dev); 4262 4202 if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) 4263 4203 setfreq_i(sd); 4264 4204 ··· 4676 4608 } 4677 4609 } 4678 4610 4611 + static void setexposure(struct gspca_dev *gspca_dev) 4612 + { 4613 + struct sd *sd = (struct sd *) gspca_dev; 4614 + 4615 + if (!sd->ctrls[AUTOGAIN].val) 4616 + i2c_w(sd, 0x10, sd->ctrls[EXPOSURE].val); 4617 + } 4618 + 4679 4619 static void setcolors(struct gspca_dev *gspca_dev) 4680 4620 { 4681 4621 struct sd *sd = (struct sd *) gspca_dev; ··· 4740 4664 struct sd *sd = (struct sd *) gspca_dev; 4741 4665 4742 4666 i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); 4667 + } 4668 + 4669 + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) 4670 + { 4671 + struct sd *sd = (struct sd *) gspca_dev; 4672 + 4673 + sd->ctrls[AUTOGAIN].val = val; 4674 + if (val) { 4675 + gspca_dev->ctrl_inac |= (1 << EXPOSURE); 4676 + } else { 4677 + gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); 4678 + sd->ctrls[EXPOSURE].val = i2c_r(sd, 0x10); 4679 + } 4680 + if (gspca_dev->streaming) 4681 + setautogain(gspca_dev); 4682 + return gspca_dev->usb_err; 4743 4683 } 4744 4684 4745 4685 static void setfreq_i(struct sd *sd)