Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
m5602_po1030.c
Go to the documentation of this file.
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 <[email protected]>
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,
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  {
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  {
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  {
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  {
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)
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 
395  if (err < 0)
396  return err;
397 
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 
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++)
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++)
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++)
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 
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);
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);
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 
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 
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);
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);
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 
658  &i2c_data, 1);
659  if (err < 0)
660  return err;
661 
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 }