V4L/DVB (11414): gspca - m5602-mt9m111: Move v4l2 controls to main sensor file.
[pandora-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         {
73                 {
74                         .id             = V4L2_CID_EXPOSURE,
75                         .type           = V4L2_CTRL_TYPE_INTEGER,
76                         .name           = "exposure",
77                         .minimum        = 0x00,
78                         .maximum        = 0xffff,
79                         .step           = 0x1,
80                         .default_value  = EXPOSURE_DEFAULT,
81                         .flags          = V4L2_CTRL_FLAG_SLIDER
82                 },
83                 .set = ov9650_set_exposure,
84                 .get = ov9650_get_exposure
85         }, {
86                 {
87                         .id             = V4L2_CID_GAIN,
88                         .type           = V4L2_CTRL_TYPE_INTEGER,
89                         .name           = "gain",
90                         .minimum        = 0x00,
91                         .maximum        = 0x3ff,
92                         .step           = 0x1,
93                         .default_value  = GAIN_DEFAULT,
94                         .flags          = V4L2_CTRL_FLAG_SLIDER
95                 },
96                 .set = ov9650_set_gain,
97                 .get = ov9650_get_gain
98         }, {
99                 {
100                         .type           = V4L2_CTRL_TYPE_INTEGER,
101                         .name           = "red balance",
102                         .minimum        = 0x00,
103                         .maximum        = 0xff,
104                         .step           = 0x1,
105                         .default_value  = RED_GAIN_DEFAULT,
106                         .flags          = V4L2_CTRL_FLAG_SLIDER
107                 },
108                 .set = ov9650_set_red_balance,
109                 .get = ov9650_get_red_balance
110         }, {
111                 {
112                         .type           = V4L2_CTRL_TYPE_INTEGER,
113                         .name           = "blue balance",
114                         .minimum        = 0x00,
115                         .maximum        = 0xff,
116                         .step           = 0x1,
117                         .default_value  = BLUE_GAIN_DEFAULT,
118                         .flags          = V4L2_CTRL_FLAG_SLIDER
119                 },
120                 .set = ov9650_set_blue_balance,
121                 .get = ov9650_get_blue_balance
122         }, {
123                 {
124                         .id             = V4L2_CID_HFLIP,
125                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
126                         .name           = "horizontal flip",
127                         .minimum        = 0,
128                         .maximum        = 1,
129                         .step           = 1,
130                         .default_value  = 0
131                 },
132                 .set = ov9650_set_hflip,
133                 .get = ov9650_get_hflip
134         }, {
135                 {
136                         .id             = V4L2_CID_VFLIP,
137                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
138                         .name           = "vertical flip",
139                         .minimum        = 0,
140                         .maximum        = 1,
141                         .step           = 1,
142                         .default_value  = 0
143                 },
144                 .set = ov9650_set_vflip,
145                 .get = ov9650_get_vflip
146         }, {
147                 {
148                         .id             = V4L2_CID_AUTO_WHITE_BALANCE,
149                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
150                         .name           = "auto white balance",
151                         .minimum        = 0,
152                         .maximum        = 1,
153                         .step           = 1,
154                         .default_value  = 0
155                 },
156                 .set = ov9650_set_auto_white_balance,
157                 .get = ov9650_get_auto_white_balance
158         }, {
159                 {
160                         .id             = V4L2_CID_AUTOGAIN,
161                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
162                         .name           = "auto gain control",
163                         .minimum        = 0,
164                         .maximum        = 1,
165                         .step           = 1,
166                         .default_value  = 0
167                 },
168                 .set = ov9650_set_auto_gain,
169                 .get = ov9650_get_auto_gain
170         }
171 };
172
173 static struct v4l2_pix_format ov9650_modes[] = {
174         {
175                 176,
176                 144,
177                 V4L2_PIX_FMT_SBGGR8,
178                 V4L2_FIELD_NONE,
179                 .sizeimage =
180                         176 * 144,
181                 .bytesperline = 176,
182                 .colorspace = V4L2_COLORSPACE_SRGB,
183                 .priv = 0
184         }, {
185                 320,
186                 240,
187                 V4L2_PIX_FMT_SBGGR8,
188                 V4L2_FIELD_NONE,
189                 .sizeimage =
190                         320 * 240,
191                 .bytesperline = 320,
192                 .colorspace = V4L2_COLORSPACE_SRGB,
193                 .priv = 0
194         }, {
195                 352,
196                 288,
197                 V4L2_PIX_FMT_SBGGR8,
198                 V4L2_FIELD_NONE,
199                 .sizeimage =
200                         352 * 288,
201                 .bytesperline = 352,
202                 .colorspace = V4L2_COLORSPACE_SRGB,
203                 .priv = 0
204         }, {
205                 640,
206                 480,
207                 V4L2_PIX_FMT_SBGGR8,
208                 V4L2_FIELD_NONE,
209                 .sizeimage =
210                         640 * 480,
211                 .bytesperline = 640,
212                 .colorspace = V4L2_COLORSPACE_SRGB,
213                 .priv = 0
214         }
215 };
216
217 static void ov9650_dump_registers(struct sd *sd);
218
219 int ov9650_probe(struct sd *sd)
220 {
221         u8 prod_id = 0, ver_id = 0, i;
222
223         if (force_sensor) {
224                 if (force_sensor == OV9650_SENSOR) {
225                         info("Forcing an %s sensor", ov9650.name);
226                         goto sensor_found;
227                 }
228                 /* If we want to force another sensor,
229                    don't try to probe this one */
230                 return -ENODEV;
231         }
232
233         info("Probing for an ov9650 sensor");
234
235         /* Run the pre-init to actually probe the unit */
236         for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
237                 u8 data = preinit_ov9650[i][2];
238                 if (preinit_ov9650[i][0] == SENSOR)
239                         m5602_write_sensor(sd,
240                                             preinit_ov9650[i][1], &data, 1);
241                 else
242                         m5602_write_bridge(sd, preinit_ov9650[i][1], data);
243         }
244
245         if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
246                 return -ENODEV;
247
248         if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
249                 return -ENODEV;
250
251         if ((prod_id == 0x96) && (ver_id == 0x52)) {
252                 info("Detected an ov9650 sensor");
253                 goto sensor_found;
254         }
255
256         return -ENODEV;
257
258 sensor_found:
259         sd->gspca_dev.cam.cam_mode = ov9650_modes;
260         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
261         sd->desc->ctrls = ov9650_ctrls;
262         sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
263         return 0;
264 }
265
266 int ov9650_init(struct sd *sd)
267 {
268         int i, err = 0;
269         u8 data;
270
271         if (dump_sensor)
272                 ov9650_dump_registers(sd);
273
274         for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
275                 data = init_ov9650[i][2];
276                 if (init_ov9650[i][0] == SENSOR)
277                         err = m5602_write_sensor(sd, init_ov9650[i][1],
278                                                   &data, 1);
279                 else
280                         err = m5602_write_bridge(sd, init_ov9650[i][1], data);
281         }
282
283         if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
284                 info("vflip quirk active");
285                 data = 0x30;
286                 err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1);
287         }
288
289         return err;
290 }
291
292 int ov9650_start(struct sd *sd)
293 {
294         int i, err = 0;
295         struct cam *cam = &sd->gspca_dev.cam;
296
297         err = ov9650_init(sd);
298         if (err < 0)
299                 return err;
300
301         for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
302                 if (res_init_ov9650[i][0] == BRIDGE)
303                         err = m5602_write_bridge(sd, res_init_ov9650[i][1],
304                                 res_init_ov9650[i][2]);
305                 else if (res_init_ov9650[i][0] == SENSOR) {
306                         u8 data = res_init_ov9650[i][2];
307                         err = m5602_write_sensor(sd,
308                                 res_init_ov9650[i][1], &data, 1);
309                 }
310         }
311         if (err < 0)
312                 return err;
313
314         switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
315         case 640:
316                 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
317
318                 for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) {
319                         if (VGA_ov9650[i][0] == SENSOR) {
320                                 u8 data = VGA_ov9650[i][2];
321
322                                 err = m5602_write_sensor(sd,
323                                         VGA_ov9650[i][1], &data, 1);
324                         } else {
325                                 err = m5602_write_bridge(sd, VGA_ov9650[i][1],
326                                                 VGA_ov9650[i][2]);
327                         }
328                 }
329                 break;
330
331         case 352:
332                 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
333
334                 for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) {
335                         if (CIF_ov9650[i][0] == SENSOR) {
336                                 u8 data = CIF_ov9650[i][2];
337
338                                 err = m5602_write_sensor(sd,
339                                         CIF_ov9650[i][1], &data, 1);
340                         } else {
341                                 err = m5602_write_bridge(sd, CIF_ov9650[i][1],
342                                                 CIF_ov9650[i][2]);
343                         }
344                 }
345                 break;
346
347         case 320:
348                 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
349
350                 for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) {
351                         if (QVGA_ov9650[i][0] == SENSOR) {
352                                 u8 data = QVGA_ov9650[i][2];
353
354                                 err = m5602_write_sensor(sd,
355                                         QVGA_ov9650[i][1], &data, 1);
356                         } else {
357                                 err = m5602_write_bridge(sd, QVGA_ov9650[i][1],
358                                                 QVGA_ov9650[i][2]);
359                         }
360                 }
361                 break;
362
363         case 176:
364                 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
365
366                 for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) {
367                         if (QCIF_ov9650[i][0] == SENSOR) {
368                                 u8 data = QCIF_ov9650[i][2];
369                                 err = m5602_write_sensor(sd,
370                                         QCIF_ov9650[i][1], &data, 1);
371                         } else {
372                                 err = m5602_write_bridge(sd, QCIF_ov9650[i][1],
373                                                 QCIF_ov9650[i][2]);
374                         }
375                 }
376                 break;
377
378         }
379         return err;
380 }
381
382 int ov9650_stop(struct sd *sd)
383 {
384         u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
385         return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
386 }
387
388 int ov9650_power_down(struct sd *sd)
389 {
390         int i, err = 0;
391         for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
392                 u8 data = power_down_ov9650[i][2];
393                 if (power_down_ov9650[i][0] == SENSOR)
394                         err = m5602_write_sensor(sd,
395                                             power_down_ov9650[i][1], &data, 1);
396                 else
397                         err = m5602_write_bridge(sd, power_down_ov9650[i][1],
398                                                  data);
399         }
400
401         return err;
402 }
403
404 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
405 {
406         struct sd *sd = (struct sd *) gspca_dev;
407         u8 i2c_data;
408         int err;
409
410         err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
411         if (err < 0)
412                 return err;
413         *val = i2c_data & 0x03;
414
415         err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
416         if (err < 0)
417                 return err;
418         *val |= (i2c_data << 2);
419
420         err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
421         if (err < 0)
422                 return err;
423         *val |= (i2c_data & 0x3f) << 10;
424
425         PDEBUG(D_V4L2, "Read exposure %d", *val);
426
427         return err;
428 }
429
430 int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
431 {
432         struct sd *sd = (struct sd *) gspca_dev;
433         u8 i2c_data;
434         int err;
435
436         PDEBUG(D_V4L2, "Set exposure to %d",
437                val & 0xffff);
438
439         /* The 6 MSBs */
440         i2c_data = (val >> 10) & 0x3f;
441         err = m5602_write_sensor(sd, OV9650_AECHM,
442                                   &i2c_data, 1);
443         if (err < 0)
444                 return err;
445
446         /* The 8 middle bits */
447         i2c_data = (val >> 2) & 0xff;
448         err = m5602_write_sensor(sd, OV9650_AECH,
449                                   &i2c_data, 1);
450         if (err < 0)
451                 return err;
452
453         /* The 2 LSBs */
454         i2c_data = val & 0x03;
455         err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
456
457         return err;
458 }
459
460 int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
461 {
462         int err;
463         u8 i2c_data;
464         struct sd *sd = (struct sd *) gspca_dev;
465
466         m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
467         *val = (i2c_data & 0x03) << 8;
468
469         err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
470         *val |= i2c_data;
471         PDEBUG(D_V4L2, "Read gain %d", *val);
472         return err;
473 }
474
475 int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
476 {
477         int err;
478         u8 i2c_data;
479         struct sd *sd = (struct sd *) gspca_dev;
480
481         /* The 2 MSB */
482         /* Read the OV9650_VREF register first to avoid
483            corrupting the VREF high and low bits */
484         m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
485         /* Mask away all uninteresting bits */
486         i2c_data = ((val & 0x0300) >> 2) |
487                         (i2c_data & 0x3F);
488         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
489
490         /* The 8 LSBs */
491         i2c_data = val & 0xff;
492         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
493         return err;
494 }
495
496 int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
497 {
498         int err;
499         u8 i2c_data;
500         struct sd *sd = (struct sd *) gspca_dev;
501
502         err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1);
503         *val = i2c_data;
504
505         PDEBUG(D_V4L2, "Read red gain %d", *val);
506
507         return err;
508 }
509
510 int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
511 {
512         int err;
513         u8 i2c_data;
514         struct sd *sd = (struct sd *) gspca_dev;
515
516         PDEBUG(D_V4L2, "Set red gain to %d",
517                              val & 0xff);
518
519         i2c_data = val & 0xff;
520         err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
521
522         return err;
523 }
524
525 int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
526 {
527         int err;
528         u8 i2c_data;
529         struct sd *sd = (struct sd *) gspca_dev;
530
531         err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
532         *val = i2c_data;
533
534         PDEBUG(D_V4L2, "Read blue gain %d", *val);
535
536         return err;
537 }
538
539 int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
540 {
541         int err;
542         u8 i2c_data;
543         struct sd *sd = (struct sd *) gspca_dev;
544
545         PDEBUG(D_V4L2, "Set blue gain to %d",
546                val & 0xff);
547
548         i2c_data = val & 0xff;
549         err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
550
551         return err;
552 }
553
554 int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
555 {
556         int err;
557         u8 i2c_data;
558         struct sd *sd = (struct sd *) gspca_dev;
559
560         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
561         if (dmi_check_system(ov9650_flip_dmi_table))
562                 *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
563         else
564                 *val = (i2c_data & OV9650_HFLIP) >> 5;
565         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
566
567         return err;
568 }
569
570 int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
571 {
572         int err;
573         u8 i2c_data;
574         struct sd *sd = (struct sd *) gspca_dev;
575
576         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
577         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
578         if (err < 0)
579                 return err;
580
581         if (dmi_check_system(ov9650_flip_dmi_table))
582                 i2c_data = ((i2c_data & 0xdf) |
583                            (((val ? 0 : 1) & 0x01) << 5));
584         else
585                 i2c_data = ((i2c_data & 0xdf) |
586                            ((val & 0x01) << 5));
587
588         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
589
590         return err;
591 }
592
593 int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
594 {
595         int err;
596         u8 i2c_data;
597         struct sd *sd = (struct sd *) gspca_dev;
598
599         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
600         if (dmi_check_system(ov9650_flip_dmi_table))
601                 *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
602         else
603                 *val = (i2c_data & 0x10) >> 4;
604         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
605
606         return err;
607 }
608
609 int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
610 {
611         int err;
612         u8 i2c_data;
613         struct sd *sd = (struct sd *) gspca_dev;
614
615         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
616         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
617         if (err < 0)
618                 return err;
619
620         if (dmi_check_system(ov9650_flip_dmi_table))
621                 i2c_data = ((i2c_data & 0xef) |
622                                 (((val ? 0 : 1) & 0x01) << 4));
623         else
624                 i2c_data = ((i2c_data & 0xef) |
625                                 ((val & 0x01) << 4));
626
627         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
628
629         return err;
630 }
631
632 int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
633 {
634         int err;
635         u8 i2c_data;
636         struct sd *sd = (struct sd *) gspca_dev;
637
638         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
639         if (err < 0)
640                 return err;
641         *val = (i2c_data & 0x03) << 8;
642
643         err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
644         *val |= i2c_data;
645         PDEBUG(D_V4L2, "Read gain %d", *val);
646
647         return err;
648 }
649
650 int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
651 {
652         int err;
653         u8 i2c_data;
654         struct sd *sd = (struct sd *) gspca_dev;
655
656         PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff);
657
658         /* Read the OV9650_VREF register first to avoid
659                 corrupting the VREF high and low bits */
660         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
661         if (err < 0)
662                 return err;
663
664         /* Mask away all uninteresting bits */
665         i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
666         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
667         if (err < 0)
668                 return err;
669
670         /* The 8 LSBs */
671         i2c_data = val & 0xff;
672         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
673
674         return err;
675 }
676
677 int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
678 {
679         int err;
680         u8 i2c_data;
681         struct sd *sd = (struct sd *) gspca_dev;
682
683         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
684         *val = (i2c_data & OV9650_AWB_EN) >> 1;
685         PDEBUG(D_V4L2, "Read auto white balance %d", *val);
686
687         return err;
688 }
689
690 int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
691 {
692         int err;
693         u8 i2c_data;
694         struct sd *sd = (struct sd *) gspca_dev;
695
696         PDEBUG(D_V4L2, "Set auto white balance to %d", val);
697         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
698         if (err < 0)
699                 return err;
700
701         i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
702         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
703
704         return err;
705 }
706
707 int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
708 {
709         int err;
710         u8 i2c_data;
711         struct sd *sd = (struct sd *) gspca_dev;
712
713         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
714         *val = (i2c_data & OV9650_AGC_EN) >> 2;
715         PDEBUG(D_V4L2, "Read auto gain control %d", *val);
716
717         return err;
718 }
719
720 int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
721 {
722         int err;
723         u8 i2c_data;
724         struct sd *sd = (struct sd *) gspca_dev;
725
726         PDEBUG(D_V4L2, "Set auto gain control to %d", val);
727         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
728         if (err < 0)
729                 return err;
730
731         i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
732         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
733
734         return err;
735 }
736
737 static void ov9650_dump_registers(struct sd *sd)
738 {
739         int address;
740         info("Dumping the ov9650 register state");
741         for (address = 0; address < 0xa9; address++) {
742                 u8 value;
743                 m5602_read_sensor(sd, address, &value, 1);
744                 info("register 0x%x contains 0x%x",
745                      address, value);
746         }
747
748         info("ov9650 register state dump complete");
749
750         info("Probing for which registers that are read/write");
751         for (address = 0; address < 0xff; address++) {
752                 u8 old_value, ctrl_value;
753                 u8 test_value[2] = {0xff, 0xff};
754
755                 m5602_read_sensor(sd, address, &old_value, 1);
756                 m5602_write_sensor(sd, address, test_value, 1);
757                 m5602_read_sensor(sd, address, &ctrl_value, 1);
758
759                 if (ctrl_value == test_value[0])
760                         info("register 0x%x is writeable", address);
761                 else
762                         info("register 0x%x is read only", address);
763
764                 /* Restore original value */
765                 m5602_write_sensor(sd, address, &old_value, 1);
766         }
767 }