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