Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / drivers / media / usb / gspca / m5602 / m5602_po1030.c
1 /*
2  * Driver for the po1030 sensor
3  *
4  * Copyright (c) 2008 Erik AndrĂ©n
5  * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6  * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7  *
8  * Portions of code to USB interface and ALi driver software,
9  * Copyright (c) 2006 Willem Duinker
10  * v4l2 interface modeled after the V4L2 driver
11  * for SN9C10x PC Camera Controllers
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation, version 2.
16  *
17  */
18
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21 #include "m5602_po1030.h"
22
23 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
24 static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
25 static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26 static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27 static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
28 static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
29 static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
30 static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
31 static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
32 static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
33 static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34 static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35 static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36 static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37 static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
38                                          __s32 val);
39 static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
40                                          __s32 *val);
41 static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
42                                          __s32 val);
43 static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
44                                          __s32 *val);
45
46 static struct v4l2_pix_format po1030_modes[] = {
47         {
48                 640,
49                 480,
50                 V4L2_PIX_FMT_SBGGR8,
51                 V4L2_FIELD_NONE,
52                 .sizeimage = 640 * 480,
53                 .bytesperline = 640,
54                 .colorspace = V4L2_COLORSPACE_SRGB,
55                 .priv = 2
56         }
57 };
58
59 static const struct ctrl po1030_ctrls[] = {
60 #define GAIN_IDX 0
61         {
62                 {
63                         .id             = V4L2_CID_GAIN,
64                         .type           = V4L2_CTRL_TYPE_INTEGER,
65                         .name           = "gain",
66                         .minimum        = 0x00,
67                         .maximum        = 0x4f,
68                         .step           = 0x1,
69                         .default_value  = PO1030_GLOBAL_GAIN_DEFAULT,
70                         .flags          = V4L2_CTRL_FLAG_SLIDER
71                 },
72                 .set = po1030_set_gain,
73                 .get = po1030_get_gain
74         },
75 #define EXPOSURE_IDX 1
76         {
77                 {
78                         .id             = V4L2_CID_EXPOSURE,
79                         .type           = V4L2_CTRL_TYPE_INTEGER,
80                         .name           = "exposure",
81                         .minimum        = 0x00,
82                         .maximum        = 0x02ff,
83                         .step           = 0x1,
84                         .default_value  = PO1030_EXPOSURE_DEFAULT,
85                         .flags          = V4L2_CTRL_FLAG_SLIDER
86                 },
87                 .set = po1030_set_exposure,
88                 .get = po1030_get_exposure
89         },
90 #define RED_BALANCE_IDX 2
91         {
92                 {
93                         .id             = V4L2_CID_RED_BALANCE,
94                         .type           = V4L2_CTRL_TYPE_INTEGER,
95                         .name           = "red balance",
96                         .minimum        = 0x00,
97                         .maximum        = 0xff,
98                         .step           = 0x1,
99                         .default_value  = PO1030_RED_GAIN_DEFAULT,
100                         .flags          = V4L2_CTRL_FLAG_SLIDER
101                 },
102                 .set = po1030_set_red_balance,
103                 .get = po1030_get_red_balance
104         },
105 #define BLUE_BALANCE_IDX 3
106         {
107                 {
108                         .id             = V4L2_CID_BLUE_BALANCE,
109                         .type           = V4L2_CTRL_TYPE_INTEGER,
110                         .name           = "blue balance",
111                         .minimum        = 0x00,
112                         .maximum        = 0xff,
113                         .step           = 0x1,
114                         .default_value  = PO1030_BLUE_GAIN_DEFAULT,
115                         .flags          = V4L2_CTRL_FLAG_SLIDER
116                 },
117                 .set = po1030_set_blue_balance,
118                 .get = po1030_get_blue_balance
119         },
120 #define HFLIP_IDX 4
121         {
122                 {
123                         .id             = V4L2_CID_HFLIP,
124                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
125                         .name           = "horizontal flip",
126                         .minimum        = 0,
127                         .maximum        = 1,
128                         .step           = 1,
129                         .default_value  = 0,
130                 },
131                 .set = po1030_set_hflip,
132                 .get = po1030_get_hflip
133         },
134 #define VFLIP_IDX 5
135         {
136                 {
137                         .id             = V4L2_CID_VFLIP,
138                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
139                         .name           = "vertical flip",
140                         .minimum        = 0,
141                         .maximum        = 1,
142                         .step           = 1,
143                         .default_value  = 0,
144                 },
145                 .set = po1030_set_vflip,
146                 .get = po1030_get_vflip
147         },
148 #define AUTO_WHITE_BALANCE_IDX 6
149         {
150                 {
151                         .id             = V4L2_CID_AUTO_WHITE_BALANCE,
152                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
153                         .name           = "auto white balance",
154                         .minimum        = 0,
155                         .maximum        = 1,
156                         .step           = 1,
157                         .default_value  = 0,
158                 },
159                 .set = po1030_set_auto_white_balance,
160                 .get = po1030_get_auto_white_balance
161         },
162 #define AUTO_EXPOSURE_IDX 7
163         {
164                 {
165                         .id             = V4L2_CID_EXPOSURE_AUTO,
166                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
167                         .name           = "auto exposure",
168                         .minimum        = 0,
169                         .maximum        = 1,
170                         .step           = 1,
171                         .default_value  = 0,
172                 },
173                 .set = po1030_set_auto_exposure,
174                 .get = po1030_get_auto_exposure
175         },
176 #define GREEN_BALANCE_IDX 8
177         {
178                 {
179                         .id             = M5602_V4L2_CID_GREEN_BALANCE,
180                         .type           = V4L2_CTRL_TYPE_INTEGER,
181                         .name           = "green balance",
182                         .minimum        = 0x00,
183                         .maximum        = 0xff,
184                         .step           = 0x1,
185                         .default_value  = PO1030_GREEN_GAIN_DEFAULT,
186                         .flags          = V4L2_CTRL_FLAG_SLIDER
187                 },
188                 .set = po1030_set_green_balance,
189                 .get = po1030_get_green_balance
190         },
191 };
192
193 static void po1030_dump_registers(struct sd *sd);
194
195 int po1030_probe(struct sd *sd)
196 {
197         u8 dev_id_h = 0, i;
198         s32 *sensor_settings;
199
200         if (force_sensor) {
201                 if (force_sensor == PO1030_SENSOR) {
202                         pr_info("Forcing a %s sensor\n", po1030.name);
203                         goto sensor_found;
204                 }
205                 /* If we want to force another sensor, don't try to probe this
206                  * one */
207                 return -ENODEV;
208         }
209
210         PDEBUG(D_PROBE, "Probing for a po1030 sensor");
211
212         /* Run the pre-init to actually probe the unit */
213         for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
214                 u8 data = preinit_po1030[i][2];
215                 if (preinit_po1030[i][0] == SENSOR)
216                         m5602_write_sensor(sd,
217                                 preinit_po1030[i][1], &data, 1);
218                 else
219                         m5602_write_bridge(sd, preinit_po1030[i][1], data);
220         }
221
222         if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
223                 return -ENODEV;
224
225         if (dev_id_h == 0x30) {
226                 pr_info("Detected a po1030 sensor\n");
227                 goto sensor_found;
228         }
229         return -ENODEV;
230
231 sensor_found:
232         sensor_settings = kmalloc(
233                 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
234         if (!sensor_settings)
235                 return -ENOMEM;
236
237         sd->gspca_dev.cam.cam_mode = po1030_modes;
238         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
239         sd->desc->ctrls = po1030_ctrls;
240         sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
241
242         for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
243                 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
244         sd->sensor_priv = sensor_settings;
245
246         return 0;
247 }
248
249 int po1030_init(struct sd *sd)
250 {
251         s32 *sensor_settings = sd->sensor_priv;
252         int i, err = 0;
253
254         /* Init the sensor */
255         for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
256                 u8 data[2] = {0x00, 0x00};
257
258                 switch (init_po1030[i][0]) {
259                 case BRIDGE:
260                         err = m5602_write_bridge(sd,
261                                 init_po1030[i][1],
262                                 init_po1030[i][2]);
263                         break;
264
265                 case SENSOR:
266                         data[0] = init_po1030[i][2];
267                         err = m5602_write_sensor(sd,
268                                 init_po1030[i][1], data, 1);
269                         break;
270
271                 default:
272                         pr_info("Invalid stream command, exiting init\n");
273                         return -EINVAL;
274                 }
275         }
276         if (err < 0)
277                 return err;
278
279         if (dump_sensor)
280                 po1030_dump_registers(sd);
281
282         err = po1030_set_exposure(&sd->gspca_dev,
283                                    sensor_settings[EXPOSURE_IDX]);
284         if (err < 0)
285                 return err;
286
287         err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
288         if (err < 0)
289                 return err;
290
291         err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
292         if (err < 0)
293                 return err;
294
295         err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
296         if (err < 0)
297                 return err;
298
299         err = po1030_set_red_balance(&sd->gspca_dev,
300                                       sensor_settings[RED_BALANCE_IDX]);
301         if (err < 0)
302                 return err;
303
304         err = po1030_set_blue_balance(&sd->gspca_dev,
305                                       sensor_settings[BLUE_BALANCE_IDX]);
306         if (err < 0)
307                 return err;
308
309         err = po1030_set_green_balance(&sd->gspca_dev,
310                                        sensor_settings[GREEN_BALANCE_IDX]);
311         if (err < 0)
312                 return err;
313
314         err = po1030_set_auto_white_balance(&sd->gspca_dev,
315                                 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
316         if (err < 0)
317                 return err;
318
319         err = po1030_set_auto_exposure(&sd->gspca_dev,
320                                 sensor_settings[AUTO_EXPOSURE_IDX]);
321         return err;
322 }
323
324 int po1030_start(struct sd *sd)
325 {
326         struct cam *cam = &sd->gspca_dev.cam;
327         int i, err = 0;
328         int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
329         int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
330         int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
331         u8 data;
332
333         switch (width) {
334         case 320:
335                 data = PO1030_SUBSAMPLING;
336                 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
337                 if (err < 0)
338                         return err;
339
340                 data = ((width + 3) >> 8) & 0xff;
341                 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
342                 if (err < 0)
343                         return err;
344
345                 data = (width + 3) & 0xff;
346                 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
347                 if (err < 0)
348                         return err;
349
350                 data = ((height + 1) >> 8) & 0xff;
351                 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
352                 if (err < 0)
353                         return err;
354
355                 data = (height + 1) & 0xff;
356                 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
357
358                 height += 6;
359                 width -= 1;
360                 break;
361
362         case 640:
363                 data = 0;
364                 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
365                 if (err < 0)
366                         return err;
367
368                 data = ((width + 7) >> 8) & 0xff;
369                 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
370                 if (err < 0)
371                         return err;
372
373                 data = (width + 7) & 0xff;
374                 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
375                 if (err < 0)
376                         return err;
377
378                 data = ((height + 3) >> 8) & 0xff;
379                 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
380                 if (err < 0)
381                         return err;
382
383                 data = (height + 3) & 0xff;
384                 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
385
386                 height += 12;
387                 width -= 2;
388                 break;
389         }
390         err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
391         if (err < 0)
392                 return err;
393
394         err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
395         if (err < 0)
396                 return err;
397
398         err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
399         if (err < 0)
400                 return err;
401
402         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
403         if (err < 0)
404                 return err;
405
406         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
407                                  ((ver_offs >> 8) & 0xff));
408         if (err < 0)
409                 return err;
410
411         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
412         if (err < 0)
413                 return err;
414
415         for (i = 0; i < 2 && !err; i++)
416                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
417         if (err < 0)
418                 return err;
419
420         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
421         if (err < 0)
422                 return err;
423
424         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
425         if (err < 0)
426                 return err;
427
428         for (i = 0; i < 2 && !err; i++)
429                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
430
431         for (i = 0; i < 2 && !err; i++)
432                 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
433
434         for (i = 0; i < 2 && !err; i++)
435                 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
436         if (err < 0)
437                 return err;
438
439         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
440         if (err < 0)
441                 return err;
442
443         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
444         if (err < 0)
445                 return err;
446
447         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
448         return err;
449 }
450
451 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
452 {
453         struct sd *sd = (struct sd *) gspca_dev;
454         s32 *sensor_settings = sd->sensor_priv;
455
456         *val = sensor_settings[EXPOSURE_IDX];
457         PDEBUG(D_V4L2, "Exposure read as %d", *val);
458         return 0;
459 }
460
461 static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
462 {
463         struct sd *sd = (struct sd *) gspca_dev;
464         s32 *sensor_settings = sd->sensor_priv;
465         u8 i2c_data;
466         int err;
467
468         sensor_settings[EXPOSURE_IDX] = val;
469         PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
470
471         i2c_data = ((val & 0xff00) >> 8);
472         PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
473                i2c_data);
474
475         err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
476                                   &i2c_data, 1);
477         if (err < 0)
478                 return err;
479
480         i2c_data = (val & 0xff);
481         PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
482                i2c_data);
483         err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
484                                   &i2c_data, 1);
485
486         return err;
487 }
488
489 static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
490 {
491         struct sd *sd = (struct sd *) gspca_dev;
492         s32 *sensor_settings = sd->sensor_priv;
493
494         *val = sensor_settings[GAIN_IDX];
495         PDEBUG(D_V4L2, "Read global gain %d", *val);
496         return 0;
497 }
498
499 static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
500 {
501         struct sd *sd = (struct sd *) gspca_dev;
502         s32 *sensor_settings = sd->sensor_priv;
503         u8 i2c_data;
504         int err;
505
506         sensor_settings[GAIN_IDX] = val;
507
508         i2c_data = val & 0xff;
509         PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
510         err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
511                                  &i2c_data, 1);
512         return err;
513 }
514
515 static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
516 {
517         struct sd *sd = (struct sd *) gspca_dev;
518         s32 *sensor_settings = sd->sensor_priv;
519
520         *val = sensor_settings[HFLIP_IDX];
521         PDEBUG(D_V4L2, "Read hflip %d", *val);
522
523         return 0;
524 }
525
526 static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
527 {
528         struct sd *sd = (struct sd *) gspca_dev;
529         s32 *sensor_settings = sd->sensor_priv;
530         u8 i2c_data;
531         int err;
532
533         sensor_settings[HFLIP_IDX] = val;
534
535         PDEBUG(D_V4L2, "Set hflip %d", val);
536         err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
537         if (err < 0)
538                 return err;
539
540         i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
541
542         err = m5602_write_sensor(sd, PO1030_CONTROL2,
543                                  &i2c_data, 1);
544
545         return err;
546 }
547
548 static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
549 {
550         struct sd *sd = (struct sd *) gspca_dev;
551         s32 *sensor_settings = sd->sensor_priv;
552
553         *val = sensor_settings[VFLIP_IDX];
554         PDEBUG(D_V4L2, "Read vflip %d", *val);
555
556         return 0;
557 }
558
559 static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
560 {
561         struct sd *sd = (struct sd *) gspca_dev;
562         s32 *sensor_settings = sd->sensor_priv;
563         u8 i2c_data;
564         int err;
565
566         sensor_settings[VFLIP_IDX] = val;
567
568         PDEBUG(D_V4L2, "Set vflip %d", val);
569         err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
570         if (err < 0)
571                 return err;
572
573         i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
574
575         err = m5602_write_sensor(sd, PO1030_CONTROL2,
576                                  &i2c_data, 1);
577
578         return err;
579 }
580
581 static int po1030_get_red_balance(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[RED_BALANCE_IDX];
587         PDEBUG(D_V4L2, "Read red gain %d", *val);
588         return 0;
589 }
590
591 static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
592 {
593         struct sd *sd = (struct sd *) gspca_dev;
594         s32 *sensor_settings = sd->sensor_priv;
595         u8 i2c_data;
596         int err;
597
598         sensor_settings[RED_BALANCE_IDX] = val;
599
600         i2c_data = val & 0xff;
601         PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
602         err = m5602_write_sensor(sd, PO1030_RED_GAIN,
603                                   &i2c_data, 1);
604         return err;
605 }
606
607 static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
608 {
609         struct sd *sd = (struct sd *) gspca_dev;
610         s32 *sensor_settings = sd->sensor_priv;
611
612         *val = sensor_settings[BLUE_BALANCE_IDX];
613         PDEBUG(D_V4L2, "Read blue gain %d", *val);
614
615         return 0;
616 }
617
618 static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
619 {
620         struct sd *sd = (struct sd *) gspca_dev;
621         s32 *sensor_settings = sd->sensor_priv;
622         u8 i2c_data;
623         int err;
624
625         sensor_settings[BLUE_BALANCE_IDX] = val;
626
627         i2c_data = val & 0xff;
628         PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
629         err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
630                                   &i2c_data, 1);
631
632         return err;
633 }
634
635 static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
636 {
637         struct sd *sd = (struct sd *) gspca_dev;
638         s32 *sensor_settings = sd->sensor_priv;
639
640         *val = sensor_settings[GREEN_BALANCE_IDX];
641         PDEBUG(D_V4L2, "Read green gain %d", *val);
642
643         return 0;
644 }
645
646 static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
647 {
648         struct sd *sd = (struct sd *) gspca_dev;
649         s32 *sensor_settings = sd->sensor_priv;
650         u8 i2c_data;
651         int err;
652
653         sensor_settings[GREEN_BALANCE_IDX] = val;
654         i2c_data = val & 0xff;
655         PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
656
657         err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
658                            &i2c_data, 1);
659         if (err < 0)
660                 return err;
661
662         return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
663                                  &i2c_data, 1);
664 }
665
666 static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
667                                          __s32 *val)
668 {
669         struct sd *sd = (struct sd *) gspca_dev;
670         s32 *sensor_settings = sd->sensor_priv;
671
672         *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
673         PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
674
675         return 0;
676 }
677
678 static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
679                                          __s32 val)
680 {
681         struct sd *sd = (struct sd *) gspca_dev;
682         s32 *sensor_settings = sd->sensor_priv;
683         u8 i2c_data;
684         int err;
685
686         sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
687
688         err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
689         if (err < 0)
690                 return err;
691
692         PDEBUG(D_V4L2, "Set auto white balance to %d", val);
693         i2c_data = (i2c_data & 0xfe) | (val & 0x01);
694         err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
695         return err;
696 }
697
698 static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
699                                     __s32 *val)
700 {
701         struct sd *sd = (struct sd *) gspca_dev;
702         s32 *sensor_settings = sd->sensor_priv;
703
704         *val = sensor_settings[AUTO_EXPOSURE_IDX];
705         PDEBUG(D_V4L2, "Auto exposure is %d", *val);
706         return 0;
707 }
708
709 static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
710                                     __s32 val)
711 {
712         struct sd *sd = (struct sd *) gspca_dev;
713         s32 *sensor_settings = sd->sensor_priv;
714         u8 i2c_data;
715         int err;
716
717         sensor_settings[AUTO_EXPOSURE_IDX] = val;
718         err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
719         if (err < 0)
720                 return err;
721
722         PDEBUG(D_V4L2, "Set auto exposure to %d", val);
723         i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
724         return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
725 }
726
727 void po1030_disconnect(struct sd *sd)
728 {
729         sd->sensor = NULL;
730         kfree(sd->sensor_priv);
731 }
732
733 static void po1030_dump_registers(struct sd *sd)
734 {
735         int address;
736         u8 value = 0;
737
738         pr_info("Dumping the po1030 sensor core registers\n");
739         for (address = 0; address < 0x7f; address++) {
740                 m5602_read_sensor(sd, address, &value, 1);
741                 pr_info("register 0x%x contains 0x%x\n", address, value);
742         }
743
744         pr_info("po1030 register state dump complete\n");
745
746         pr_info("Probing for which registers that are read/write\n");
747         for (address = 0; address < 0xff; address++) {
748                 u8 old_value, ctrl_value;
749                 u8 test_value[2] = {0xff, 0xff};
750
751                 m5602_read_sensor(sd, address, &old_value, 1);
752                 m5602_write_sensor(sd, address, test_value, 1);
753                 m5602_read_sensor(sd, address, &ctrl_value, 1);
754
755                 if (ctrl_value == test_value[0])
756                         pr_info("register 0x%x is writeable\n", address);
757                 else
758                         pr_info("register 0x%x is read only\n", address);
759
760                 /* Restore original value */
761                 m5602_write_sensor(sd, address, &old_value, 1);
762         }
763 }