2 * Driver for the ov7660 sensor
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 <m5602@x3ng.com.br>
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
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.
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 #include "m5602_ov7660.h"
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
,
27 static int ov7660_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
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
);
38 static const struct ctrl ov7660_ctrls
[] = {
43 .type
= V4L2_CTRL_TYPE_INTEGER
,
48 .default_value
= OV7660_DEFAULT_GAIN
,
49 .flags
= V4L2_CTRL_FLAG_SLIDER
51 .set
= ov7660_set_gain
,
52 .get
= ov7660_get_gain
54 #define BLUE_BALANCE_IDX 2
55 #define RED_BALANCE_IDX 3
56 #define AUTO_WHITE_BALANCE_IDX 4
59 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
60 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
61 .name
= "auto white balance",
67 .set
= ov7660_set_auto_white_balance
,
68 .get
= ov7660_get_auto_white_balance
70 #define AUTO_GAIN_CTRL_IDX 5
73 .id
= V4L2_CID_AUTOGAIN
,
74 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
75 .name
= "auto gain control",
81 .set
= ov7660_set_auto_gain
,
82 .get
= ov7660_get_auto_gain
84 #define AUTO_EXPOSURE_IDX 6
87 .id
= V4L2_CID_EXPOSURE_AUTO
,
88 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
89 .name
= "auto exposure",
95 .set
= ov7660_set_auto_exposure
,
96 .get
= ov7660_get_auto_exposure
101 .id
= V4L2_CID_HFLIP
,
102 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
103 .name
= "horizontal flip",
109 .set
= ov7660_set_hflip
,
110 .get
= ov7660_get_hflip
115 .id
= V4L2_CID_VFLIP
,
116 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
117 .name
= "vertical flip",
123 .set
= ov7660_set_vflip
,
124 .get
= ov7660_get_vflip
129 static struct v4l2_pix_format ov7660_modes
[] = {
138 .colorspace
= V4L2_COLORSPACE_SRGB
,
143 static void ov7660_dump_registers(struct sd
*sd
);
145 int ov7660_probe(struct sd
*sd
)
148 u8 prod_id
= 0, ver_id
= 0;
150 s32
*sensor_settings
;
153 if (force_sensor
== OV7660_SENSOR
) {
154 pr_info("Forcing an %s sensor\n", ov7660
.name
);
157 /* If we want to force another sensor,
158 don't try to probe this one */
163 for (i
= 0; i
< ARRAY_SIZE(preinit_ov7660
) && !err
; i
++) {
166 if (preinit_ov7660
[i
][0] == BRIDGE
) {
167 err
= m5602_write_bridge(sd
,
168 preinit_ov7660
[i
][1],
169 preinit_ov7660
[i
][2]);
171 data
[0] = preinit_ov7660
[i
][2];
172 err
= m5602_write_sensor(sd
,
173 preinit_ov7660
[i
][1], data
, 1);
179 if (m5602_read_sensor(sd
, OV7660_PID
, &prod_id
, 1))
182 if (m5602_read_sensor(sd
, OV7660_VER
, &ver_id
, 1))
185 pr_info("Sensor reported 0x%x%x\n", prod_id
, ver_id
);
187 if ((prod_id
== 0x76) && (ver_id
== 0x60)) {
188 pr_info("Detected a ov7660 sensor\n");
194 sensor_settings
= kmalloc(
195 ARRAY_SIZE(ov7660_ctrls
) * sizeof(s32
), GFP_KERNEL
);
196 if (!sensor_settings
)
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
);
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
;
211 int ov7660_init(struct sd
*sd
)
214 s32
*sensor_settings
= sd
->sensor_priv
;
216 /* Init the sensor */
217 for (i
= 0; i
< ARRAY_SIZE(init_ov7660
); i
++) {
220 if (init_ov7660
[i
][0] == BRIDGE
) {
221 err
= m5602_write_bridge(sd
,
225 data
[0] = init_ov7660
[i
][2];
226 err
= m5602_write_sensor(sd
,
227 init_ov7660
[i
][1], data
, 1);
232 ov7660_dump_registers(sd
);
234 err
= ov7660_set_gain(&sd
->gspca_dev
, sensor_settings
[GAIN_IDX
]);
238 err
= ov7660_set_auto_white_balance(&sd
->gspca_dev
,
239 sensor_settings
[AUTO_WHITE_BALANCE_IDX
]);
243 err
= ov7660_set_auto_gain(&sd
->gspca_dev
,
244 sensor_settings
[AUTO_GAIN_CTRL_IDX
]);
248 err
= ov7660_set_auto_exposure(&sd
->gspca_dev
,
249 sensor_settings
[AUTO_EXPOSURE_IDX
]);
252 err
= ov7660_set_hflip(&sd
->gspca_dev
,
253 sensor_settings
[HFLIP_IDX
]);
257 err
= ov7660_set_vflip(&sd
->gspca_dev
,
258 sensor_settings
[VFLIP_IDX
]);
263 int ov7660_start(struct sd
*sd
)
268 int ov7660_stop(struct sd
*sd
)
273 void ov7660_disconnect(struct sd
*sd
)
278 kfree(sd
->sensor_priv
);
281 static int ov7660_get_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
283 struct sd
*sd
= (struct sd
*) gspca_dev
;
284 s32
*sensor_settings
= sd
->sensor_priv
;
286 *val
= sensor_settings
[GAIN_IDX
];
287 PDEBUG(D_V4L2
, "Read gain %d", *val
);
291 static int ov7660_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
295 struct sd
*sd
= (struct sd
*) gspca_dev
;
296 s32
*sensor_settings
= sd
->sensor_priv
;
298 PDEBUG(D_V4L2
, "Setting gain to %d", val
);
300 sensor_settings
[GAIN_IDX
] = val
;
302 err
= m5602_write_sensor(sd
, OV7660_GAIN
, &i2c_data
, 1);
307 static int ov7660_get_auto_white_balance(struct gspca_dev
*gspca_dev
,
310 struct sd
*sd
= (struct sd
*) gspca_dev
;
311 s32
*sensor_settings
= sd
->sensor_priv
;
313 *val
= sensor_settings
[AUTO_WHITE_BALANCE_IDX
];
317 static int ov7660_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
322 struct sd
*sd
= (struct sd
*) gspca_dev
;
323 s32
*sensor_settings
= sd
->sensor_priv
;
325 PDEBUG(D_V4L2
, "Set auto white balance to %d", val
);
327 sensor_settings
[AUTO_WHITE_BALANCE_IDX
] = val
;
328 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
332 i2c_data
= ((i2c_data
& 0xfd) | ((val
& 0x01) << 1));
333 err
= m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
338 static int ov7660_get_auto_gain(struct gspca_dev
*gspca_dev
, __s32
*val
)
340 struct sd
*sd
= (struct sd
*) gspca_dev
;
341 s32
*sensor_settings
= sd
->sensor_priv
;
343 *val
= sensor_settings
[AUTO_GAIN_CTRL_IDX
];
344 PDEBUG(D_V4L2
, "Read auto gain control %d", *val
);
348 static int ov7660_set_auto_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
352 struct sd
*sd
= (struct sd
*) gspca_dev
;
353 s32
*sensor_settings
= sd
->sensor_priv
;
355 PDEBUG(D_V4L2
, "Set auto gain control to %d", val
);
357 sensor_settings
[AUTO_GAIN_CTRL_IDX
] = val
;
358 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
362 i2c_data
= ((i2c_data
& 0xfb) | ((val
& 0x01) << 2));
364 return m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
367 static int ov7660_get_auto_exposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
369 struct sd
*sd
= (struct sd
*) gspca_dev
;
370 s32
*sensor_settings
= sd
->sensor_priv
;
372 *val
= sensor_settings
[AUTO_EXPOSURE_IDX
];
373 PDEBUG(D_V4L2
, "Read auto exposure control %d", *val
);
377 static int ov7660_set_auto_exposure(struct gspca_dev
*gspca_dev
,
382 struct sd
*sd
= (struct sd
*) gspca_dev
;
383 s32
*sensor_settings
= sd
->sensor_priv
;
385 PDEBUG(D_V4L2
, "Set auto exposure control to %d", val
);
387 sensor_settings
[AUTO_EXPOSURE_IDX
] = val
;
388 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
392 i2c_data
= ((i2c_data
& 0xfe) | ((val
& 0x01) << 0));
394 return m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
397 static int ov7660_get_hflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
399 struct sd
*sd
= (struct sd
*) gspca_dev
;
400 s32
*sensor_settings
= sd
->sensor_priv
;
402 *val
= sensor_settings
[HFLIP_IDX
];
403 PDEBUG(D_V4L2
, "Read horizontal flip %d", *val
);
407 static int ov7660_set_hflip(struct gspca_dev
*gspca_dev
, __s32 val
)
411 struct sd
*sd
= (struct sd
*) gspca_dev
;
412 s32
*sensor_settings
= sd
->sensor_priv
;
414 PDEBUG(D_V4L2
, "Set horizontal flip to %d", val
);
416 sensor_settings
[HFLIP_IDX
] = val
;
418 i2c_data
= ((val
& 0x01) << 5) |
419 (sensor_settings
[VFLIP_IDX
] << 4);
421 err
= m5602_write_sensor(sd
, OV7660_MVFP
, &i2c_data
, 1);
426 static int ov7660_get_vflip(struct gspca_dev
*gspca_dev
, __s32
*val
)
428 struct sd
*sd
= (struct sd
*) gspca_dev
;
429 s32
*sensor_settings
= sd
->sensor_priv
;
431 *val
= sensor_settings
[VFLIP_IDX
];
432 PDEBUG(D_V4L2
, "Read vertical flip %d", *val
);
437 static int ov7660_set_vflip(struct gspca_dev
*gspca_dev
, __s32 val
)
441 struct sd
*sd
= (struct sd
*) gspca_dev
;
442 s32
*sensor_settings
= sd
->sensor_priv
;
444 PDEBUG(D_V4L2
, "Set vertical flip to %d", val
);
445 sensor_settings
[VFLIP_IDX
] = val
;
447 i2c_data
= ((val
& 0x01) << 4) | (sensor_settings
[VFLIP_IDX
] << 5);
448 err
= m5602_write_sensor(sd
, OV7660_MVFP
, &i2c_data
, 1);
452 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
453 if (gspca_dev
->streaming
)
454 err
= ov7660_start(sd
);
459 static void ov7660_dump_registers(struct sd
*sd
)
462 pr_info("Dumping the ov7660 register state\n");
463 for (address
= 0; address
< 0xa9; address
++) {
465 m5602_read_sensor(sd
, address
, &value
, 1);
466 pr_info("register 0x%x contains 0x%x\n", address
, value
);
469 pr_info("ov7660 register state dump complete\n");
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};
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);
480 if (ctrl_value
== test_value
[0])
481 pr_info("register 0x%x is writeable\n", address
);
483 pr_info("register 0x%x is read only\n", address
);
485 /* Restore original value */
486 m5602_write_sensor(sd
, address
, &old_value
, 1);