Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[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 #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 }