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