V4L/DVB (11426): gspca - m5602: Don't touch hflip/vflip register on Read/Modify/Write
[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 #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
349         return err;
350 }
351
352 int ov9650_start(struct sd *sd)
353 {
354         u8 data;
355         int i, err = 0;
356         struct cam *cam = &sd->gspca_dev.cam;
357         s32 *sensor_settings = sd->sensor_priv;
358
359         int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
360         int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
361         int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
362         int hor_offs = OV9650_LEFT_OFFSET;
363
364         if (sensor_settings[VFLIP_IDX])
365                 ver_offs--;
366
367         if (width <= 320)
368                 hor_offs /= 2;
369
370         if (err < 0)
371                 return err;
372
373         /* Synthesize the vsync/hsync setup */
374         for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
375                 if (res_init_ov9650[i][0] == BRIDGE)
376                         err = m5602_write_bridge(sd, res_init_ov9650[i][1],
377                                 res_init_ov9650[i][2]);
378                 else if (res_init_ov9650[i][0] == SENSOR) {
379                         u8 data = res_init_ov9650[i][2];
380                         err = m5602_write_sensor(sd,
381                                 res_init_ov9650[i][1], &data, 1);
382                 }
383         }
384         if (err < 0)
385                 return err;
386
387         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
388                                  ((ver_offs >> 8) & 0xff));
389         if (err < 0)
390                 return err;
391
392         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
393         if (err < 0)
394                 return err;
395
396         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
397         if (err < 0)
398                 return err;
399
400         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
401         if (err < 0)
402                 return err;
403
404         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
405         if (err < 0)
406                 return err;
407
408         for (i = 0; i < 2 && !err; i++)
409                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
410         if (err < 0)
411                 return err;
412
413         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
414                                  (hor_offs >> 8) & 0xff);
415         if (err < 0)
416                 return err;
417
418         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
419         if (err < 0)
420                 return err;
421
422         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
423                                  ((width + hor_offs) >> 8) & 0xff);
424         if (err < 0)
425                 return err;
426
427         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
428                                  ((width + hor_offs) & 0xff));
429         if (err < 0)
430                 return err;
431
432         switch (width) {
433         case 640:
434                 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
435
436                 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
437                        OV9650_RAW_RGB_SELECT;
438
439                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
440
441                 break;
442
443         case 352:
444                 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
445
446                 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
447                                 OV9650_RAW_RGB_SELECT;
448
449                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
450
451                 break;
452
453         case 320:
454                 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
455
456                 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
457                                 OV9650_RAW_RGB_SELECT;
458
459                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
460
461                 break;
462
463         case 176:
464                 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
465
466                 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
467                         OV9650_RAW_RGB_SELECT;
468
469                 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
470                 break;
471         }
472         return err;
473 }
474
475 int ov9650_stop(struct sd *sd)
476 {
477         u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
478         return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
479 }
480
481 int ov9650_power_down(struct sd *sd)
482 {
483         int i, err = 0;
484         for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
485                 u8 data = power_down_ov9650[i][2];
486                 if (power_down_ov9650[i][0] == SENSOR)
487                         err = m5602_write_sensor(sd,
488                                             power_down_ov9650[i][1], &data, 1);
489                 else
490                         err = m5602_write_bridge(sd, power_down_ov9650[i][1],
491                                                  data);
492         }
493
494         return err;
495 }
496
497 void ov9650_disconnect(struct sd *sd)
498 {
499         ov9650_stop(sd);
500         ov9650_power_down(sd);
501
502         sd->sensor = NULL;
503
504         kfree(sd->sensor_priv);
505 }
506
507 int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
508 {
509         struct sd *sd = (struct sd *) gspca_dev;
510         s32 *sensor_settings = sd->sensor_priv;
511
512         *val = sensor_settings[EXPOSURE_IDX];
513         PDEBUG(D_V4L2, "Read exposure %d", *val);
514         return 0;
515 }
516
517 int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
518 {
519         struct sd *sd = (struct sd *) gspca_dev;
520         s32 *sensor_settings = sd->sensor_priv;
521         u8 i2c_data;
522         int err;
523
524         PDEBUG(D_V4L2, "Set exposure to %d", val);
525
526         sensor_settings[EXPOSURE_IDX] = val;
527
528         /* The 6 MSBs */
529         i2c_data = (val >> 10) & 0x3f;
530         err = m5602_write_sensor(sd, OV9650_AECHM,
531                                   &i2c_data, 1);
532         if (err < 0)
533                 return err;
534
535         /* The 8 middle bits */
536         i2c_data = (val >> 2) & 0xff;
537         err = m5602_write_sensor(sd, OV9650_AECH,
538                                   &i2c_data, 1);
539         if (err < 0)
540                 return err;
541
542         /* The 2 LSBs */
543         i2c_data = val & 0x03;
544         err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
545
546         return err;
547 }
548
549 int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
550 {
551         struct sd *sd = (struct sd *) gspca_dev;
552         s32 *sensor_settings = sd->sensor_priv;
553
554         *val = sensor_settings[GAIN_IDX];
555         PDEBUG(D_V4L2, "Read gain %d", *val);
556         return 0;
557 }
558
559 int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
560 {
561         int err;
562         u8 i2c_data;
563         struct sd *sd = (struct sd *) gspca_dev;
564         s32 *sensor_settings = sd->sensor_priv;
565
566         PDEBUG(D_V4L2, "Setting gain to %d", val);
567
568         sensor_settings[GAIN_IDX] = val;
569
570         /* The 2 MSB */
571         /* Read the OV9650_VREF register first to avoid
572            corrupting the VREF high and low bits */
573         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
574         if (err < 0)
575                 return err;
576
577         /* Mask away all uninteresting bits */
578         i2c_data = ((val & 0x0300) >> 2) |
579                         (i2c_data & 0x3F);
580         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
581         if (err < 0)
582                 return err;
583
584         /* The 8 LSBs */
585         i2c_data = val & 0xff;
586         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
587         return err;
588 }
589
590 int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
591 {
592         struct sd *sd = (struct sd *) gspca_dev;
593         s32 *sensor_settings = sd->sensor_priv;
594
595         *val = sensor_settings[RED_BALANCE_IDX];
596         PDEBUG(D_V4L2, "Read red gain %d", *val);
597         return 0;
598 }
599
600 int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
601 {
602         int err;
603         u8 i2c_data;
604         struct sd *sd = (struct sd *) gspca_dev;
605         s32 *sensor_settings = sd->sensor_priv;
606
607         PDEBUG(D_V4L2, "Set red gain to %d", val);
608
609         sensor_settings[RED_BALANCE_IDX] = val;
610
611         i2c_data = val & 0xff;
612         err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
613
614         return err;
615 }
616
617 int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
618 {
619         struct sd *sd = (struct sd *) gspca_dev;
620         s32 *sensor_settings = sd->sensor_priv;
621
622         *val = sensor_settings[BLUE_BALANCE_IDX];
623         PDEBUG(D_V4L2, "Read blue gain %d", *val);
624
625         return 0;
626 }
627
628 int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
629 {
630         int err;
631         u8 i2c_data;
632         struct sd *sd = (struct sd *) gspca_dev;
633         s32 *sensor_settings = sd->sensor_priv;
634
635         PDEBUG(D_V4L2, "Set blue gain to %d", val);
636
637         sensor_settings[BLUE_BALANCE_IDX] = val;
638
639         i2c_data = val & 0xff;
640         err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
641
642         return err;
643 }
644
645 int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
646 {
647         struct sd *sd = (struct sd *) gspca_dev;
648         s32 *sensor_settings = sd->sensor_priv;
649         *val = sensor_settings[HFLIP_IDX];
650         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
651
652         return 0;
653 }
654
655 int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
656 {
657         int err;
658         u8 i2c_data;
659         struct sd *sd = (struct sd *) gspca_dev;
660         s32 *sensor_settings = sd->sensor_priv;
661
662         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
663
664         sensor_settings[HFLIP_IDX] = val;
665         i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4);
666         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
667
668         return err;
669 }
670
671 int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
672 {
673         struct sd *sd = (struct sd *) gspca_dev;
674         s32 *sensor_settings = sd->sensor_priv;
675
676         *val = sensor_settings[VFLIP_IDX];
677         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
678
679         return 0;
680 }
681
682 int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
683 {
684         int err;
685         u8 i2c_data;
686         struct sd *sd = (struct sd *) gspca_dev;
687         s32 *sensor_settings = sd->sensor_priv;
688
689         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
690         sensor_settings[VFLIP_IDX] = val;
691
692         i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
693         err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
694         if (err < 0)
695                 return err;
696
697         /* When vflip is toggled we need to readjust the bridge hsync/vsync */
698         if (gspca_dev->streaming)
699                 err = ov9650_start(sd);
700
701         return err;
702 }
703
704 int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
705 {
706         struct sd *sd = (struct sd *) gspca_dev;
707         s32 *sensor_settings = sd->sensor_priv;
708
709         *val = sensor_settings[GAIN_IDX];
710         PDEBUG(D_V4L2, "Read gain %d", *val);
711
712         return 0;
713 }
714
715 int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
716 {
717         int err;
718         u8 i2c_data;
719         struct sd *sd = (struct sd *) gspca_dev;
720         s32 *sensor_settings = sd->sensor_priv;
721
722         PDEBUG(D_V4L2, "Set gain to %d", val);
723
724         sensor_settings[GAIN_IDX] = val;
725
726         /* Read the OV9650_VREF register first to avoid
727                 corrupting the VREF high and low bits */
728         err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
729         if (err < 0)
730                 return err;
731
732         /* Mask away all uninteresting bits */
733         i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
734         err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
735         if (err < 0)
736                 return err;
737
738         /* The 8 LSBs */
739         i2c_data = val & 0xff;
740         err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
741
742         return err;
743 }
744
745 int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
746 {
747         struct sd *sd = (struct sd *) gspca_dev;
748         s32 *sensor_settings = sd->sensor_priv;
749
750         *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
751         return 0;
752 }
753
754 int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
755 {
756         int err;
757         u8 i2c_data;
758         struct sd *sd = (struct sd *) gspca_dev;
759         s32 *sensor_settings = sd->sensor_priv;
760
761         PDEBUG(D_V4L2, "Set auto white balance to %d", val);
762
763         sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
764         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
765         if (err < 0)
766                 return err;
767
768         i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
769         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
770
771         return err;
772 }
773
774 int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
775 {
776         struct sd *sd = (struct sd *) gspca_dev;
777         s32 *sensor_settings = sd->sensor_priv;
778
779         *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
780         PDEBUG(D_V4L2, "Read auto gain control %d", *val);
781         return 0;
782 }
783
784 int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
785 {
786         int err;
787         u8 i2c_data;
788         struct sd *sd = (struct sd *) gspca_dev;
789         s32 *sensor_settings = sd->sensor_priv;
790
791         PDEBUG(D_V4L2, "Set auto gain control to %d", val);
792
793         sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
794         err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
795         if (err < 0)
796                 return err;
797
798         i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
799         err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
800
801         return err;
802 }
803
804 static void ov9650_dump_registers(struct sd *sd)
805 {
806         int address;
807         info("Dumping the ov9650 register state");
808         for (address = 0; address < 0xa9; address++) {
809                 u8 value;
810                 m5602_read_sensor(sd, address, &value, 1);
811                 info("register 0x%x contains 0x%x",
812                      address, value);
813         }
814
815         info("ov9650 register state dump complete");
816
817         info("Probing for which registers that are read/write");
818         for (address = 0; address < 0xff; address++) {
819                 u8 old_value, ctrl_value;
820                 u8 test_value[2] = {0xff, 0xff};
821
822                 m5602_read_sensor(sd, address, &old_value, 1);
823                 m5602_write_sensor(sd, address, test_value, 1);
824                 m5602_read_sensor(sd, address, &ctrl_value, 1);
825
826                 if (ctrl_value == test_value[0])
827                         info("register 0x%x is writeable", address);
828                 else
829                         info("register 0x%x is read only", address);
830
831                 /* Restore original value */
832                 m5602_write_sensor(sd, address, &old_value, 1);
833         }
834 }