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