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