1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for the ov7660 sensor
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>
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
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 #include "m5602_ov7660.h"
19 static int ov7660_s_ctrl(struct v4l2_ctrl
*ctrl
);
20 static void ov7660_dump_registers(struct sd
*sd
);
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},
35 {SENSOR
, OV7660_OFON
, 0x0c},
36 {SENSOR
, OV7660_COM2
, 0x11},
37 {SENSOR
, OV7660_COM7
, 0x05},
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}
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},
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},
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},
175 static struct v4l2_pix_format ov7660_modes
[] = {
184 .colorspace
= V4L2_COLORSPACE_SRGB
,
189 static const struct v4l2_ctrl_ops ov7660_ctrl_ops
= {
190 .s_ctrl
= ov7660_s_ctrl
,
193 int ov7660_probe(struct sd
*sd
)
196 u8 prod_id
= 0, ver_id
= 0;
199 if (force_sensor
== OV7660_SENSOR
) {
200 pr_info("Forcing an %s sensor\n", ov7660
.name
);
203 /* If we want to force another sensor,
204 don't try to probe this one */
209 for (i
= 0; i
< ARRAY_SIZE(preinit_ov7660
) && !err
; i
++) {
212 if (preinit_ov7660
[i
][0] == BRIDGE
) {
213 err
= m5602_write_bridge(sd
,
214 preinit_ov7660
[i
][1],
215 preinit_ov7660
[i
][2]);
217 data
[0] = preinit_ov7660
[i
][2];
218 err
= m5602_write_sensor(sd
,
219 preinit_ov7660
[i
][1], data
, 1);
225 if (m5602_read_sensor(sd
, OV7660_PID
, &prod_id
, 1))
228 if (m5602_read_sensor(sd
, OV7660_VER
, &ver_id
, 1))
231 pr_info("Sensor reported 0x%x%x\n", prod_id
, ver_id
);
233 if ((prod_id
== 0x76) && (ver_id
== 0x60)) {
234 pr_info("Detected a ov7660 sensor\n");
240 sd
->gspca_dev
.cam
.cam_mode
= ov7660_modes
;
241 sd
->gspca_dev
.cam
.nmodes
= ARRAY_SIZE(ov7660_modes
);
246 int ov7660_init(struct sd
*sd
)
250 /* Init the sensor */
251 for (i
= 0; i
< ARRAY_SIZE(init_ov7660
); i
++) {
254 if (init_ov7660
[i
][0] == BRIDGE
) {
255 err
= m5602_write_bridge(sd
,
259 data
[0] = init_ov7660
[i
][2];
260 err
= m5602_write_sensor(sd
,
261 init_ov7660
[i
][1], data
, 1);
268 ov7660_dump_registers(sd
);
273 int ov7660_init_controls(struct sd
*sd
)
275 struct v4l2_ctrl_handler
*hdl
= &sd
->gspca_dev
.ctrl_handler
;
277 sd
->gspca_dev
.vdev
.ctrl_handler
= hdl
;
278 v4l2_ctrl_handler_init(hdl
, 6);
280 v4l2_ctrl_new_std(hdl
, &ov7660_ctrl_ops
, V4L2_CID_AUTO_WHITE_BALANCE
,
282 v4l2_ctrl_new_std_menu(hdl
, &ov7660_ctrl_ops
,
283 V4L2_CID_EXPOSURE_AUTO
, 1, 0, V4L2_EXPOSURE_AUTO
);
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
);
290 sd
->hflip
= v4l2_ctrl_new_std(hdl
, &ov7660_ctrl_ops
, V4L2_CID_HFLIP
,
292 sd
->vflip
= v4l2_ctrl_new_std(hdl
, &ov7660_ctrl_ops
, V4L2_CID_VFLIP
,
296 pr_err("Could not initialize controls\n");
300 v4l2_ctrl_auto_cluster(2, &sd
->autogain
, 0, false);
301 v4l2_ctrl_cluster(2, &sd
->hflip
);
306 int ov7660_start(struct sd
*sd
)
311 int ov7660_stop(struct sd
*sd
)
316 void ov7660_disconnect(struct sd
*sd
)
323 static int ov7660_set_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
327 struct sd
*sd
= (struct sd
*) gspca_dev
;
329 gspca_dbg(gspca_dev
, D_CONF
, "Setting gain to %d\n", val
);
331 err
= m5602_write_sensor(sd
, OV7660_GAIN
, &i2c_data
, 1);
335 static int ov7660_set_auto_white_balance(struct gspca_dev
*gspca_dev
,
340 struct sd
*sd
= (struct sd
*) gspca_dev
;
342 gspca_dbg(gspca_dev
, D_CONF
, "Set auto white balance to %d\n", val
);
344 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
348 i2c_data
= ((i2c_data
& 0xfd) | ((val
& 0x01) << 1));
349 err
= m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
354 static int ov7660_set_auto_gain(struct gspca_dev
*gspca_dev
, __s32 val
)
358 struct sd
*sd
= (struct sd
*) gspca_dev
;
360 gspca_dbg(gspca_dev
, D_CONF
, "Set auto gain control to %d\n", val
);
362 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
366 i2c_data
= ((i2c_data
& 0xfb) | ((val
& 0x01) << 2));
368 return m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
371 static int ov7660_set_auto_exposure(struct gspca_dev
*gspca_dev
,
376 struct sd
*sd
= (struct sd
*) gspca_dev
;
378 gspca_dbg(gspca_dev
, D_CONF
, "Set auto exposure control to %d\n", val
);
380 err
= m5602_read_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
384 val
= (val
== V4L2_EXPOSURE_AUTO
);
385 i2c_data
= ((i2c_data
& 0xfe) | ((val
& 0x01) << 0));
387 return m5602_write_sensor(sd
, OV7660_COM8
, &i2c_data
, 1);
390 static int ov7660_set_hvflip(struct gspca_dev
*gspca_dev
)
394 struct sd
*sd
= (struct sd
*) gspca_dev
;
396 gspca_dbg(gspca_dev
, D_CONF
, "Set hvflip to %d, %d\n",
397 sd
->hflip
->val
, sd
->vflip
->val
);
399 i2c_data
= (sd
->hflip
->val
<< 5) | (sd
->vflip
->val
<< 4);
401 err
= m5602_write_sensor(sd
, OV7660_MVFP
, &i2c_data
, 1);
406 static int ov7660_s_ctrl(struct v4l2_ctrl
*ctrl
)
408 struct gspca_dev
*gspca_dev
=
409 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
410 struct sd
*sd
= (struct sd
*) gspca_dev
;
413 if (!gspca_dev
->streaming
)
417 case V4L2_CID_AUTO_WHITE_BALANCE
:
418 err
= ov7660_set_auto_white_balance(gspca_dev
, ctrl
->val
);
420 case V4L2_CID_EXPOSURE_AUTO
:
421 err
= ov7660_set_auto_exposure(gspca_dev
, ctrl
->val
);
423 case V4L2_CID_AUTOGAIN
:
424 err
= ov7660_set_auto_gain(gspca_dev
, ctrl
->val
);
425 if (err
|| ctrl
->val
)
427 err
= ov7660_set_gain(gspca_dev
, sd
->gain
->val
);
430 err
= ov7660_set_hvflip(gspca_dev
);
439 static void ov7660_dump_registers(struct sd
*sd
)
442 pr_info("Dumping the ov7660 register state\n");
443 for (address
= 0; address
< 0xa9; address
++) {
445 m5602_read_sensor(sd
, address
, &value
, 1);
446 pr_info("register 0x%x contains 0x%x\n", address
, value
);
449 pr_info("ov7660 register state dump complete\n");
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};
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);
460 if (ctrl_value
== test_value
[0])
461 pr_info("register 0x%x is writeable\n", address
);
463 pr_info("register 0x%x is read only\n", address
);
465 /* Restore original value */
466 m5602_write_sensor(sd
, address
, &old_value
, 1);