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 #include "m5602_ov7660.h"
21 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
22 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
23 static int ov7660_get_blue_gain(struct gspca_dev *gspca_dev, __s32 *val);
24 static int ov7660_set_blue_gain(struct gspca_dev *gspca_dev, __s32 val);
26 const static struct ctrl ov7660_ctrls[] = {
31 .type = V4L2_CTRL_TYPE_INTEGER,
36 .default_value = OV7660_DEFAULT_GAIN,
37 .flags = V4L2_CTRL_FLAG_SLIDER
39 .set = ov7660_set_gain,
40 .get = ov7660_get_gain
42 #define BLUE_BALANCE_IDX 2
45 .id = V4L2_CID_BLUE_BALANCE,
46 .type = V4L2_CTRL_TYPE_INTEGER,
47 .name = "blue balance",
51 .default_value = OV7660_DEFAULT_BLUE_GAIN,
52 .flags = V4L2_CTRL_FLAG_SLIDER
54 .set = ov7660_set_blue_gain,
55 .get = ov7660_get_blue_gain
60 static struct v4l2_pix_format ov7660_modes[] = {
69 .colorspace = V4L2_COLORSPACE_SRGB,
74 static void ov7660_dump_registers(struct sd *sd);
76 int ov7660_probe(struct sd *sd)
79 u8 prod_id = 0, ver_id = 0;
84 if (force_sensor == OV7660_SENSOR) {
85 info("Forcing an %s sensor", ov7660.name);
88 /* If we want to force another sensor,
89 don't try to probe this one */
94 for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
97 if (preinit_ov7660[i][0] == BRIDGE) {
98 err = m5602_write_bridge(sd,
100 preinit_ov7660[i][2]);
102 data[0] = preinit_ov7660[i][2];
103 err = m5602_write_sensor(sd,
104 preinit_ov7660[i][1], data, 1);
110 if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
113 if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
116 info("Sensor reported 0x%x%x", prod_id, ver_id);
118 if ((prod_id == 0x76) && (ver_id == 0x60)) {
119 info("Detected a ov7660 sensor");
125 sensor_settings = kmalloc(
126 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
127 if (!sensor_settings)
130 sd->gspca_dev.cam.cam_mode = ov7660_modes;
131 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
132 sd->desc->ctrls = ov7660_ctrls;
133 sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
135 for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
136 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
137 sd->sensor_priv = sensor_settings;
142 int ov7660_init(struct sd *sd)
145 s32 *sensor_settings = sd->sensor_priv;
147 /* Init the sensor */
148 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
151 if (init_ov7660[i][0] == BRIDGE) {
152 err = m5602_write_bridge(sd,
156 data[0] = init_ov7660[i][2];
157 err = m5602_write_sensor(sd,
158 init_ov7660[i][1], data, 1);
163 ov7660_dump_registers(sd);
165 err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
172 int ov7660_start(struct sd *sd)
177 int ov7660_stop(struct sd *sd)
182 void ov7660_disconnect(struct sd *sd)
187 kfree(sd->sensor_priv);
190 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
192 struct sd *sd = (struct sd *) gspca_dev;
193 s32 *sensor_settings = sd->sensor_priv;
195 *val = sensor_settings[GAIN_IDX];
196 PDEBUG(D_V4L2, "Read gain %d", *val);
200 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
204 struct sd *sd = (struct sd *) gspca_dev;
205 s32 *sensor_settings = sd->sensor_priv;
207 PDEBUG(D_V4L2, "Setting gain to %d", val);
209 sensor_settings[GAIN_IDX] = val;
211 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
215 static int ov7660_get_blue_gain(struct gspca_dev *gspca_dev, __s32 *val)
217 struct sd *sd = (struct sd *) gspca_dev;
218 s32 *sensor_settings = sd->sensor_priv;
220 *val = sensor_settings[BLUE_BALANCE_IDX];
221 PDEBUG(D_V4L2, "Read blue balance %d", *val);
225 static int ov7660_set_blue_gain(struct gspca_dev *gspca_dev, __s32 val)
229 struct sd *sd = (struct sd *) gspca_dev;
230 s32 *sensor_settings = sd->sensor_priv;
232 PDEBUG(D_V4L2, "Setting blue balance to %d", val);
234 sensor_settings[BLUE_BALANCE_IDX] = val;
236 err = m5602_write_sensor(sd, OV7660_BLUE_GAIN, &i2c_data, 1);
240 static void ov7660_dump_registers(struct sd *sd)
243 info("Dumping the ov7660 register state");
244 for (address = 0; address < 0xa9; address++) {
246 m5602_read_sensor(sd, address, &value, 1);
247 info("register 0x%x contains 0x%x",
251 info("ov7660 register state dump complete");
253 info("Probing for which registers that are read/write");
254 for (address = 0; address < 0xff; address++) {
255 u8 old_value, ctrl_value;
256 u8 test_value[2] = {0xff, 0xff};
258 m5602_read_sensor(sd, address, &old_value, 1);
259 m5602_write_sensor(sd, address, test_value, 1);
260 m5602_read_sensor(sd, address, &ctrl_value, 1);
262 if (ctrl_value == test_value[0])
263 info("register 0x%x is writeable", address);
265 info("register 0x%x is read only", address);
267 /* Restore original value */
268 m5602_write_sensor(sd, address, &old_value, 1);