1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#include "m5602_ov9650.h"
19
20static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
21static void ov9650_dump_registers(struct sd *sd);
22
23static const unsigned char preinit_ov9650[][3] = {
24
25 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
26 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
27 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
28 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
29 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
30 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
31
32 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
33 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
34 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
35 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
36 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
37 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
38 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
39 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
40
41 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
42
43 {SENSOR, OV9650_CLKRC, 0x80},
44
45 {SENSOR, OV9650_OFON, 0x40}
46};
47
48static const unsigned char init_ov9650[][3] = {
49
50 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
51 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
52 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
53 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
54 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
55 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
56
57 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
58 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
59 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
60 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
61 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
62 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
63 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
64 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
65
66
67 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
68
69
70 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
71
72
73 {SENSOR, OV9650_CLKRC, 0x80},
74
75 {SENSOR, OV9650_OFON, 0x40},
76
77
78 {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
79 OV9650_AEC_UNLIM_STEP_SIZE},
80
81 {SENSOR, OV9650_CHLF, 0x10},
82 {SENSOR, OV9650_ARBLM, 0xbf},
83 {SENSOR, OV9650_ACOM38, 0x81},
84
85 {SENSOR, OV9650_COM16, 0x00},
86
87
88 {SENSOR, OV9650_COM13, 0x19},
89
90 {SENSOR, OV9650_TSLB, 0x0c},
91
92 {SENSOR, OV9650_COM24, 0x00},
93
94 {SENSOR, OV9650_COM12, 0x73},
95
96
97 {SENSOR, OV9650_DBLC1, 0xdf},
98 {SENSOR, OV9650_COM21, 0x06},
99 {SENSOR, OV9650_RSVD35, 0x91},
100
101 {SENSOR, OV9650_RSVD16, 0x06},
102 {SENSOR, OV9650_RSVD94, 0x99},
103 {SENSOR, OV9650_RSVD95, 0x99},
104 {SENSOR, OV9650_RSVD96, 0x04},
105
106 {SENSOR, OV9650_COM15, 0x0},
107
108
109 {SENSOR, OV9650_COM6, 0x4b},
110
111 {SENSOR, OV9650_BBIAS, 0xa0},
112
113 {SENSOR, OV9650_GbBIAS, 0xa0},
114
115 {SENSOR, OV9650_Gr_COM, 0x00},
116
117 {SENSOR, OV9650_RBIAS, 0xa0},
118
119 {SENSOR, OV9650_RBIAS, 0x0},
120 {SENSOR, OV9650_COM26, 0x80},
121 {SENSOR, OV9650_ACOMA9, 0x98},
122
123 {SENSOR, OV9650_AEW, 0x68},
124
125 {SENSOR, OV9650_AEB, 0x5c},
126
127 {SENSOR, OV9650_VPT, 0xc3},
128
129
130
131
132 {SENSOR, OV9650_COM9, 0x6e},
133
134
135 {SENSOR, OV9650_COM10, 0x42},
136
137 {SENSOR, OV9650_HSTART, 0x1a},
138
139 {SENSOR, OV9650_HSTOP, 0xbf},
140
141 {SENSOR, OV9650_HREF, 0xb2},
142
143 {SENSOR, OV9650_VSTRT, 0x02},
144
145 {SENSOR, OV9650_VSTOP, 0x7e},
146
147 {SENSOR, OV9650_VREF, 0x10},
148 {SENSOR, OV9650_ADC, 0x04},
149 {SENSOR, OV9650_HV, 0x40},
150
151
152 {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
153 OV9650_WHITE_PIXEL_ENABLE |
154 OV9650_WHITE_PIXEL_OPTION},
155
156
157 {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
158 {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
159
160
161 {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
162};
163
164static const unsigned char res_init_ov9650[][3] = {
165 {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
166
167 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
168 {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
169 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
170 {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
171 {BRIDGE, M5602_XB_SIG_INI, 0x01}
172};
173
174
175
176static
177 const
178 struct dmi_system_id ov9650_flip_dmi_table[] = {
179 {
180 .ident = "ASUS A6Ja",
181 .matches = {
182 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
183 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
184 }
185 },
186 {
187 .ident = "ASUS A6JC",
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
190 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
191 }
192 },
193 {
194 .ident = "ASUS A6K",
195 .matches = {
196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
197 DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
198 }
199 },
200 {
201 .ident = "ASUS A6Kt",
202 .matches = {
203 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
204 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
205 }
206 },
207 {
208 .ident = "ASUS A6VA",
209 .matches = {
210 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
211 DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
212 }
213 },
214 {
215
216 .ident = "ASUS A6VC",
217 .matches = {
218 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
219 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
220 }
221 },
222 {
223 .ident = "ASUS A6VM",
224 .matches = {
225 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
226 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
227 }
228 },
229 {
230 .ident = "ASUS A7V",
231 .matches = {
232 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
233 DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
234 }
235 },
236 {
237 .ident = "Alienware Aurora m9700",
238 .matches = {
239 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
240 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
241 }
242 },
243 {}
244};
245
246static struct v4l2_pix_format ov9650_modes[] = {
247 {
248 176,
249 144,
250 V4L2_PIX_FMT_SBGGR8,
251 V4L2_FIELD_NONE,
252 .sizeimage =
253 176 * 144,
254 .bytesperline = 176,
255 .colorspace = V4L2_COLORSPACE_SRGB,
256 .priv = 9
257 }, {
258 320,
259 240,
260 V4L2_PIX_FMT_SBGGR8,
261 V4L2_FIELD_NONE,
262 .sizeimage =
263 320 * 240,
264 .bytesperline = 320,
265 .colorspace = V4L2_COLORSPACE_SRGB,
266 .priv = 8
267 }, {
268 352,
269 288,
270 V4L2_PIX_FMT_SBGGR8,
271 V4L2_FIELD_NONE,
272 .sizeimage =
273 352 * 288,
274 .bytesperline = 352,
275 .colorspace = V4L2_COLORSPACE_SRGB,
276 .priv = 9
277 }, {
278 640,
279 480,
280 V4L2_PIX_FMT_SBGGR8,
281 V4L2_FIELD_NONE,
282 .sizeimage =
283 640 * 480,
284 .bytesperline = 640,
285 .colorspace = V4L2_COLORSPACE_SRGB,
286 .priv = 9
287 }
288};
289
290static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
291 .s_ctrl = ov9650_s_ctrl,
292};
293
294int ov9650_probe(struct sd *sd)
295{
296 int err = 0;
297 u8 prod_id = 0, ver_id = 0, i;
298 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
299
300 if (force_sensor) {
301 if (force_sensor == OV9650_SENSOR) {
302 pr_info("Forcing an %s sensor\n", ov9650.name);
303 goto sensor_found;
304 }
305
306
307 return -ENODEV;
308 }
309
310 gspca_dbg(gspca_dev, D_PROBE, "Probing for an ov9650 sensor\n");
311
312
313 for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
314 u8 data = preinit_ov9650[i][2];
315 if (preinit_ov9650[i][0] == SENSOR)
316 err = m5602_write_sensor(sd,
317 preinit_ov9650[i][1], &data, 1);
318 else
319 err = m5602_write_bridge(sd,
320 preinit_ov9650[i][1], data);
321 }
322
323 if (err < 0)
324 return err;
325
326 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
327 return -ENODEV;
328
329 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
330 return -ENODEV;
331
332 if ((prod_id == 0x96) && (ver_id == 0x52)) {
333 pr_info("Detected an ov9650 sensor\n");
334 goto sensor_found;
335 }
336 return -ENODEV;
337
338sensor_found:
339 sd->gspca_dev.cam.cam_mode = ov9650_modes;
340 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
341
342 return 0;
343}
344
345int ov9650_init(struct sd *sd)
346{
347 int i, err = 0;
348 u8 data;
349
350 if (dump_sensor)
351 ov9650_dump_registers(sd);
352
353 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
354 data = init_ov9650[i][2];
355 if (init_ov9650[i][0] == SENSOR)
356 err = m5602_write_sensor(sd, init_ov9650[i][1],
357 &data, 1);
358 else
359 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
360 }
361
362 return 0;
363}
364
365int ov9650_init_controls(struct sd *sd)
366{
367 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
368
369 sd->gspca_dev.vdev.ctrl_handler = hdl;
370 v4l2_ctrl_handler_init(hdl, 9);
371
372 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
373 V4L2_CID_AUTO_WHITE_BALANCE,
374 0, 1, 1, 1);
375 sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
376 V4L2_CID_RED_BALANCE, 0, 255, 1,
377 RED_GAIN_DEFAULT);
378 sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
379 V4L2_CID_BLUE_BALANCE, 0, 255, 1,
380 BLUE_GAIN_DEFAULT);
381
382 sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &ov9650_ctrl_ops,
383 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
384 sd->expo = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_EXPOSURE,
385 0, 0x1ff, 4, EXPOSURE_DEFAULT);
386
387 sd->autogain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
388 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
389 sd->gain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_GAIN, 0,
390 0x3ff, 1, GAIN_DEFAULT);
391
392 sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
393 0, 1, 1, 0);
394 sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
395 0, 1, 1, 0);
396
397 if (hdl->error) {
398 pr_err("Could not initialize controls\n");
399 return hdl->error;
400 }
401
402 v4l2_ctrl_auto_cluster(3, &sd->auto_white_bal, 0, false);
403 v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
404 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
405 v4l2_ctrl_cluster(2, &sd->hflip);
406
407 return 0;
408}
409
410int ov9650_start(struct sd *sd)
411{
412 u8 data;
413 int i, err = 0;
414 struct cam *cam = &sd->gspca_dev.cam;
415
416 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
417 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
418 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
419 int hor_offs = OV9650_LEFT_OFFSET;
420 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
421
422 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
423 sd->vflip->val) ||
424 (dmi_check_system(ov9650_flip_dmi_table) &&
425 !sd->vflip->val))
426 ver_offs--;
427
428 if (width <= 320)
429 hor_offs /= 2;
430
431
432 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
433 if (res_init_ov9650[i][0] == BRIDGE)
434 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
435 res_init_ov9650[i][2]);
436 else if (res_init_ov9650[i][0] == SENSOR) {
437 data = res_init_ov9650[i][2];
438 err = m5602_write_sensor(sd,
439 res_init_ov9650[i][1], &data, 1);
440 }
441 }
442 if (err < 0)
443 return err;
444
445 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
446 ((ver_offs >> 8) & 0xff));
447 if (err < 0)
448 return err;
449
450 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
451 if (err < 0)
452 return err;
453
454 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
455 if (err < 0)
456 return err;
457
458 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
459 if (err < 0)
460 return err;
461
462 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
463 if (err < 0)
464 return err;
465
466 for (i = 0; i < 2 && !err; i++)
467 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
468 if (err < 0)
469 return err;
470
471 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
472 if (err < 0)
473 return err;
474
475 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
476 if (err < 0)
477 return err;
478
479 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
480 (hor_offs >> 8) & 0xff);
481 if (err < 0)
482 return err;
483
484 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
485 if (err < 0)
486 return err;
487
488 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
489 ((width + hor_offs) >> 8) & 0xff);
490 if (err < 0)
491 return err;
492
493 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
494 ((width + hor_offs) & 0xff));
495 if (err < 0)
496 return err;
497
498 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
499 if (err < 0)
500 return err;
501
502 switch (width) {
503 case 640:
504 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
505
506 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
507 OV9650_RAW_RGB_SELECT;
508 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
509 break;
510
511 case 352:
512 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for CIF mode\n");
513
514 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
515 OV9650_RAW_RGB_SELECT;
516 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
517 break;
518
519 case 320:
520 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n");
521
522 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
523 OV9650_RAW_RGB_SELECT;
524 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
525 break;
526
527 case 176:
528 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QCIF mode\n");
529
530 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
531 OV9650_RAW_RGB_SELECT;
532 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
533 break;
534 }
535 return err;
536}
537
538int ov9650_stop(struct sd *sd)
539{
540 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
541 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
542}
543
544void ov9650_disconnect(struct sd *sd)
545{
546 ov9650_stop(sd);
547
548 sd->sensor = NULL;
549}
550
551static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 u8 i2c_data;
555 int err;
556
557 gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d\n", val);
558
559
560 i2c_data = (val >> 10) & 0x3f;
561 err = m5602_write_sensor(sd, OV9650_AECHM,
562 &i2c_data, 1);
563 if (err < 0)
564 return err;
565
566
567 i2c_data = (val >> 2) & 0xff;
568 err = m5602_write_sensor(sd, OV9650_AECH,
569 &i2c_data, 1);
570 if (err < 0)
571 return err;
572
573
574 i2c_data = val & 0x03;
575 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
576 return err;
577}
578
579static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
580{
581 int err;
582 u8 i2c_data;
583 struct sd *sd = (struct sd *) gspca_dev;
584
585 gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val);
586
587
588
589
590 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
591 if (err < 0)
592 return err;
593
594
595 i2c_data = ((val & 0x0300) >> 2) |
596 (i2c_data & 0x3f);
597 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
598 if (err < 0)
599 return err;
600
601
602 i2c_data = val & 0xff;
603 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
604 return err;
605}
606
607static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
608{
609 int err;
610 u8 i2c_data;
611 struct sd *sd = (struct sd *) gspca_dev;
612
613 gspca_dbg(gspca_dev, D_CONF, "Set red gain to %d\n", val);
614
615 i2c_data = val & 0xff;
616 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
617 return err;
618}
619
620static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
621{
622 int err;
623 u8 i2c_data;
624 struct sd *sd = (struct sd *) gspca_dev;
625
626 gspca_dbg(gspca_dev, D_CONF, "Set blue gain to %d\n", val);
627
628 i2c_data = val & 0xff;
629 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
630 return err;
631}
632
633static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
634{
635 int err;
636 u8 i2c_data;
637 struct sd *sd = (struct sd *) gspca_dev;
638 int hflip = sd->hflip->val;
639 int vflip = sd->vflip->val;
640
641 gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n", hflip, vflip);
642
643 if (dmi_check_system(ov9650_flip_dmi_table))
644 vflip = !vflip;
645
646 i2c_data = (hflip << 5) | (vflip << 4);
647 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
648 if (err < 0)
649 return err;
650
651
652 if (gspca_dev->streaming)
653 err = ov9650_start(sd);
654
655 return err;
656}
657
658static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
659 __s32 val)
660{
661 int err;
662 u8 i2c_data;
663 struct sd *sd = (struct sd *) gspca_dev;
664
665 gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val);
666
667 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
668 if (err < 0)
669 return err;
670
671 val = (val == V4L2_EXPOSURE_AUTO);
672 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
673
674 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
675}
676
677static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
678 __s32 val)
679{
680 int err;
681 u8 i2c_data;
682 struct sd *sd = (struct sd *) gspca_dev;
683
684 gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val);
685
686 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
687 if (err < 0)
688 return err;
689
690 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
691 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
692
693 return err;
694}
695
696static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
697{
698 int err;
699 u8 i2c_data;
700 struct sd *sd = (struct sd *) gspca_dev;
701
702 gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val);
703
704 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
705 if (err < 0)
706 return err;
707
708 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
709
710 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
711}
712
713static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
714{
715 struct gspca_dev *gspca_dev =
716 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
717 struct sd *sd = (struct sd *) gspca_dev;
718 int err;
719
720 if (!gspca_dev->streaming)
721 return 0;
722
723 switch (ctrl->id) {
724 case V4L2_CID_AUTO_WHITE_BALANCE:
725 err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
726 if (err || ctrl->val)
727 return err;
728 err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
729 if (err)
730 return err;
731 err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
732 break;
733 case V4L2_CID_EXPOSURE_AUTO:
734 err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
735 if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
736 return err;
737 err = ov9650_set_exposure(gspca_dev, sd->expo->val);
738 break;
739 case V4L2_CID_AUTOGAIN:
740 err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
741 if (err || ctrl->val)
742 return err;
743 err = ov9650_set_gain(gspca_dev, sd->gain->val);
744 break;
745 case V4L2_CID_HFLIP:
746 err = ov9650_set_hvflip(gspca_dev);
747 break;
748 default:
749 return -EINVAL;
750 }
751
752 return err;
753}
754
755static void ov9650_dump_registers(struct sd *sd)
756{
757 int address;
758 pr_info("Dumping the ov9650 register state\n");
759 for (address = 0; address < 0xa9; address++) {
760 u8 value;
761 m5602_read_sensor(sd, address, &value, 1);
762 pr_info("register 0x%x contains 0x%x\n", address, value);
763 }
764
765 pr_info("ov9650 register state dump complete\n");
766
767 pr_info("Probing for which registers that are read/write\n");
768 for (address = 0; address < 0xff; address++) {
769 u8 old_value, ctrl_value;
770 u8 test_value[2] = {0xff, 0xff};
771
772 m5602_read_sensor(sd, address, &old_value, 1);
773 m5602_write_sensor(sd, address, test_value, 1);
774 m5602_read_sensor(sd, address, &ctrl_value, 1);
775
776 if (ctrl_value == test_value[0])
777 pr_info("register 0x%x is writeable\n", address);
778 else
779 pr_info("register 0x%x is read only\n", address);
780
781
782 m5602_write_sensor(sd, address, &old_value, 1);
783 }
784}
785