15288a114fe27cd33c2c75ff2d6f8e24ea6d75d0
[safe/jmp/linux-2.6] / 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        = 0x1ff,
79                         .step           = 0x4,
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  = 1
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  = 1
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 = 9
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 = 8
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 = 9
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 = 9
214         }
215 };
216
217 static void ov9650_dump_registers(struct sd *sd);
218
219 int ov9650_probe(struct sd *sd)
220 {
221         int err = 0;
222         u8 prod_id = 0, ver_id = 0, i;
223
224         if (force_sensor) {
225                 if (force_sensor == OV9650_SENSOR) {
226                         info("Forcing an %s sensor", ov9650.name);
227                         goto sensor_found;
228                 }
229                 /* If we want to force another sensor,
230                    don't try to probe this one */
231                 return -ENODEV;
232         }
233
234         info("Probing for an ov9650 sensor");
235
236         /* Run the pre-init to actually probe the unit */
237         for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
238                 u8 data = preinit_ov9650[i][2];
239                 if (preinit_ov9650[i][0] == SENSOR)
240                         err = m5602_write_sensor(sd,
241                                             preinit_ov9650[i][1], &data, 1);
242                 else
243                         err = m5602_write_bridge(sd, preinit_ov9650[i][1], data);
244         }
245
246         if (err < 0)
247                 return err;
248
249         if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
250                 return -ENODEV;
251
252         if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
253                 return -ENODEV;
254
255         if ((prod_id == 0x96) && (ver_id == 0x52)) {
256                 info("Detected an ov9650 sensor");
257                 goto sensor_found;
258         }
259
260         return -ENODEV;
261
262 sensor_found:
263         sd->gspca_dev.cam.cam_mode = ov9650_modes;
264         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
265         sd->desc->ctrls = ov9650_ctrls;
266         sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
267         return 0;
268 }
269
270 int ov9650_init(struct sd *sd)
271 {
272         int i, err = 0;
273         u8 data;
274
275         if (dump_sensor)
276                 ov9650_dump_registers(sd);
277
278         for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
279                 data = init_ov9650[i][2];
280                 if (init_ov9650[i][0] == SENSOR)
281                         err = m5602_write_sensor(sd, init_ov9650[i][1],
282                                                   &data, 1);
283                 else
284                         err = m5602_write_bridge(sd, init_ov9650[i][1], data);
285         }
286
287         if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
288                 info("vflip quirk active");
289                 data = 0x30;
290                 err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1);
291         }
292
293         return err;
294 }
295
296 int ov9650_start(struct sd *sd)
297 {
298         u8 data;
299         int i, err = 0;
300         struct cam *cam = &sd->gspca_dev.cam;
301         int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
302         int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
303         int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
304         int hor_offs = OV9650_LEFT_OFFSET;
305
306         if (width <= 320)
307                 hor_offs /= 2;
308
309         err = ov9650_init(sd);
310         if (err < 0)
311                 return err;
312
313         /* Synthesize the vsync/hsync setup */
314         for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
315                 if (res_init_ov9650[i][0] == BRIDGE)
316                         err = m5602_write_bridge(sd, res_init_ov9650[i][1],
317                                 res_init_ov9650[i][2]);
318                 else if (res_init_ov9650[i][0] == SENSOR) {
319                         u8 data = res_init_ov9650[i][2];
320                         err = m5602_write_sensor(sd,
321                                 res_init_ov9650[i][1], &data, 1);
322                 }
323         }
324         if (err < 0)
325                 return err;
326
327         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff));
328         if (err < 0)
329                 return err;
330
331         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
332         if (err < 0)
333                 return err;
334
335         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
336         if (err < 0)
337                 return err;
338
339         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
340         if (err < 0)
341                 return err;
342
343         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
344         if (err < 0)
345                 return err;
346
347         for (i = 0; i < 2 && !err; i++) {
348                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
349         }
350         if (err < 0)
351                 return err;
352
353         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff);
354         if (err < 0)
355                 return err;
356
357         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
358         if (err < 0)
359                 return err;
360
361         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff);
362         if (err < 0)
363                 return err;
364
365         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff));
366         if (err < 0)
367                 return err;
368
369         switch (width) {
370         case 640:
371                 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
372
373                 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
374                        OV9650_RAW_RGB_SELECT;
375
376                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
377
378                 break;
379
380         case 352:
381                 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
382
383                 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
384                                 OV9650_RAW_RGB_SELECT;
385
386                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
387
388                 break;
389
390         case 320:
391                 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
392
393                 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
394                                 OV9650_RAW_RGB_SELECT;
395
396                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
397
398                 break;
399
400         case 176:
401                 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
402
403                 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
404                         OV9650_RAW_RGB_SELECT;
405
406                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
407                 break;
408         }
409         return err;
410 }
411
412 int ov9650_stop(struct sd *sd)
413 {
414         u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
415         return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
416 }
417
418 int ov9650_power_down(struct sd *sd)
419 {
420         int i, err = 0;
421         for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
422                 u8 data = power_down_ov9650[i][2];
423                 if (power_down_ov9650[i][0] == SENSOR)
424                         err = m5602_write_sensor(sd,
425                                             power_down_ov9650[i][1], &data, 1);
426                 else
427                         err = m5602_write_bridge(sd, power_down_ov9650[i][1],
428                                                  data);
429         }
430
431         return err;
432 }
433
434 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
435 {
436         struct sd *sd = (struct sd *) gspca_dev;
437         u8 i2c_data;
438         int err;
439
440         err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
441         if (err < 0)
442                 return err;
443         *val |= (i2c_data << 2);
444
445         err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
446         if (err < 0)
447                 return err;
448         *val |= (i2c_data & 0x3f) << 10;
449
450         PDEBUG(D_V4L2, "Read exposure %d", *val);
451
452         return err;
453 }
454
455 int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
456 {
457         struct sd *sd = (struct sd *) gspca_dev;
458         u8 i2c_data;
459         int err;
460
461         PDEBUG(D_V4L2, "Set exposure to %d",
462                val & 0xffff);
463
464         /* The 6 MSBs */
465         i2c_data = (val >> 10) & 0x3f;
466         err = m5602_write_sensor(sd, OV9650_AECHM,
467                                   &i2c_data, 1);
468         if (err < 0)
469                 return err;
470
471         /* The 8 middle bits */
472         i2c_data = (val >> 2) & 0xff;
473         err = m5602_write_sensor(sd, OV9650_AECH,
474                                   &i2c_data, 1);
475         if (err < 0)
476                 return err;
477
478         /* The 2 LSBs */
479         i2c_data = val & 0x03;
480         err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
481
482         return err;
483 }
484
485 int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
486 {
487         int err;
488         u8 i2c_data;
489         struct sd *sd = (struct sd *) gspca_dev;
490
491         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
492         if (err < 0)
493                 return err;
494
495         *val = (i2c_data & 0x03) << 8;
496
497         err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
498         *val |= i2c_data;
499         PDEBUG(D_V4L2, "Read gain %d", *val);
500         return err;
501 }
502
503 int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
504 {
505         int err;
506         u8 i2c_data;
507         struct sd *sd = (struct sd *) gspca_dev;
508
509         /* The 2 MSB */
510         /* Read the OV9650_VREF register first to avoid
511            corrupting the VREF high and low bits */
512         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
513         if (err < 0)
514                 return err;
515
516         /* Mask away all uninteresting bits */
517         i2c_data = ((val & 0x0300) >> 2) |
518                         (i2c_data & 0x3F);
519         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
520         if (err < 0)
521                 return err;
522
523         /* The 8 LSBs */
524         i2c_data = val & 0xff;
525         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
526         return err;
527 }
528
529 int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
530 {
531         int err;
532         u8 i2c_data;
533         struct sd *sd = (struct sd *) gspca_dev;
534
535         err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1);
536         *val = i2c_data;
537
538         PDEBUG(D_V4L2, "Read red gain %d", *val);
539
540         return err;
541 }
542
543 int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
544 {
545         int err;
546         u8 i2c_data;
547         struct sd *sd = (struct sd *) gspca_dev;
548
549         PDEBUG(D_V4L2, "Set red gain to %d",
550                              val & 0xff);
551
552         i2c_data = val & 0xff;
553         err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
554
555         return err;
556 }
557
558 int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
559 {
560         int err;
561         u8 i2c_data;
562         struct sd *sd = (struct sd *) gspca_dev;
563
564         err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
565         *val = i2c_data;
566
567         PDEBUG(D_V4L2, "Read blue gain %d", *val);
568
569         return err;
570 }
571
572 int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
573 {
574         int err;
575         u8 i2c_data;
576         struct sd *sd = (struct sd *) gspca_dev;
577
578         PDEBUG(D_V4L2, "Set blue gain to %d",
579                val & 0xff);
580
581         i2c_data = val & 0xff;
582         err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
583
584         return err;
585 }
586
587 int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
588 {
589         int err;
590         u8 i2c_data;
591         struct sd *sd = (struct sd *) gspca_dev;
592
593         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
594         if (dmi_check_system(ov9650_flip_dmi_table))
595                 *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
596         else
597                 *val = (i2c_data & OV9650_HFLIP) >> 5;
598         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
599
600         return err;
601 }
602
603 int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
604 {
605         int err;
606         u8 i2c_data;
607         struct sd *sd = (struct sd *) gspca_dev;
608
609         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
610         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
611         if (err < 0)
612                 return err;
613
614         if (dmi_check_system(ov9650_flip_dmi_table))
615                 i2c_data = ((i2c_data & 0xdf) |
616                            (((val ? 0 : 1) & 0x01) << 5));
617         else
618                 i2c_data = ((i2c_data & 0xdf) |
619                            ((val & 0x01) << 5));
620
621         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
622
623         return err;
624 }
625
626 int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
627 {
628         int err;
629         u8 i2c_data;
630         struct sd *sd = (struct sd *) gspca_dev;
631
632         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
633         if (dmi_check_system(ov9650_flip_dmi_table))
634                 *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
635         else
636                 *val = (i2c_data & 0x10) >> 4;
637         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
638
639         return err;
640 }
641
642 int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
643 {
644         int err;
645         u8 i2c_data;
646         struct sd *sd = (struct sd *) gspca_dev;
647
648         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
649         err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
650         if (err < 0)
651                 return err;
652
653         if (dmi_check_system(ov9650_flip_dmi_table))
654                 i2c_data = ((i2c_data & 0xef) |
655                                 (((val ? 0 : 1) & 0x01) << 4));
656         else
657                 i2c_data = ((i2c_data & 0xef) |
658                                 ((val & 0x01) << 4));
659
660         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
661
662         return err;
663 }
664
665 int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
666 {
667         int err;
668         u8 i2c_data;
669         struct sd *sd = (struct sd *) gspca_dev;
670
671         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
672         if (err < 0)
673                 return err;
674         *val = (i2c_data & 0x03) << 8;
675
676         err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
677         *val |= i2c_data;
678         PDEBUG(D_V4L2, "Read gain %d", *val);
679
680         return err;
681 }
682
683 int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
684 {
685         int err;
686         u8 i2c_data;
687         struct sd *sd = (struct sd *) gspca_dev;
688
689         PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff);
690
691         /* Read the OV9650_VREF register first to avoid
692                 corrupting the VREF high and low bits */
693         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
694         if (err < 0)
695                 return err;
696
697         /* Mask away all uninteresting bits */
698         i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
699         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
700         if (err < 0)
701                 return err;
702
703         /* The 8 LSBs */
704         i2c_data = val & 0xff;
705         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
706
707         return err;
708 }
709
710 int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
711 {
712         int err;
713         u8 i2c_data;
714         struct sd *sd = (struct sd *) gspca_dev;
715
716         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
717         *val = (i2c_data & OV9650_AWB_EN) >> 1;
718         PDEBUG(D_V4L2, "Read auto white balance %d", *val);
719
720         return err;
721 }
722
723 int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
724 {
725         int err;
726         u8 i2c_data;
727         struct sd *sd = (struct sd *) gspca_dev;
728
729         PDEBUG(D_V4L2, "Set auto white balance to %d", val);
730         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
731         if (err < 0)
732                 return err;
733
734         i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
735         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
736
737         return err;
738 }
739
740 int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
741 {
742         int err;
743         u8 i2c_data;
744         struct sd *sd = (struct sd *) gspca_dev;
745
746         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
747         *val = (i2c_data & OV9650_AGC_EN) >> 2;
748         PDEBUG(D_V4L2, "Read auto gain control %d", *val);
749
750         return err;
751 }
752
753 int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
754 {
755         int err;
756         u8 i2c_data;
757         struct sd *sd = (struct sd *) gspca_dev;
758
759         PDEBUG(D_V4L2, "Set auto gain control to %d", val);
760         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
761         if (err < 0)
762                 return err;
763
764         i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
765         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
766
767         return err;
768 }
769
770 static void ov9650_dump_registers(struct sd *sd)
771 {
772         int address;
773         info("Dumping the ov9650 register state");
774         for (address = 0; address < 0xa9; address++) {
775                 u8 value;
776                 m5602_read_sensor(sd, address, &value, 1);
777                 info("register 0x%x contains 0x%x",
778                      address, value);
779         }
780
781         info("ov9650 register state dump complete");
782
783         info("Probing for which registers that are read/write");
784         for (address = 0; address < 0xff; address++) {
785                 u8 old_value, ctrl_value;
786                 u8 test_value[2] = {0xff, 0xff};
787
788                 m5602_read_sensor(sd, address, &old_value, 1);
789                 m5602_write_sensor(sd, address, test_value, 1);
790                 m5602_read_sensor(sd, address, &ctrl_value, 1);
791
792                 if (ctrl_value == test_value[0])
793                         info("register 0x%x is writeable", address);
794                 else
795                         info("register 0x%x is read only", address);
796
797                 /* Restore original value */
798                 m5602_write_sensor(sd, address, &old_value, 1);
799         }
800 }