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