xref: /linux/drivers/media/usb/gspca/m5602/m5602_ov7660.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Driver for the ov7660 sensor
4  *
5  * Copyright (C) 2009 Erik Andrén
6  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
7  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
8  *
9  * Portions of code to USB interface and ALi driver software,
10  * Copyright (c) 2006 Willem Duinker
11  * v4l2 interface modeled after the V4L2 driver
12  * for SN9C10x PC Camera Controllers
13  */
14 
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 
17 #include "m5602_ov7660.h"
18 
19 static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl);
20 static void ov7660_dump_registers(struct sd *sd);
21 
22 static const unsigned char preinit_ov7660[][4] = {
23 	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
24 	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
25 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
26 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
27 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
28 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
29 	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
30 	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
31 	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
32 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
33 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
34 
35 	{SENSOR, OV7660_OFON, 0x0c},
36 	{SENSOR, OV7660_COM2, 0x11},
37 	{SENSOR, OV7660_COM7, 0x05},
38 
39 	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
40 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
41 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
42 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
43 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
44 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
45 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
46 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
47 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
48 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
49 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
50 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
51 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
52 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
53 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
54 };
55 
56 static const unsigned char init_ov7660[][4] = {
57 	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
58 	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
59 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
60 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
61 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
62 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
63 	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
64 	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
65 	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
66 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
67 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
68 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
69 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
70 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
71 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
72 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
73 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
74 	{SENSOR, OV7660_COM7, 0x80},
75 	{SENSOR, OV7660_CLKRC, 0x80},
76 	{SENSOR, OV7660_COM9, 0x4c},
77 	{SENSOR, OV7660_OFON, 0x43},
78 	{SENSOR, OV7660_COM12, 0x28},
79 	{SENSOR, OV7660_COM8, 0x00},
80 	{SENSOR, OV7660_COM10, 0x40},
81 	{SENSOR, OV7660_HSTART, 0x0c},
82 	{SENSOR, OV7660_HSTOP, 0x61},
83 	{SENSOR, OV7660_HREF, 0xa4},
84 	{SENSOR, OV7660_PSHFT, 0x0b},
85 	{SENSOR, OV7660_VSTART, 0x01},
86 	{SENSOR, OV7660_VSTOP, 0x7a},
87 	{SENSOR, OV7660_VSTOP, 0x00},
88 	{SENSOR, OV7660_COM7, 0x05},
89 	{SENSOR, OV7660_COM6, 0x42},
90 	{SENSOR, OV7660_BBIAS, 0x94},
91 	{SENSOR, OV7660_GbBIAS, 0x94},
92 	{SENSOR, OV7660_RSVD29, 0x94},
93 	{SENSOR, OV7660_RBIAS, 0x94},
94 	{SENSOR, OV7660_COM1, 0x00},
95 	{SENSOR, OV7660_AECH, 0x00},
96 	{SENSOR, OV7660_AECHH, 0x00},
97 	{SENSOR, OV7660_ADC, 0x05},
98 	{SENSOR, OV7660_COM13, 0x00},
99 	{SENSOR, OV7660_RSVDA1, 0x23},
100 	{SENSOR, OV7660_TSLB, 0x0d},
101 	{SENSOR, OV7660_HV, 0x80},
102 	{SENSOR, OV7660_LCC1, 0x00},
103 	{SENSOR, OV7660_LCC2, 0x00},
104 	{SENSOR, OV7660_LCC3, 0x10},
105 	{SENSOR, OV7660_LCC4, 0x40},
106 	{SENSOR, OV7660_LCC5, 0x01},
107 
108 	{SENSOR, OV7660_AECH, 0x20},
109 	{SENSOR, OV7660_COM1, 0x00},
110 	{SENSOR, OV7660_OFON, 0x0c},
111 	{SENSOR, OV7660_COM2, 0x11},
112 	{SENSOR, OV7660_COM7, 0x05},
113 	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
114 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
115 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
116 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
117 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
118 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
119 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
120 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
121 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
122 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
123 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
124 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
125 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
126 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
127 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
128 	{SENSOR, OV7660_AECH, 0x5f},
129 	{SENSOR, OV7660_COM1, 0x03},
130 	{SENSOR, OV7660_OFON, 0x0c},
131 	{SENSOR, OV7660_COM2, 0x11},
132 	{SENSOR, OV7660_COM7, 0x05},
133 	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
134 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
135 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
136 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
137 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
138 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
139 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
140 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
141 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
142 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
143 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
144 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
145 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
146 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
147 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
148 
149 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
150 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
151 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
152 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
153 	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
154 	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
155 	{BRIDGE, M5602_XB_SIG_INI, 0x01},
156 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
157 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
158 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
159 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
160 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
161 	{BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
162 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
163 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
164 	{BRIDGE, M5602_XB_SIG_INI, 0x00},
165 	{BRIDGE, M5602_XB_SIG_INI, 0x02},
166 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
167 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x27},
168 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
169 	{BRIDGE, M5602_XB_HSYNC_PARA, 0xa7},
170 	{BRIDGE, M5602_XB_SIG_INI, 0x00},
171 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
172 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
173 };
174 
175 static struct v4l2_pix_format ov7660_modes[] = {
176 	{
177 		640,
178 		480,
179 		V4L2_PIX_FMT_SBGGR8,
180 		V4L2_FIELD_NONE,
181 		.sizeimage =
182 			640 * 480,
183 		.bytesperline = 640,
184 		.colorspace = V4L2_COLORSPACE_SRGB,
185 		.priv = 0
186 	}
187 };
188 
189 static const struct v4l2_ctrl_ops ov7660_ctrl_ops = {
190 	.s_ctrl = ov7660_s_ctrl,
191 };
192 
ov7660_probe(struct sd * sd)193 int ov7660_probe(struct sd *sd)
194 {
195 	int err = 0, i;
196 	u8 prod_id = 0, ver_id = 0;
197 
198 	if (force_sensor) {
199 		if (force_sensor == OV7660_SENSOR) {
200 			pr_info("Forcing an %s sensor\n", ov7660.name);
201 			goto sensor_found;
202 		}
203 		/* If we want to force another sensor,
204 		don't try to probe this one */
205 		return -ENODEV;
206 	}
207 
208 	/* Do the preinit */
209 	for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
210 		u8 data[2];
211 
212 		if (preinit_ov7660[i][0] == BRIDGE) {
213 			err = m5602_write_bridge(sd,
214 				preinit_ov7660[i][1],
215 				preinit_ov7660[i][2]);
216 		} else {
217 			data[0] = preinit_ov7660[i][2];
218 			err = m5602_write_sensor(sd,
219 				preinit_ov7660[i][1], data, 1);
220 		}
221 	}
222 	if (err < 0)
223 		return err;
224 
225 	if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
226 		return -ENODEV;
227 
228 	if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
229 		return -ENODEV;
230 
231 	pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
232 
233 	if ((prod_id == 0x76) && (ver_id == 0x60)) {
234 		pr_info("Detected a ov7660 sensor\n");
235 		goto sensor_found;
236 	}
237 	return -ENODEV;
238 
239 sensor_found:
240 	sd->gspca_dev.cam.cam_mode = ov7660_modes;
241 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
242 
243 	return 0;
244 }
245 
ov7660_init(struct sd * sd)246 int ov7660_init(struct sd *sd)
247 {
248 	int i, err;
249 
250 	/* Init the sensor */
251 	for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
252 		u8 data[2];
253 
254 		if (init_ov7660[i][0] == BRIDGE) {
255 			err = m5602_write_bridge(sd,
256 				init_ov7660[i][1],
257 				init_ov7660[i][2]);
258 		} else {
259 			data[0] = init_ov7660[i][2];
260 			err = m5602_write_sensor(sd,
261 				init_ov7660[i][1], data, 1);
262 		}
263 		if (err < 0)
264 			return err;
265 	}
266 
267 	if (dump_sensor)
268 		ov7660_dump_registers(sd);
269 
270 	return 0;
271 }
272 
ov7660_init_controls(struct sd * sd)273 int ov7660_init_controls(struct sd *sd)
274 {
275 	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
276 
277 	sd->gspca_dev.vdev.ctrl_handler = hdl;
278 	v4l2_ctrl_handler_init(hdl, 6);
279 
280 	v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
281 			  0, 1, 1, 1);
282 	v4l2_ctrl_new_std_menu(hdl, &ov7660_ctrl_ops,
283 			  V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
284 
285 	sd->autogain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops,
286 					 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
287 	sd->gain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_GAIN, 0,
288 				     255, 1, OV7660_DEFAULT_GAIN);
289 
290 	sd->hflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_HFLIP,
291 				      0, 1, 1, 0);
292 	sd->vflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_VFLIP,
293 				      0, 1, 1, 0);
294 
295 	if (hdl->error) {
296 		pr_err("Could not initialize controls\n");
297 		return hdl->error;
298 	}
299 
300 	v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
301 	v4l2_ctrl_cluster(2, &sd->hflip);
302 
303 	return 0;
304 }
305 
ov7660_start(struct sd * sd)306 int ov7660_start(struct sd *sd)
307 {
308 	return 0;
309 }
310 
ov7660_stop(struct sd * sd)311 int ov7660_stop(struct sd *sd)
312 {
313 	return 0;
314 }
315 
ov7660_disconnect(struct sd * sd)316 void ov7660_disconnect(struct sd *sd)
317 {
318 	ov7660_stop(sd);
319 
320 	sd->sensor = NULL;
321 }
322 
ov7660_set_gain(struct gspca_dev * gspca_dev,__s32 val)323 static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
324 {
325 	int err;
326 	u8 i2c_data = val;
327 	struct sd *sd = (struct sd *) gspca_dev;
328 
329 	gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val);
330 
331 	err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
332 	return err;
333 }
334 
ov7660_set_auto_white_balance(struct gspca_dev * gspca_dev,__s32 val)335 static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
336 					 __s32 val)
337 {
338 	int err;
339 	u8 i2c_data;
340 	struct sd *sd = (struct sd *) gspca_dev;
341 
342 	gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val);
343 
344 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
345 	if (err < 0)
346 		return err;
347 
348 	i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
349 	err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
350 
351 	return err;
352 }
353 
ov7660_set_auto_gain(struct gspca_dev * gspca_dev,__s32 val)354 static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
355 {
356 	int err;
357 	u8 i2c_data;
358 	struct sd *sd = (struct sd *) gspca_dev;
359 
360 	gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val);
361 
362 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
363 	if (err < 0)
364 		return err;
365 
366 	i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
367 
368 	return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
369 }
370 
ov7660_set_auto_exposure(struct gspca_dev * gspca_dev,__s32 val)371 static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
372 				    __s32 val)
373 {
374 	int err;
375 	u8 i2c_data;
376 	struct sd *sd = (struct sd *) gspca_dev;
377 
378 	gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val);
379 
380 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
381 	if (err < 0)
382 		return err;
383 
384 	val = (val == V4L2_EXPOSURE_AUTO);
385 	i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
386 
387 	return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
388 }
389 
ov7660_set_hvflip(struct gspca_dev * gspca_dev)390 static int ov7660_set_hvflip(struct gspca_dev *gspca_dev)
391 {
392 	int err;
393 	u8 i2c_data;
394 	struct sd *sd = (struct sd *) gspca_dev;
395 
396 	gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d, %d\n",
397 		  sd->hflip->val, sd->vflip->val);
398 
399 	i2c_data = (sd->hflip->val << 5) | (sd->vflip->val << 4);
400 
401 	err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
402 
403 	return err;
404 }
405 
ov7660_s_ctrl(struct v4l2_ctrl * ctrl)406 static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl)
407 {
408 	struct gspca_dev *gspca_dev =
409 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
410 	struct sd *sd = (struct sd *) gspca_dev;
411 	int err;
412 
413 	if (!gspca_dev->streaming)
414 		return 0;
415 
416 	switch (ctrl->id) {
417 	case V4L2_CID_AUTO_WHITE_BALANCE:
418 		err = ov7660_set_auto_white_balance(gspca_dev, ctrl->val);
419 		break;
420 	case V4L2_CID_EXPOSURE_AUTO:
421 		err = ov7660_set_auto_exposure(gspca_dev, ctrl->val);
422 		break;
423 	case V4L2_CID_AUTOGAIN:
424 		err = ov7660_set_auto_gain(gspca_dev, ctrl->val);
425 		if (err || ctrl->val)
426 			return err;
427 		err = ov7660_set_gain(gspca_dev, sd->gain->val);
428 		break;
429 	case V4L2_CID_HFLIP:
430 		err = ov7660_set_hvflip(gspca_dev);
431 		break;
432 	default:
433 		return -EINVAL;
434 	}
435 
436 	return err;
437 }
438 
ov7660_dump_registers(struct sd * sd)439 static void ov7660_dump_registers(struct sd *sd)
440 {
441 	int address;
442 	pr_info("Dumping the ov7660 register state\n");
443 	for (address = 0; address < 0xa9; address++) {
444 		u8 value;
445 		m5602_read_sensor(sd, address, &value, 1);
446 		pr_info("register 0x%x contains 0x%x\n", address, value);
447 	}
448 
449 	pr_info("ov7660 register state dump complete\n");
450 
451 	pr_info("Probing for which registers that are read/write\n");
452 	for (address = 0; address < 0xff; address++) {
453 		u8 old_value, ctrl_value;
454 		u8 test_value[2] = {0xff, 0xff};
455 
456 		m5602_read_sensor(sd, address, &old_value, 1);
457 		m5602_write_sensor(sd, address, test_value, 1);
458 		m5602_read_sensor(sd, address, &ctrl_value, 1);
459 
460 		if (ctrl_value == test_value[0])
461 			pr_info("register 0x%x is writeable\n", address);
462 		else
463 			pr_info("register 0x%x is read only\n", address);
464 
465 		/* Restore original value */
466 		m5602_write_sensor(sd, address, &old_value, 1);
467 	}
468 }
469