Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
m5602_ov7660.c
Go to the documentation of this file.
1 /*
2  * Driver for the ov7660 sensor
3  *
4  * Copyright (C) 2009 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_ov7660.h"
22 
23 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25 static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
26  __s32 *val);
27 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
28  __s32 val);
29 static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
30 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
31 static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
32 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
33 static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34 static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35 static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36 static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37 
38 static const struct ctrl ov7660_ctrls[] = {
39 #define GAIN_IDX 1
40  {
41  {
42  .id = V4L2_CID_GAIN,
43  .type = V4L2_CTRL_TYPE_INTEGER,
44  .name = "gain",
45  .minimum = 0x00,
46  .maximum = 0xff,
47  .step = 0x1,
48  .default_value = OV7660_DEFAULT_GAIN,
49  .flags = V4L2_CTRL_FLAG_SLIDER
50  },
51  .set = ov7660_set_gain,
52  .get = ov7660_get_gain
53  },
54 #define BLUE_BALANCE_IDX 2
55 #define RED_BALANCE_IDX 3
56 #define AUTO_WHITE_BALANCE_IDX 4
57  {
58  {
60  .type = V4L2_CTRL_TYPE_BOOLEAN,
61  .name = "auto white balance",
62  .minimum = 0,
63  .maximum = 1,
64  .step = 1,
65  .default_value = 1
66  },
67  .set = ov7660_set_auto_white_balance,
68  .get = ov7660_get_auto_white_balance
69  },
70 #define AUTO_GAIN_CTRL_IDX 5
71  {
72  {
73  .id = V4L2_CID_AUTOGAIN,
74  .type = V4L2_CTRL_TYPE_BOOLEAN,
75  .name = "auto gain control",
76  .minimum = 0,
77  .maximum = 1,
78  .step = 1,
79  .default_value = 1
80  },
81  .set = ov7660_set_auto_gain,
82  .get = ov7660_get_auto_gain
83  },
84 #define AUTO_EXPOSURE_IDX 6
85  {
86  {
88  .type = V4L2_CTRL_TYPE_BOOLEAN,
89  .name = "auto exposure",
90  .minimum = 0,
91  .maximum = 1,
92  .step = 1,
93  .default_value = 1
94  },
95  .set = ov7660_set_auto_exposure,
96  .get = ov7660_get_auto_exposure
97  },
98 #define HFLIP_IDX 7
99  {
100  {
101  .id = V4L2_CID_HFLIP,
102  .type = V4L2_CTRL_TYPE_BOOLEAN,
103  .name = "horizontal flip",
104  .minimum = 0,
105  .maximum = 1,
106  .step = 1,
107  .default_value = 0
108  },
109  .set = ov7660_set_hflip,
110  .get = ov7660_get_hflip
111  },
112 #define VFLIP_IDX 8
113  {
114  {
115  .id = V4L2_CID_VFLIP,
116  .type = V4L2_CTRL_TYPE_BOOLEAN,
117  .name = "vertical flip",
118  .minimum = 0,
119  .maximum = 1,
120  .step = 1,
121  .default_value = 0
122  },
123  .set = ov7660_set_vflip,
124  .get = ov7660_get_vflip
125  },
126 
127 };
128 
129 static struct v4l2_pix_format ov7660_modes[] = {
130  {
131  640,
132  480,
135  .sizeimage =
136  640 * 480,
137  .bytesperline = 640,
138  .colorspace = V4L2_COLORSPACE_SRGB,
139  .priv = 0
140  }
141 };
142 
143 static void ov7660_dump_registers(struct sd *sd);
144 
145 int ov7660_probe(struct sd *sd)
146 {
147  int err = 0, i;
148  u8 prod_id = 0, ver_id = 0;
149 
150  s32 *sensor_settings;
151 
152  if (force_sensor) {
153  if (force_sensor == OV7660_SENSOR) {
154  pr_info("Forcing an %s sensor\n", ov7660.name);
155  goto sensor_found;
156  }
157  /* If we want to force another sensor,
158  don't try to probe this one */
159  return -ENODEV;
160  }
161 
162  /* Do the preinit */
163  for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
164  u8 data[2];
165 
166  if (preinit_ov7660[i][0] == BRIDGE) {
167  err = m5602_write_bridge(sd,
168  preinit_ov7660[i][1],
169  preinit_ov7660[i][2]);
170  } else {
171  data[0] = preinit_ov7660[i][2];
172  err = m5602_write_sensor(sd,
173  preinit_ov7660[i][1], data, 1);
174  }
175  }
176  if (err < 0)
177  return err;
178 
179  if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
180  return -ENODEV;
181 
182  if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
183  return -ENODEV;
184 
185  pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
186 
187  if ((prod_id == 0x76) && (ver_id == 0x60)) {
188  pr_info("Detected a ov7660 sensor\n");
189  goto sensor_found;
190  }
191  return -ENODEV;
192 
193 sensor_found:
194  sensor_settings = kmalloc(
195  ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
196  if (!sensor_settings)
197  return -ENOMEM;
198 
199  sd->gspca_dev.cam.cam_mode = ov7660_modes;
200  sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
201  sd->desc->ctrls = ov7660_ctrls;
202  sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
203 
204  for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
205  sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
206  sd->sensor_priv = sensor_settings;
207 
208  return 0;
209 }
210 
211 int ov7660_init(struct sd *sd)
212 {
213  int i, err = 0;
214  s32 *sensor_settings = sd->sensor_priv;
215 
216  /* Init the sensor */
217  for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
218  u8 data[2];
219 
220  if (init_ov7660[i][0] == BRIDGE) {
221  err = m5602_write_bridge(sd,
222  init_ov7660[i][1],
223  init_ov7660[i][2]);
224  } else {
225  data[0] = init_ov7660[i][2];
226  err = m5602_write_sensor(sd,
227  init_ov7660[i][1], data, 1);
228  }
229  }
230 
231  if (dump_sensor)
232  ov7660_dump_registers(sd);
233 
234  err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
235  if (err < 0)
236  return err;
237 
238  err = ov7660_set_auto_white_balance(&sd->gspca_dev,
239  sensor_settings[AUTO_WHITE_BALANCE_IDX]);
240  if (err < 0)
241  return err;
242 
243  err = ov7660_set_auto_gain(&sd->gspca_dev,
244  sensor_settings[AUTO_GAIN_CTRL_IDX]);
245  if (err < 0)
246  return err;
247 
248  err = ov7660_set_auto_exposure(&sd->gspca_dev,
249  sensor_settings[AUTO_EXPOSURE_IDX]);
250  if (err < 0)
251  return err;
252  err = ov7660_set_hflip(&sd->gspca_dev,
253  sensor_settings[HFLIP_IDX]);
254  if (err < 0)
255  return err;
256 
257  err = ov7660_set_vflip(&sd->gspca_dev,
258  sensor_settings[VFLIP_IDX]);
259 
260  return err;
261 }
262 
263 int ov7660_start(struct sd *sd)
264 {
265  return 0;
266 }
267 
268 int ov7660_stop(struct sd *sd)
269 {
270  return 0;
271 }
272 
273 void ov7660_disconnect(struct sd *sd)
274 {
275  ov7660_stop(sd);
276 
277  sd->sensor = NULL;
278  kfree(sd->sensor_priv);
279 }
280 
281 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
282 {
283  struct sd *sd = (struct sd *) gspca_dev;
284  s32 *sensor_settings = sd->sensor_priv;
285 
286  *val = sensor_settings[GAIN_IDX];
287  PDEBUG(D_V4L2, "Read gain %d", *val);
288  return 0;
289 }
290 
291 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
292 {
293  int err;
294  u8 i2c_data;
295  struct sd *sd = (struct sd *) gspca_dev;
296  s32 *sensor_settings = sd->sensor_priv;
297 
298  PDEBUG(D_V4L2, "Setting gain to %d", val);
299 
300  sensor_settings[GAIN_IDX] = val;
301 
302  err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
303  return err;
304 }
305 
306 
307 static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
308  __s32 *val)
309 {
310  struct sd *sd = (struct sd *) gspca_dev;
311  s32 *sensor_settings = sd->sensor_priv;
312 
313  *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
314  return 0;
315 }
316 
317 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
318  __s32 val)
319 {
320  int err;
321  u8 i2c_data;
322  struct sd *sd = (struct sd *) gspca_dev;
323  s32 *sensor_settings = sd->sensor_priv;
324 
325  PDEBUG(D_V4L2, "Set auto white balance to %d", val);
326 
327  sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
328  err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
329  if (err < 0)
330  return err;
331 
332  i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
333  err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
334 
335  return err;
336 }
337 
338 static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
339 {
340  struct sd *sd = (struct sd *) gspca_dev;
341  s32 *sensor_settings = sd->sensor_priv;
342 
343  *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
344  PDEBUG(D_V4L2, "Read auto gain control %d", *val);
345  return 0;
346 }
347 
348 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
349 {
350  int err;
351  u8 i2c_data;
352  struct sd *sd = (struct sd *) gspca_dev;
353  s32 *sensor_settings = sd->sensor_priv;
354 
355  PDEBUG(D_V4L2, "Set auto gain control to %d", val);
356 
357  sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
358  err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
359  if (err < 0)
360  return err;
361 
362  i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
363 
364  return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
365 }
366 
367 static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
368 {
369  struct sd *sd = (struct sd *) gspca_dev;
370  s32 *sensor_settings = sd->sensor_priv;
371 
372  *val = sensor_settings[AUTO_EXPOSURE_IDX];
373  PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
374  return 0;
375 }
376 
377 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
378  __s32 val)
379 {
380  int err;
381  u8 i2c_data;
382  struct sd *sd = (struct sd *) gspca_dev;
383  s32 *sensor_settings = sd->sensor_priv;
384 
385  PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
386 
387  sensor_settings[AUTO_EXPOSURE_IDX] = val;
388  err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
389  if (err < 0)
390  return err;
391 
392  i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
393 
394  return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
395 }
396 
397 static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
398 {
399  struct sd *sd = (struct sd *) gspca_dev;
400  s32 *sensor_settings = sd->sensor_priv;
401 
402  *val = sensor_settings[HFLIP_IDX];
403  PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
404  return 0;
405 }
406 
407 static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
408 {
409  int err;
410  u8 i2c_data;
411  struct sd *sd = (struct sd *) gspca_dev;
412  s32 *sensor_settings = sd->sensor_priv;
413 
414  PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
415 
416  sensor_settings[HFLIP_IDX] = val;
417 
418  i2c_data = ((val & 0x01) << 5) |
419  (sensor_settings[VFLIP_IDX] << 4);
420 
421  err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
422 
423  return err;
424 }
425 
426 static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
427 {
428  struct sd *sd = (struct sd *) gspca_dev;
429  s32 *sensor_settings = sd->sensor_priv;
430 
431  *val = sensor_settings[VFLIP_IDX];
432  PDEBUG(D_V4L2, "Read vertical flip %d", *val);
433 
434  return 0;
435 }
436 
437 static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
438 {
439  int err;
440  u8 i2c_data;
441  struct sd *sd = (struct sd *) gspca_dev;
442  s32 *sensor_settings = sd->sensor_priv;
443 
444  PDEBUG(D_V4L2, "Set vertical flip to %d", val);
445  sensor_settings[VFLIP_IDX] = val;
446 
447  i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
448  err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
449  if (err < 0)
450  return err;
451 
452  /* When vflip is toggled we need to readjust the bridge hsync/vsync */
453  if (gspca_dev->streaming)
454  err = ov7660_start(sd);
455 
456  return err;
457 }
458 
459 static void ov7660_dump_registers(struct sd *sd)
460 {
461  int address;
462  pr_info("Dumping the ov7660 register state\n");
463  for (address = 0; address < 0xa9; address++) {
464  u8 value;
465  m5602_read_sensor(sd, address, &value, 1);
466  pr_info("register 0x%x contains 0x%x\n", address, value);
467  }
468 
469  pr_info("ov7660 register state dump complete\n");
470 
471  pr_info("Probing for which registers that are read/write\n");
472  for (address = 0; address < 0xff; address++) {
473  u8 old_value, ctrl_value;
474  u8 test_value[2] = {0xff, 0xff};
475 
476  m5602_read_sensor(sd, address, &old_value, 1);
477  m5602_write_sensor(sd, address, test_value, 1);
478  m5602_read_sensor(sd, address, &ctrl_value, 1);
479 
480  if (ctrl_value == test_value[0])
481  pr_info("register 0x%x is writeable\n", address);
482  else
483  pr_info("register 0x%x is read only\n", address);
484 
485  /* Restore original value */
486  m5602_write_sensor(sd, address, &old_value, 1);
487  }
488 }