1/*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 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>
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#ifndef M5602_OV9650_H_
20#define M5602_OV9650_H_
21
22#include <linux/dmi.h>
23#include "m5602_sensor.h"
24
25/*****************************************************************************/
26
27#define OV9650_GAIN			0x00
28#define OV9650_BLUE			0x01
29#define OV9650_RED			0x02
30#define OV9650_VREF			0x03
31#define OV9650_COM1			0x04
32#define OV9650_BAVE			0x05
33#define OV9650_GEAVE			0x06
34#define OV9650_RSVD7			0x07
35#define OV9650_COM2			0x09
36#define OV9650_PID			0x0a
37#define OV9650_VER			0x0b
38#define OV9650_COM3			0x0c
39#define OV9650_COM4			0x0d
40#define OV9650_COM5			0x0e
41#define OV9650_COM6			0x0f
42#define OV9650_AECH			0x10
43#define OV9650_CLKRC			0x11
44#define OV9650_COM7			0x12
45#define OV9650_COM8			0x13
46#define OV9650_COM9			0x14
47#define OV9650_COM10			0x15
48#define OV9650_RSVD16			0x16
49#define OV9650_HSTART			0x17
50#define OV9650_HSTOP			0x18
51#define OV9650_VSTRT			0x19
52#define OV9650_VSTOP			0x1a
53#define OV9650_PSHFT			0x1b
54#define OV9650_MVFP			0x1e
55#define OV9650_AEW			0x24
56#define OV9650_AEB			0x25
57#define OV9650_VPT			0x26
58#define OV9650_BBIAS			0x27
59#define OV9650_GbBIAS			0x28
60#define OV9650_Gr_COM			0x29
61#define OV9650_RBIAS			0x2c
62#define OV9650_HREF			0x32
63#define OV9650_CHLF			0x33
64#define OV9650_ARBLM			0x34
65#define OV9650_RSVD35			0x35
66#define OV9650_RSVD36			0x36
67#define OV9650_ADC			0x37
68#define OV9650_ACOM38			0x38
69#define OV9650_OFON			0x39
70#define OV9650_TSLB			0x3a
71#define OV9650_COM12			0x3c
72#define OV9650_COM13			0x3d
73#define OV9650_COM15			0x40
74#define OV9650_COM16			0x41
75#define OV9650_LCC1			0x62
76#define OV9650_LCC2			0x63
77#define OV9650_LCC3			0x64
78#define OV9650_LCC4			0x65
79#define OV9650_LCC5			0x66
80#define OV9650_HV			0x69
81#define OV9650_DBLV			0x6b
82#define OV9650_COM21			0x8b
83#define OV9650_COM22			0x8c
84#define OV9650_COM24			0x8e
85#define OV9650_DBLC1			0x8f
86#define OV9650_RSVD94			0x94
87#define OV9650_RSVD95			0x95
88#define OV9650_RSVD96			0x96
89#define OV9650_LCCFB			0x9d
90#define OV9650_LCCFR			0x9e
91#define OV9650_AECHM			0xa1
92#define OV9650_COM26			0xa5
93#define OV9650_ACOMA8			0xa8
94#define OV9650_ACOMA9			0xa9
95
96#define OV9650_REGISTER_RESET		(1 << 7)
97#define OV9650_VGA_SELECT		(1 << 6)
98#define OV9650_CIF_SELECT		(1 << 5)
99#define OV9650_QVGA_SELECT		(1 << 4)
100#define OV9650_QCIF_SELECT		(1 << 3)
101#define OV9650_RGB_SELECT		(1 << 2)
102#define OV9650_RAW_RGB_SELECT		(1 << 0)
103
104#define OV9650_FAST_AGC_AEC		(1 << 7)
105#define OV9650_AEC_UNLIM_STEP_SIZE	(1 << 6)
106#define OV9650_BANDING			(1 << 5)
107#define OV9650_AGC_EN			(1 << 2)
108#define OV9650_AWB_EN			(1 << 1)
109#define OV9650_AEC_EN			(1 << 0)
110
111#define OV9650_VARIOPIXEL		(1 << 2)
112#define OV9650_SYSTEM_CLK_SEL		(1 << 7)
113#define OV9650_SLAM_MODE		(1 << 4)
114
115#define OV9650_QVGA_VARIOPIXEL		(1 << 7)
116
117#define OV9650_VFLIP			(1 << 4)
118#define OV9650_HFLIP			(1 << 5)
119
120#define OV9650_SOFT_SLEEP		(1 << 4)
121#define OV9650_OUTPUT_DRIVE_2X		(1 << 0)
122
123#define OV9650_DENOISE_ENABLE		(1 << 5)
124#define OV9650_WHITE_PIXEL_ENABLE	(1 << 1)
125#define OV9650_WHITE_PIXEL_OPTION	(1 << 0)
126
127#define OV9650_LEFT_OFFSET		0x62
128
129#define GAIN_DEFAULT			0x14
130#define RED_GAIN_DEFAULT		0x70
131#define BLUE_GAIN_DEFAULT		0x20
132#define EXPOSURE_DEFAULT		0x1ff
133
134/*****************************************************************************/
135
136/* Kernel module parameters */
137extern int force_sensor;
138extern bool dump_sensor;
139
140int ov9650_probe(struct sd *sd);
141int ov9650_init(struct sd *sd);
142int ov9650_init_controls(struct sd *sd);
143int ov9650_start(struct sd *sd);
144int ov9650_stop(struct sd *sd);
145void ov9650_disconnect(struct sd *sd);
146
147static const struct m5602_sensor ov9650 = {
148	.name = "OV9650",
149	.i2c_slave_id = 0x60,
150	.i2c_regW = 1,
151	.probe = ov9650_probe,
152	.init = ov9650_init,
153	.init_controls = ov9650_init_controls,
154	.start = ov9650_start,
155	.stop = ov9650_stop,
156	.disconnect = ov9650_disconnect,
157};
158
159static const unsigned char preinit_ov9650[][3] = {
160	/* [INITCAM] */
161	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
162	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
163	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
164	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
165	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
166	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
167
168	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
169	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
170	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
171	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
172	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
173	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
174	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
175	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
176	/* Reset chip */
177	{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
178	/* Enable double clock */
179	{SENSOR, OV9650_CLKRC, 0x80},
180	/* Do something out of spec with the power */
181	{SENSOR, OV9650_OFON, 0x40}
182};
183
184static const unsigned char init_ov9650[][3] = {
185	/* [INITCAM] */
186	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
187	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
188	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
189	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
190	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
191	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
192
193	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
194	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
195	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
196	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
197	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
198	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
199	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
200	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
201
202	/* Reset chip */
203	{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
204	/* One extra reset is needed in order to make the sensor behave
205	   properly when resuming from ram, could be a timing issue */
206	{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
207
208	/* Enable double clock */
209	{SENSOR, OV9650_CLKRC, 0x80},
210	/* Do something out of spec with the power */
211	{SENSOR, OV9650_OFON, 0x40},
212
213	/* Set fast AGC/AEC algorithm with unlimited step size */
214	{SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
215			      OV9650_AEC_UNLIM_STEP_SIZE},
216
217	{SENSOR, OV9650_CHLF, 0x10},
218	{SENSOR, OV9650_ARBLM, 0xbf},
219	{SENSOR, OV9650_ACOM38, 0x81},
220	/* Turn off color matrix coefficient double option */
221	{SENSOR, OV9650_COM16, 0x00},
222	/* Enable color matrix for RGB/YUV, Delay Y channel,
223	set output Y/UV delay to 1 */
224	{SENSOR, OV9650_COM13, 0x19},
225	/* Enable digital BLC, Set output mode to U Y V Y */
226	{SENSOR, OV9650_TSLB, 0x0c},
227	/* Limit the AGC/AEC stable upper region */
228	{SENSOR, OV9650_COM24, 0x00},
229	/* Enable HREF and some out of spec things */
230	{SENSOR, OV9650_COM12, 0x73},
231	/* Set all DBLC offset signs to positive and
232	do some out of spec stuff */
233	{SENSOR, OV9650_DBLC1, 0xdf},
234	{SENSOR, OV9650_COM21, 0x06},
235	{SENSOR, OV9650_RSVD35, 0x91},
236	/* Necessary, no camera stream without it */
237	{SENSOR, OV9650_RSVD16, 0x06},
238	{SENSOR, OV9650_RSVD94, 0x99},
239	{SENSOR, OV9650_RSVD95, 0x99},
240	{SENSOR, OV9650_RSVD96, 0x04},
241	/* Enable full range output */
242	{SENSOR, OV9650_COM15, 0x0},
243	/* Enable HREF at optical black, enable ADBLC bias,
244	enable ADBLC, reset timings at format change */
245	{SENSOR, OV9650_COM6, 0x4b},
246	/* Subtract 32 from the B channel bias */
247	{SENSOR, OV9650_BBIAS, 0xa0},
248	/* Subtract 32 from the Gb channel bias */
249	{SENSOR, OV9650_GbBIAS, 0xa0},
250	/* Do not bypass the analog BLC and to some out of spec stuff */
251	{SENSOR, OV9650_Gr_COM, 0x00},
252	/* Subtract 32 from the R channel bias */
253	{SENSOR, OV9650_RBIAS, 0xa0},
254	/* Subtract 32 from the R channel bias */
255	{SENSOR, OV9650_RBIAS, 0x0},
256	{SENSOR, OV9650_COM26, 0x80},
257	{SENSOR, OV9650_ACOMA9, 0x98},
258	/* Set the AGC/AEC stable region upper limit */
259	{SENSOR, OV9650_AEW, 0x68},
260	/* Set the AGC/AEC stable region lower limit */
261	{SENSOR, OV9650_AEB, 0x5c},
262	/* Set the high and low limit nibbles to 3 */
263	{SENSOR, OV9650_VPT, 0xc3},
264	/* Set the Automatic Gain Ceiling (AGC) to 128x,
265	drop VSYNC at frame drop,
266	limit exposure timing,
267	drop frame when the AEC step is larger than the exposure gap */
268	{SENSOR, OV9650_COM9, 0x6e},
269	/* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
270	and set PWDN to SLVS (slave mode vertical sync) */
271	{SENSOR, OV9650_COM10, 0x42},
272	/* Set horizontal column start high to default value */
273	{SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
274	/* Set horizontal column end */
275	{SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
276	/* Complementing register to the two writes above */
277	{SENSOR, OV9650_HREF, 0xb2},
278	/* Set vertical row start high bits */
279	{SENSOR, OV9650_VSTRT, 0x02},
280	/* Set vertical row end low bits */
281	{SENSOR, OV9650_VSTOP, 0x7e},
282	/* Set complementing vertical frame control */
283	{SENSOR, OV9650_VREF, 0x10},
284	{SENSOR, OV9650_ADC, 0x04},
285	{SENSOR, OV9650_HV, 0x40},
286
287	/* Enable denoise, and white-pixel erase */
288	{SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
289		 OV9650_WHITE_PIXEL_ENABLE |
290		 OV9650_WHITE_PIXEL_OPTION},
291
292	/* Enable VARIOPIXEL */
293	{SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
294	{SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
295
296	/* Put the sensor in soft sleep mode */
297	{SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
298};
299
300static const unsigned char res_init_ov9650[][3] = {
301	{SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
302
303	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
304	{BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
305	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
306	{BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
307	{BRIDGE, M5602_XB_SIG_INI, 0x01}
308};
309#endif
310