]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/video/gspca/m5602/m5602_ov9650.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
[mirror_ubuntu-artful-kernel.git] / drivers / media / video / gspca / m5602 / m5602_ov9650.c
1 /*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19 #include "m5602_ov9650.h"
20
21 /* Vertically and horizontally flips the image if matched, needed for machines
22 where the sensor is mounted upside down */
23 static
24 const
25 struct dmi_system_id ov9650_flip_dmi_table[] = {
26 {
27 .ident = "ASUS A6VC",
28 .matches = {
29 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
30 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
31 }
32 },
33 {
34 .ident = "ASUS A6VM",
35 .matches = {
36 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
37 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
38 }
39 },
40 {
41 .ident = "ASUS A6JC",
42 .matches = {
43 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
44 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
45 }
46 },
47 {
48 .ident = "ASUS A6Ja",
49 .matches = {
50 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
51 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
52 }
53 },
54 {
55 .ident = "ASUS A6Kt",
56 .matches = {
57 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
58 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
59 }
60 },
61 {
62 .ident = "Alienware Aurora m9700",
63 .matches = {
64 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
65 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
66 }
67 },
68 {}
69 };
70
71 const static struct ctrl ov9650_ctrls[] = {
72 #define EXPOSURE_IDX 0
73 {
74 {
75 .id = V4L2_CID_EXPOSURE,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "exposure",
78 .minimum = 0x00,
79 .maximum = 0x1ff,
80 .step = 0x4,
81 .default_value = EXPOSURE_DEFAULT,
82 .flags = V4L2_CTRL_FLAG_SLIDER
83 },
84 .set = ov9650_set_exposure,
85 .get = ov9650_get_exposure
86 },
87 #define GAIN_IDX 1
88 {
89 {
90 .id = V4L2_CID_GAIN,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "gain",
93 .minimum = 0x00,
94 .maximum = 0x3ff,
95 .step = 0x1,
96 .default_value = GAIN_DEFAULT,
97 .flags = V4L2_CTRL_FLAG_SLIDER
98 },
99 .set = ov9650_set_gain,
100 .get = ov9650_get_gain
101 },
102 #define RED_BALANCE_IDX 2
103 {
104 {
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "red balance",
107 .minimum = 0x00,
108 .maximum = 0xff,
109 .step = 0x1,
110 .default_value = RED_GAIN_DEFAULT,
111 .flags = V4L2_CTRL_FLAG_SLIDER
112 },
113 .set = ov9650_set_red_balance,
114 .get = ov9650_get_red_balance
115 },
116 #define BLUE_BALANCE_IDX 3
117 {
118 {
119 .type = V4L2_CTRL_TYPE_INTEGER,
120 .name = "blue balance",
121 .minimum = 0x00,
122 .maximum = 0xff,
123 .step = 0x1,
124 .default_value = BLUE_GAIN_DEFAULT,
125 .flags = V4L2_CTRL_FLAG_SLIDER
126 },
127 .set = ov9650_set_blue_balance,
128 .get = ov9650_get_blue_balance
129 },
130 #define HFLIP_IDX 4
131 {
132 {
133 .id = V4L2_CID_HFLIP,
134 .type = V4L2_CTRL_TYPE_BOOLEAN,
135 .name = "horizontal flip",
136 .minimum = 0,
137 .maximum = 1,
138 .step = 1,
139 .default_value = 0
140 },
141 .set = ov9650_set_hflip,
142 .get = ov9650_get_hflip
143 },
144 #define VFLIP_IDX 5
145 {
146 {
147 .id = V4L2_CID_VFLIP,
148 .type = V4L2_CTRL_TYPE_BOOLEAN,
149 .name = "vertical flip",
150 .minimum = 0,
151 .maximum = 1,
152 .step = 1,
153 .default_value = 0
154 },
155 .set = ov9650_set_vflip,
156 .get = ov9650_get_vflip
157 },
158 #define AUTO_WHITE_BALANCE_IDX 6
159 {
160 {
161 .id = V4L2_CID_AUTO_WHITE_BALANCE,
162 .type = V4L2_CTRL_TYPE_BOOLEAN,
163 .name = "auto white balance",
164 .minimum = 0,
165 .maximum = 1,
166 .step = 1,
167 .default_value = 1
168 },
169 .set = ov9650_set_auto_white_balance,
170 .get = ov9650_get_auto_white_balance
171 },
172 #define AUTO_GAIN_CTRL_IDX 7
173 {
174 {
175 .id = V4L2_CID_AUTOGAIN,
176 .type = V4L2_CTRL_TYPE_BOOLEAN,
177 .name = "auto gain control",
178 .minimum = 0,
179 .maximum = 1,
180 .step = 1,
181 .default_value = 1
182 },
183 .set = ov9650_set_auto_gain,
184 .get = ov9650_get_auto_gain
185 }
186 };
187
188 static struct v4l2_pix_format ov9650_modes[] = {
189 {
190 176,
191 144,
192 V4L2_PIX_FMT_SBGGR8,
193 V4L2_FIELD_NONE,
194 .sizeimage =
195 176 * 144,
196 .bytesperline = 176,
197 .colorspace = V4L2_COLORSPACE_SRGB,
198 .priv = 9
199 }, {
200 320,
201 240,
202 V4L2_PIX_FMT_SBGGR8,
203 V4L2_FIELD_NONE,
204 .sizeimage =
205 320 * 240,
206 .bytesperline = 320,
207 .colorspace = V4L2_COLORSPACE_SRGB,
208 .priv = 8
209 }, {
210 352,
211 288,
212 V4L2_PIX_FMT_SBGGR8,
213 V4L2_FIELD_NONE,
214 .sizeimage =
215 352 * 288,
216 .bytesperline = 352,
217 .colorspace = V4L2_COLORSPACE_SRGB,
218 .priv = 9
219 }, {
220 640,
221 480,
222 V4L2_PIX_FMT_SBGGR8,
223 V4L2_FIELD_NONE,
224 .sizeimage =
225 640 * 480,
226 .bytesperline = 640,
227 .colorspace = V4L2_COLORSPACE_SRGB,
228 .priv = 9
229 }
230 };
231
232 static void ov9650_dump_registers(struct sd *sd);
233
234 int ov9650_probe(struct sd *sd)
235 {
236 int err = 0;
237 u8 prod_id = 0, ver_id = 0, i;
238 s32 *sensor_settings;
239
240 if (force_sensor) {
241 if (force_sensor == OV9650_SENSOR) {
242 info("Forcing an %s sensor", ov9650.name);
243 goto sensor_found;
244 }
245 /* If we want to force another sensor,
246 don't try to probe this one */
247 return -ENODEV;
248 }
249
250 info("Probing for an ov9650 sensor");
251
252 /* Run the pre-init before probing the sensor */
253 for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
254 u8 data = preinit_ov9650[i][2];
255 if (preinit_ov9650[i][0] == SENSOR)
256 err = m5602_write_sensor(sd,
257 preinit_ov9650[i][1], &data, 1);
258 else
259 err = m5602_write_bridge(sd,
260 preinit_ov9650[i][1], data);
261 }
262
263 if (err < 0)
264 return err;
265
266 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
267 return -ENODEV;
268
269 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
270 return -ENODEV;
271
272 if ((prod_id == 0x96) && (ver_id == 0x52)) {
273 info("Detected an ov9650 sensor");
274 goto sensor_found;
275 }
276 return -ENODEV;
277
278 sensor_found:
279 sensor_settings = kmalloc(
280 ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
281 if (!sensor_settings)
282 return -ENOMEM;
283
284 sd->gspca_dev.cam.cam_mode = ov9650_modes;
285 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
286 sd->desc->ctrls = ov9650_ctrls;
287 sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
288
289 for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
290 sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
291 sd->sensor_priv = sensor_settings;
292
293 if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
294 info("vflip quirk active");
295 sensor_settings[VFLIP_IDX] = 1;
296 }
297
298 return 0;
299 }
300
301 int ov9650_init(struct sd *sd)
302 {
303 int i, err = 0;
304 u8 data;
305 s32 *sensor_settings = sd->sensor_priv;
306
307 if (dump_sensor)
308 ov9650_dump_registers(sd);
309
310 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
311 data = init_ov9650[i][2];
312 if (init_ov9650[i][0] == SENSOR)
313 err = m5602_write_sensor(sd, init_ov9650[i][1],
314 &data, 1);
315 else
316 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
317 }
318
319 err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
320 if (err < 0)
321 return err;
322
323 err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
324 if (err < 0)
325 return err;
326
327 err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]);
328 if (err < 0)
329 return err;
330
331 err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]);
332 if (err < 0)
333 return err;
334
335 err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
336 if (err < 0)
337 return err;
338
339 err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
340 if (err < 0)
341 return err;
342
343 err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]);
344 if (err < 0)
345 return err;
346
347 err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]);
348 return err;
349 }
350
351 int ov9650_start(struct sd *sd)
352 {
353 u8 data;
354 int i, err = 0;
355 struct cam *cam = &sd->gspca_dev.cam;
356 s32 *sensor_settings = sd->sensor_priv;
357
358 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
359 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
360 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
361 int hor_offs = OV9650_LEFT_OFFSET;
362
363 if (sensor_settings[VFLIP_IDX])
364 ver_offs--;
365
366 if (width <= 320)
367 hor_offs /= 2;
368
369 /* Synthesize the vsync/hsync setup */
370 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
371 if (res_init_ov9650[i][0] == BRIDGE)
372 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
373 res_init_ov9650[i][2]);
374 else if (res_init_ov9650[i][0] == SENSOR) {
375 u8 data = res_init_ov9650[i][2];
376 err = m5602_write_sensor(sd,
377 res_init_ov9650[i][1], &data, 1);
378 }
379 }
380 if (err < 0)
381 return err;
382
383 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
384 ((ver_offs >> 8) & 0xff));
385 if (err < 0)
386 return err;
387
388 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
389 if (err < 0)
390 return err;
391
392 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
393 if (err < 0)
394 return err;
395
396 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
397 if (err < 0)
398 return err;
399
400 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
401 if (err < 0)
402 return err;
403
404 for (i = 0; i < 2 && !err; i++)
405 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
406 if (err < 0)
407 return err;
408
409 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
410 (hor_offs >> 8) & 0xff);
411 if (err < 0)
412 return err;
413
414 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
415 if (err < 0)
416 return err;
417
418 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
419 ((width + hor_offs) >> 8) & 0xff);
420 if (err < 0)
421 return err;
422
423 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
424 ((width + hor_offs) & 0xff));
425 if (err < 0)
426 return err;
427
428 switch (width) {
429 case 640:
430 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
431
432 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
433 OV9650_RAW_RGB_SELECT;
434 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
435 break;
436
437 case 352:
438 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
439
440 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
441 OV9650_RAW_RGB_SELECT;
442 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
443 break;
444
445 case 320:
446 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
447
448 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
449 OV9650_RAW_RGB_SELECT;
450 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
451 break;
452
453 case 176:
454 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
455
456 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
457 OV9650_RAW_RGB_SELECT;
458 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
459 break;
460 }
461 return err;
462 }
463
464 int ov9650_stop(struct sd *sd)
465 {
466 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
467 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
468 }
469
470 int ov9650_power_down(struct sd *sd)
471 {
472 int i, err = 0;
473 for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
474 u8 data = power_down_ov9650[i][2];
475 if (power_down_ov9650[i][0] == SENSOR)
476 err = m5602_write_sensor(sd,
477 power_down_ov9650[i][1], &data, 1);
478 else
479 err = m5602_write_bridge(sd, power_down_ov9650[i][1],
480 data);
481 }
482
483 return err;
484 }
485
486 void ov9650_disconnect(struct sd *sd)
487 {
488 ov9650_stop(sd);
489 ov9650_power_down(sd);
490
491 sd->sensor = NULL;
492 kfree(sd->sensor_priv);
493 }
494
495 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
496 {
497 struct sd *sd = (struct sd *) gspca_dev;
498 s32 *sensor_settings = sd->sensor_priv;
499
500 *val = sensor_settings[EXPOSURE_IDX];
501 PDEBUG(D_V4L2, "Read exposure %d", *val);
502 return 0;
503 }
504
505 int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
506 {
507 struct sd *sd = (struct sd *) gspca_dev;
508 s32 *sensor_settings = sd->sensor_priv;
509 u8 i2c_data;
510 int err;
511
512 PDEBUG(D_V4L2, "Set exposure to %d", val);
513
514 sensor_settings[EXPOSURE_IDX] = val;
515 /* The 6 MSBs */
516 i2c_data = (val >> 10) & 0x3f;
517 err = m5602_write_sensor(sd, OV9650_AECHM,
518 &i2c_data, 1);
519 if (err < 0)
520 return err;
521
522 /* The 8 middle bits */
523 i2c_data = (val >> 2) & 0xff;
524 err = m5602_write_sensor(sd, OV9650_AECH,
525 &i2c_data, 1);
526 if (err < 0)
527 return err;
528
529 /* The 2 LSBs */
530 i2c_data = val & 0x03;
531 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
532 return err;
533 }
534
535 int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
536 {
537 struct sd *sd = (struct sd *) gspca_dev;
538 s32 *sensor_settings = sd->sensor_priv;
539
540 *val = sensor_settings[GAIN_IDX];
541 PDEBUG(D_V4L2, "Read gain %d", *val);
542 return 0;
543 }
544
545 int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
546 {
547 int err;
548 u8 i2c_data;
549 struct sd *sd = (struct sd *) gspca_dev;
550 s32 *sensor_settings = sd->sensor_priv;
551
552 PDEBUG(D_V4L2, "Setting gain to %d", val);
553
554 sensor_settings[GAIN_IDX] = val;
555
556 /* The 2 MSB */
557 /* Read the OV9650_VREF register first to avoid
558 corrupting the VREF high and low bits */
559 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
560 if (err < 0)
561 return err;
562
563 /* Mask away all uninteresting bits */
564 i2c_data = ((val & 0x0300) >> 2) |
565 (i2c_data & 0x3F);
566 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
567 if (err < 0)
568 return err;
569
570 /* The 8 LSBs */
571 i2c_data = val & 0xff;
572 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
573 return err;
574 }
575
576 int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
577 {
578 struct sd *sd = (struct sd *) gspca_dev;
579 s32 *sensor_settings = sd->sensor_priv;
580
581 *val = sensor_settings[RED_BALANCE_IDX];
582 PDEBUG(D_V4L2, "Read red gain %d", *val);
583 return 0;
584 }
585
586 int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
587 {
588 int err;
589 u8 i2c_data;
590 struct sd *sd = (struct sd *) gspca_dev;
591 s32 *sensor_settings = sd->sensor_priv;
592
593 PDEBUG(D_V4L2, "Set red gain to %d", val);
594
595 sensor_settings[RED_BALANCE_IDX] = val;
596
597 i2c_data = val & 0xff;
598 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
599 return err;
600 }
601
602 int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
603 {
604 struct sd *sd = (struct sd *) gspca_dev;
605 s32 *sensor_settings = sd->sensor_priv;
606
607 *val = sensor_settings[BLUE_BALANCE_IDX];
608 PDEBUG(D_V4L2, "Read blue gain %d", *val);
609
610 return 0;
611 }
612
613 int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
614 {
615 int err;
616 u8 i2c_data;
617 struct sd *sd = (struct sd *) gspca_dev;
618 s32 *sensor_settings = sd->sensor_priv;
619
620 PDEBUG(D_V4L2, "Set blue gain to %d", val);
621
622 sensor_settings[BLUE_BALANCE_IDX] = val;
623
624 i2c_data = val & 0xff;
625 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
626 return err;
627 }
628
629 int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
630 {
631 struct sd *sd = (struct sd *) gspca_dev;
632 s32 *sensor_settings = sd->sensor_priv;
633
634 *val = sensor_settings[HFLIP_IDX];
635 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
636 return 0;
637 }
638
639 int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
640 {
641 int err;
642 u8 i2c_data;
643 struct sd *sd = (struct sd *) gspca_dev;
644 s32 *sensor_settings = sd->sensor_priv;
645
646 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
647
648 sensor_settings[HFLIP_IDX] = val;
649 i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4);
650 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
651
652 return err;
653 }
654
655 int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
656 {
657 struct sd *sd = (struct sd *) gspca_dev;
658 s32 *sensor_settings = sd->sensor_priv;
659
660 *val = sensor_settings[VFLIP_IDX];
661 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
662
663 return 0;
664 }
665
666 int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
667 {
668 int err;
669 u8 i2c_data;
670 struct sd *sd = (struct sd *) gspca_dev;
671 s32 *sensor_settings = sd->sensor_priv;
672
673 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
674 sensor_settings[VFLIP_IDX] = val;
675
676 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
677 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
678 if (err < 0)
679 return err;
680
681 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
682 if (gspca_dev->streaming)
683 err = ov9650_start(sd);
684
685 return err;
686 }
687
688 int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
689 {
690 struct sd *sd = (struct sd *) gspca_dev;
691 s32 *sensor_settings = sd->sensor_priv;
692
693 *val = sensor_settings[GAIN_IDX];
694 PDEBUG(D_V4L2, "Read gain %d", *val);
695
696 return 0;
697 }
698
699 int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
700 {
701 int err;
702 u8 i2c_data;
703 struct sd *sd = (struct sd *) gspca_dev;
704 s32 *sensor_settings = sd->sensor_priv;
705
706 PDEBUG(D_V4L2, "Set gain to %d", val);
707
708 sensor_settings[GAIN_IDX] = val;
709
710 /* Read the OV9650_VREF register first to avoid
711 corrupting the VREF high and low bits */
712 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
713 if (err < 0)
714 return err;
715
716 /* Mask away all uninteresting bits */
717 i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
718 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
719 if (err < 0)
720 return err;
721
722 /* The 8 LSBs */
723 i2c_data = val & 0xff;
724 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
725
726 return err;
727 }
728
729 int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
730 {
731 struct sd *sd = (struct sd *) gspca_dev;
732 s32 *sensor_settings = sd->sensor_priv;
733
734 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
735 return 0;
736 }
737
738 int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
739 {
740 int err;
741 u8 i2c_data;
742 struct sd *sd = (struct sd *) gspca_dev;
743 s32 *sensor_settings = sd->sensor_priv;
744
745 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
746
747 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
748 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
749 if (err < 0)
750 return err;
751
752 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
753 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
754
755 return err;
756 }
757
758 int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
759 {
760 struct sd *sd = (struct sd *) gspca_dev;
761 s32 *sensor_settings = sd->sensor_priv;
762
763 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
764 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
765 return 0;
766 }
767
768 int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
769 {
770 int err;
771 u8 i2c_data;
772 struct sd *sd = (struct sd *) gspca_dev;
773 s32 *sensor_settings = sd->sensor_priv;
774
775 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
776
777 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
778 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
779 if (err < 0)
780 return err;
781
782 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
783 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
784
785 return err;
786 }
787
788 static void ov9650_dump_registers(struct sd *sd)
789 {
790 int address;
791 info("Dumping the ov9650 register state");
792 for (address = 0; address < 0xa9; address++) {
793 u8 value;
794 m5602_read_sensor(sd, address, &value, 1);
795 info("register 0x%x contains 0x%x",
796 address, value);
797 }
798
799 info("ov9650 register state dump complete");
800
801 info("Probing for which registers that are read/write");
802 for (address = 0; address < 0xff; address++) {
803 u8 old_value, ctrl_value;
804 u8 test_value[2] = {0xff, 0xff};
805
806 m5602_read_sensor(sd, address, &old_value, 1);
807 m5602_write_sensor(sd, address, test_value, 1);
808 m5602_read_sensor(sd, address, &ctrl_value, 1);
809
810 if (ctrl_value == test_value[0])
811 info("register 0x%x is writeable", address);
812 else
813 info("register 0x%x is read only", address);
814
815 /* Restore original value */
816 m5602_write_sensor(sd, address, &old_value, 1);
817 }
818 }