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