Fix SXGA support to enforce bayer format
[microdia.git] / omnivision.c
blobc625e669b1a00d922a022c173ca91f512ef64e39
1 /**
2 * @file omnivision.c
3 * @date 2008-10-27
5 * @brief Common control functions for Omnivision Image Sensors.
7 * @par Licences
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "sn9c20x.h"
25 #include "sn9c20x-bridge.h"
26 #include "omnivision.h"
28 struct sn9c20x_i2c_regs ov7660_init[] = {
29 /* System CLK selection, to get a higher Frame Rate */
30 {OV7660_CTL_COM5, 0x80},
31 /* OV7660 Wakeup */
32 /* COM4 is Reserved : using default value 0x40 OR windows driver value 0x08 */
33 {OV7660_CTL_COM4, 0x08},
34 /* Enable HREF at optical black, Use optical black line as BLC signal
35 Reset all timing when format changes, Enable ADBLC option */
36 {OV7660_CTL_COM6, 0xc3},
37 /* windows 0x00, default 0x00, trying 0x60 to enable CCIR656 format */
38 {OV7660_CTL_COM1, 0xc3},
39 /* default is 0x40, windows sets it to 0x00 */
40 {OV7660_CTL_AECH, 0x40},
41 /* default is 0x00, windows sets it to 0x40 */
42 {OV7660_CTL_CLKRC, 0x40},
43 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
44 {OV7660_CTL_COM7, 0x05},
45 /* default is 0x8f, windows used 0xf8 */
46 /* Enable fast AGC/AEC algorithm, AEC - Step size limit = 1/16 x AEC */
47 /* Banding & Reserved are disabled. AGC, AEC enabled, 0x85 */
48 {OV7660_CTL_COM8, 0xba},
49 /* video appears jagged w/o these ADC writes */
50 {OV7660_CTL_ADC, 0x0f},
51 {OV7660_CTL_ACOM, 0x02},
52 {OV7660_CTL_OFON, 0x43},
53 /* video appears jagged w/o this write */
54 /* Default 0x0c sets format to uYvY, Windows driver 0x00 sets format to YuYv */
55 {OV7660_CTL_TSLB, 0x00},
56 /* Not doing this write makes the video look green */
57 /* Manual Banding Filter MSB , set B & R channel pre-gain */
58 {OV7660_CTL_HV, 0x90},
59 /* No video stream w/o these ADVFL/ADVFH write totally black */
60 {OV7660_CTL_ADVFL, 0xf6},
61 {OV7660_CTL_ADVFH, 0x0b},
62 /* Setting BLUE to 0x78; RED to 0x78 to get natural colors in artificial light */
63 {OV7660_CTL_BLUE, 0x78},
64 /* Setting RED to 0x50 to get natural colors in natural light */
65 {OV7660_CTL_RED, 0x50},
66 {0xff, 0xff},
69 struct sn9c20x_i2c_regs ov7670_init[] = {
70 /* Phase 1 */
71 {OV7670_CTL_COM7, 0x80},
72 {OV7670_CTL_CLKRC, 0x80},
73 {OV7670_CTL_TSLB, 0x04},
74 {OV7670_CTL_COM7, 0x01},
75 {OV7670_CTL_HREF, 0xb6},
76 {OV7670_CTL_VREF, 0x0a},
77 {OV7670_CTL_COM3, 0x00},
78 {OV7670_CTL_COM14, 0x00},
79 {OV7670_CTL_SCALING_XSC, 0x3a},
80 {OV7670_CTL_SCALING_YSC, 0x35},
81 {OV7670_CTL_SCALING_DCWCTR, 0x11},
82 {OV7670_CTL_SCALING_PCLK_DIV, 0xf0},
83 {OV7670_CTL_SCALING_PCLK_DELAY, 0x02},
84 {OV7670_CTL_COM8, 0xe0},
85 {OV7670_CTL_GAIN, 0x00},
86 {OV7670_CTL_AECH, 0x00},
87 {OV7670_CTL_COM4, 0x40},
88 {OV7670_CTL_COM9, 0x08},
89 {OV7670_CTL_BD50MAX, 0x05},
90 {OV7670_CTL_BD60MAX, 0x07},
91 {OV7670_CTL_AEW, 0x95},
92 {OV7670_CTL_AEB, 0x33},
93 {OV7670_CTL_VPT, 0xe3},
94 {OV7670_CTL_HAECC1, 0x75},
95 {OV7670_CTL_HAECC2, 0x65},
96 {0xa1, 0x0b},
97 {OV7670_CTL_HAECC3, 0xd8},
98 {OV7670_CTL_HAECC4, 0xd8},
99 {OV7670_CTL_HAECC5, 0xf0},
100 {OV7670_CTL_HAECC6, 0x90},
101 {OV7670_CTL_HAECC7, 0x94},
102 {OV7670_CTL_COM8, 0xe5},
103 {OV7670_CTL_COM5, 0x61},
104 {OV7670_CTL_COM6, 0x4b},
105 {0x16, 0x02},
106 {OV7670_CTL_MVFP, 0x27},
107 {OV7670_CTL_ADCCTR1, 0x02},
108 {OV7670_CTL_ADCCTR2, 0x91},
109 {0x29, 0x07},
110 {OV7670_CTL_CHLF, 0x0b},
111 {0x35, 0x0b},
112 {OV7670_CTL_ADC, 0x1d},
113 {OV7670_CTL_ACOM, 0x71},
114 {OV7670_CTL_OFON, 0x2a},
115 {OV7670_CTL_COM12, 0x78},
116 {0x4d, 0x40},
117 {0x4e, 0x20},
118 {OV7670_CTL_GFIX, 0x00},
119 {OV7670_CTL_REG74, 0x19},
120 {0x8d, 0x4f},
121 {0x8e, 0x00},
122 {0x8f, 0x00},
123 {0x90, 0x00},
124 {0x91, 0x00},
125 {0x96, 0x00},
126 {0x9a, 0x80},
127 {0xb0, 0x84},
128 {OV7670_CTL_ABLC1, 0x0c},
129 {0xb2, 0x0e},
130 {OV7670_CTL_THL_ST, 0x82},
131 {0xb8, 0x0a},
132 {OV7670_CTL_AWBC1, 0x0a},
133 {OV7670_CTL_AWBC2, 0xf0},
134 {OV7670_CTL_AWBC3, 0x20},
135 {OV7670_CTL_AWBC4, 0x7d},
136 {OV7670_CTL_AWBC5, 0x29},
137 {OV7670_CTL_AWBC6, 0x4a},
138 {0x59, 0x8c},
139 {0x5a, 0xa5},
140 {0x5b, 0xde},
141 {0x5c, 0x96},
142 {0x5d, 0x66},
143 {0x5e, 0x10},
144 {OV7670_CTL_AWBCTR3, 0x0a},
145 {OV7670_CTL_AWBCTR2, 0x55},
146 {OV7670_CTL_AWBCTR1, 0x11},
147 {OV7670_CTL_AWBCTR0, 0x9e},
148 {OV7670_CTL_GGAIN, 0x40},
149 {OV7670_CTL_BLUE, 0x40},
150 {OV7670_CTL_RED, 0x40},
151 {OV7670_CTL_COM8, 0xe7},
152 {OV7670_CTL_MTX1, 0x6e},
153 {OV7670_CTL_MTX2, 0x70},
154 {OV7670_CTL_MTX3, 0x02},
155 {OV7670_CTL_MTX4, 0x1d},
156 {OV7670_CTL_MTX5, 0x56},
157 {OV7670_CTL_MTX6, 0x73},
158 {OV7670_CTL_BRIGHT, 0x0a},
159 {OV7670_CTL_CONTRAS, 0x55},
160 {OV7670_CTL_CONTRAS_CENTER, 0x80},
161 {OV7670_CTL_MTXS, 0x9e},
162 {OV7670_CTL_COM16, 0x08},
163 {OV7670_CTL_EDGE, 0x02},
164 {OV7670_CTL_REG75, 0x03},
165 {OV7670_CTL_REG76, 0x63},
166 {OV7670_CTL_DNSTH, 0x04},
167 {OV7670_CTL_REG77, 0x06},
168 {OV7670_CTL_COM13, 0x02},
169 {OV7670_CTL_REG4B, 0x09},
170 {OV7670_CTL_SATCTR, 0x30},
171 {OV7670_CTL_COM16, 0x08},
172 {OV7670_CTL_CONTRAS, 0x48},
173 {OV7670_CTL_ARBLM, 0x11},
174 {OV7670_CTL_NT_CTRL, 0x88},
175 {0x96, 0x00},
176 {0x97, 0x30},
177 {0x98, 0x20},
178 {0x99, 0x30},
179 {0x9a, 0x84},
180 {0x9b, 0x29},
181 {0x9c, 0x03},
182 {OV7670_CTL_BD50ST, 0x99},
183 {OV7670_CTL_BD60ST, 0x7f},
184 {0x78, 0x04},
185 {0x79, 0x01},
186 {0xc8, 0xf0},
187 {0x79, 0x0f},
188 {0xc8, 0x00},
189 {0x79, 0x10},
190 {0xc8, 0x7e},
191 {0x79, 0x0a},
192 {0xc8, 0x80},
193 {0x79, 0x0b},
194 {0xc8, 0x01},
195 {0x79, 0x0c},
196 {0xc8, 0x0f},
197 {0x79, 0x0d},
198 {0xc8, 0x20},
199 {0x79, 0x09},
200 {0xc8, 0x80},
201 {0x79, 0x02},
202 {0xc8, 0xc0},
203 {0x79, 0x03},
204 {0xc8, 0x40},
205 {0x79, 0x05},
206 {0xc8, 0x30},
207 {0x79, 0x26},
208 {OV7670_CTL_LCC1, 0x20},
209 {OV7670_CTL_LCC2, 0x00},
210 {OV7670_CTL_LCC3, 0x06},
211 {OV7670_CTL_LCC4, 0x00},
212 {OV7670_CTL_LCC5, 0x05},
213 {OV7670_CTL_LCC6, 0x05},
214 {OV7670_CTL_LCC7, 0x0a},
215 {OV7670_CTL_HSTART, 0x13},
216 {OV7670_CTL_HSTOP, 0x01},
217 {OV7670_CTL_VSTRT, 0x02},
218 {OV7670_CTL_VSTOP, 0x7a},
219 {OV7670_CTL_AWBC4, 0x59},
220 {OV7670_CTL_AWBC5, 0x30},
221 {OV7670_CTL_MTXS, 0x9a},
222 {0x59, 0x84},
223 {0x5a, 0x91},
224 {0x5b, 0x57},
225 {0x5c, 0x75},
226 {0x5d, 0x6d},
227 {0x5e, 0x13},
228 {OV7670_CTL_LCC3, 0x07},
229 {OV7670_CTL_LCC6, 0x07},
230 {OV7670_CTL_LCC7, 0x0d},
231 {OV7670_CTL_HAECC3, 0xdf},
232 {OV7670_CTL_HAECC4, 0xdf},
233 {OV7670_CTL_AWBC6, 0x4d},
234 {OV7670_CTL_MTX3, 0x00},
235 /* Phase 2 */
236 {OV7670_CTL_DBLV, 0x0a},
237 {OV7670_CTL_CLKRC, 0x80},
238 {OV7670_CTL_EXHCH, 0x00},
239 {OV7670_CTL_EXHCL, 0x00},
240 {OV7670_CTL_DM_LNL, 0x00},
241 {OV7670_CTL_DM_LNH, 0x00},
242 {OV7670_CTL_BRIGHT, 0x0a},
243 {OV7670_CTL_CONTRAS, 0x60},
244 {OV7670_CTL_MTX1, 0x6e},
245 {OV7670_CTL_MTX1 + 1, 0x70},
246 {OV7670_CTL_MTX1 + 2, 0x00},
247 {OV7670_CTL_MTX1 + 3, 0x1d},
248 {OV7670_CTL_MTX5, 0x56},
249 {OV7670_CTL_MTX5 + 1, 0x73},
250 {OV7670_CTL_MTXS, 0x9a},
251 {OV7670_CTL_MTX1, 0x6e},
252 {OV7670_CTL_MTX1 + 1, 0x70},
253 {OV7670_CTL_MTX1 + 2, 0x00},
254 {OV7670_CTL_MTX1 + 3, 0x1d},
255 {OV7670_CTL_MTX5, 0x56},
256 {OV7670_CTL_MTX5 + 1, 0x73},
257 {OV7670_CTL_MTXS, 0x9a},
258 {OV7670_CTL_EDGE, 0x01},
259 {OV7670_CTL_GAM1, 0x03},
260 {OV7670_CTL_GAM1 + 1, 0x09},
261 {OV7670_CTL_GAM1 + 2, 0x16},
262 {OV7670_CTL_GAM1 + 3, 0x38},
263 {OV7670_CTL_GAM5, 0x47},
264 {OV7670_CTL_GAM5 + 1, 0x53},
265 {OV7670_CTL_GAM5 + 2, 0x5e},
266 {OV7670_CTL_GAM5 + 3, 0x6a},
267 {OV7670_CTL_GAM9, 0x74},
268 {OV7670_CTL_GAM9 + 1, 0x80},
269 {OV7670_CTL_GAM9 + 2, 0x8c},
270 {OV7670_CTL_GAM9 + 3, 0x9b},
271 {OV7670_CTL_GAM13, 0xb2},
272 {OV7670_CTL_GAM13 + 1, 0xcc},
273 {OV7670_CTL_GAM13 + 2, 0xe5},
274 {OV7670_CTL_SLOP, 0x24},
275 {OV7670_CTL_COM11, 0x00},
276 {OV7670_CTL_HAECC1, 0x76},
277 {OV7670_CTL_HAECC1 + 1, 0x65},
278 {OV7670_CTL_COM8, 0xe2},
279 /* Phase 3 */
280 {OV7670_CTL_DBLV, 0x0a},
281 {OV7670_CTL_CLKRC, 0x80},
282 {OV7670_CTL_EXHCH, 0x00},
283 {OV7670_CTL_EXHCL, 0x00},
284 {OV7670_CTL_DM_LNL, 0x00},
285 {OV7670_CTL_DM_LNH, 0x00},
286 {0xff, 0xff},
290 * @var ov9650_init
291 * @brief Addresses and values for the initialization of ov965x sensors
294 struct sn9c20x_i2c_regs ov9650_init[] = {
295 {OV965X_CTL_COM7, OV965X_COM7_SCCB_RESET},
296 {OV965X_CTL_GAIN, 0x00},
297 {OV965X_CTL_BLUE, 0x78},
298 {OV965X_CTL_RED, 0x78},
299 {OV965X_CTL_VREF, OV965X_VREF_VSTOP_LOW3(0x06) |
300 OV965X_VREF_VSTART_LOW3(0x06)},
301 {OV965X_CTL_COM1, 0x03},
302 {OV965X_CTL_BAVE, 0x00}, /* default */
303 {OV965X_CTL_GEAVE, 0x00}, /* default */
304 {OV965X_CTL_RAVE, 0x00}, /* default */
305 {OV965X_CTL_COM2, OV965X_COM2_OUTPUT_DRIVE_CAP_2X},
306 {OV965X_CTL_COM3, 0x00},
307 {OV965X_CTL_COM4, 0x00},
308 {OV965X_CTL_COM5, OV965X_COM5_15FPS_48MHZ_RGB | 0x20},
309 {OV965X_CTL_COM6, OV965X_COM6_TIMING_RESET_ON_FMT_CHANGE | 0x50},
310 {OV965X_CTL_AECH, 0x7c},
311 {OV965X_CTL_CLKRC, OV965X_CLKRC_DBL_CLK_ENABLE},
312 {OV965X_CTL_COM7, OV965X_COM7_OUTPUT_VGA | OV965X_COM7_OUTPUT_RAW_RGB},
313 {OV965X_CTL_COM8, OV965X_COM8_FAST_AGC_AEC |
314 OV965X_COM8_AEC_STEP_SIZE_NOLIMIT |
315 OV965X_COM8_AWB_ENABLE},
316 {OV965X_CTL_COM9, OV965X_COM9_MAX_AGC_4X |
317 OV965X_COM9_RELAX_EXPOSURE_TIMING |
318 OV965X_COM9_DROP_VSYNC_ON_FRAME_DROP |
319 OV965X_COM9_DROP_FRAME_ON_BIG_AEC},
320 {OV965X_CTL_COM10, 0x00},
321 {0x16, 0x07}, /* reserved */
322 {OV965X_CTL_HSTART, 0x24},
323 {OV965X_CTL_HSTOP, 0xc5},
324 {OV965X_CTL_VSTRT, 0x00},
325 {OV965X_CTL_VSTOP, 0x3c},
326 {OV965X_CTL_PSHIFT, 0x00}, /* default */
327 {OV965X_CTL_MVFP, 0x04},
328 {OV965X_CTL_LAEC, 0x00}, /* reserved */
329 {OV965X_CTL_AEW, 0x78}, /* default */
330 {OV965X_CTL_AEB, 0x68}, /* default */
331 {OV965X_CTL_VPT, 0xd4}, /* default */
332 {OV965X_CTL_BBIAS, OV965X_BIAS_SUBTRACT}, /* default */
333 {OV965X_CTL_GbBIAS, OV965X_BIAS_SUBTRACT}, /* default */
334 {OV965X_CTL_Gr_COM, OV965X_Gr_COM_BYPASS_ANALOG_BLC |
335 OV965X_Gr_COM_BYPASS_REGULATOR},
336 {OV965X_CTL_EXHCH, 0x00}, /* default */
337 {OV965X_CTL_EXHCL, 0x00}, /* default */
338 {OV965X_CTL_RBIAS, OV965X_BIAS_SUBTRACT}, /* default */
339 {OV965X_CTL_ADVFL, 0x00}, /* default */
340 {OV965X_CTL_ADVFH, 0x00}, /* default */
341 {OV965X_CTL_YAVE, 0x00}, /* default */
342 {OV965X_CTL_HSYST, 0x08}, /* default */
343 {OV965X_CTL_HSYEN, 0x30}, /* default */
344 {OV965X_CTL_HREF, OV965X_HREF_EDGE_OFT_TO_DATA_OUT(2) |
345 OV965X_HREF_HSTOP_LOW3(0) |
346 OV965X_HREF_HSTART_LOW3(4)},
347 {OV965X_CTL_CHLF, 0xe2}, /* reserved */
348 {OV965X_CTL_ARBLM, 0xbf}, /* reserved */
349 {0x35, 0x81}, /* reserved */
350 {0x36, 0xf9}, /* reserved */
351 {OV965X_CTL_ADC, 0x00}, /* reserved */
352 {OV965X_CTL_ACOM, 0x93}, /* reserved */
353 {OV965X_CTL_OFON, 0x50},
354 {OV965X_CTL_TSLB, OV965X_TSLB_DIGITAL_BLC_ENABLE},
355 {OV965X_CTL_COM11, OV965X_COM11_MANUAL_BANDING_FILTER},
356 {OV965X_CTL_COM12, 0x73},
357 {OV965X_CTL_COM13, OV965X_COM13_ENABLE_COLOR_MATRIX |
358 OV965X_COM13_DELAY_Y_CHANNEL |
359 OV965X_COM13_OUTPUT_DELAY(1)},
360 {OV965X_CTL_COM14, OV965X_COM14_YUV_EDGE_ENHANCE |
361 OV965X_COM14_EDGE_ENHANCE_FACTOR_DBL | 0x0b},
362 {OV965X_CTL_EDGE, OV965X_EDGE_EDGE_ENHANCE_LOW4(8) |
363 OV965X_EDGE_EDGE_ENHANCE_FACTOR(8)},
364 {OV965X_CTL_COM15, OV965X_COM15_OUTPUT_RANGE_O0_TO_FF | 0x01},
365 {OV965X_CTL_COM16, 0x00},
366 {OV965X_CTL_COM17, 0x08},
367 {OV965X_CTL_MANU, 0x80}, /* default */
368 {OV965X_CTL_MANV, 0x80}, /* default */
369 {OV965X_CTL_HV, 0x40},
370 {OV965X_CTL_MBD, 0x00}, /* default */
371 {OV965X_CTL_DBLV, 0x0a}, /* reserved */
372 {OV965X_CTL_COM21, 0x06}, /* reserved */
373 {OV965X_CTL_COM22, 0x20},
374 {OV965X_CTL_COM23, 0x00}, /* default */
375 {OV965X_CTL_COM24, 0x00}, /* reserved */
376 {OV965X_CTL_DBLC1, 0xdf},
377 {OV965X_CTL_DM_LNL, 0x00}, /* default */
378 {OV965X_CTL_DM_LNH, 0x00}, /* default */
379 {0x94, 0x88}, /* reserved */
380 {0x95, 0x88}, /* reserved */
381 {0x96, 0x04}, /* reserved */
382 {OV965X_CTL_AECHM, 0x00},
383 {OV965X_CTL_COM26, 0x80}, /* reserved */
384 {0xa8, 0x80}, /* reserved */
385 {0xa9, 0xb8}, /* reserved */
386 {0xaa, 0x92}, /* reserved */
387 {0xab, 0x0a}, /* reserved */
388 {0xff, 0xff},
392 * @var soi968_init
393 * @brief Addresses and values for the initialization of SOI968 sensors
394 * @author Josua Grawitter
397 struct sn9c20x_i2c_regs soi968_init[] = {
398 /* reset all registers */
399 {0x12, 0x80},
400 /* stop resetting */
401 {0x12, 0x00},
402 /* snapshot mode: off */
403 {0x0c, 0x00},
404 /* enable offset adjustment,
405 * full data range,
406 * analogue2digital control black-level calibration
408 {0x0f, 0x1f},
409 /* Clock: internal PLL on */
410 {0x11, 0x80},
411 /* Analoge Black-level calibration off , no anaolgue gain */
412 {0x38, 0x52},
413 /* reserved */
414 {0x1e, 0x00},
415 /* special system settings (voltage, analogue2digital, ...) */
416 {0x33, 0x08},
417 {0x35, 0x8c},
418 {0x36, 0x0c},
419 {0x37, 0x04},
420 /* next 7 are unknown/reserved */
421 {0x45, 0x04},
422 {0x47, 0xff},
423 {0x3e, 0x00},
424 {0x3f, 0x00},
425 {0x3b, 0x20},
426 {0x3a, 0x96},
427 {0x3d, 0x0a},
428 /* disable banding filter in dark environment,
429 * VSYNC is dropped when framerate is dropped,
430 * drop frmaes when exposure out of tolerance,
431 * unfreeze exposure and gain values
433 {0x14, 0x4e},
434 /* AEC, AGC, AWB disabled; fast AEC */
435 {0x13, 0x8a},
436 /* output: VGA, master mode */
437 {0x12, 0x40},
438 /* set HSTART, HSTOP, VSTART and VSTOP */
439 {0x17, 0x13},
440 {0x18, 0x63},
441 {0x19, 0x01},
442 {0x1a, 0x79},
443 {0x32, 0x24}, /* LSB for all four */
444 /* AWB update threshold,
445 * blue and red gain LSB
447 {0x03, 0x00},
448 /* CLock: internal PLL off */
449 {0x11, 0x40},
450 /* Line interval adjustment */
451 {0x2a, 0x10},
452 {0x2b, 0xe0},
453 /* AEC MSB */
454 {0x10, 0x32},
455 /* gain - default*/
456 {0x00, 0x00},
457 /* blue and red gain - default*/
458 {0x01, 0x80},
459 {0x02, 0x80},
460 {0xff, 0xff},
463 struct sn9c20x_i2c_regs ov9655_init[] = {
464 {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
465 {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x3e}, {0x16, 0x24},
466 {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
467 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf},
468 {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12},
469 {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c},
470 {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40},
471 {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a},
472 {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc},
473 {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04},
474 {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02},
475 {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c},
476 {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60},
477 {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04},
478 {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80},
479 {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf},
480 {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b},
481 {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01},
482 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
483 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61},
484 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
485 {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01},
486 {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10},
487 {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04},
488 {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00},
489 {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80},
490 {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d},
491 {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14},
492 {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf},
493 {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00},
494 {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00},
495 {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03},
496 {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03},
497 {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
498 {0xff, 0xff},
502 * @brief OV7670 Auto-Flip
504 * @param dev Pointer to the device
505 * @param vflip Flag to indicate whether or not Camera is currently flipped
507 * @return Zero (success) or negative (USB-error value)
510 int ov7670_auto_flip(struct usb_sn9c20x *dev, __u8 vflip)
512 int ret;
513 __u8 buf[2];
515 ret = sn9c20x_read_i2c_data(dev, 1,
516 OV7670_CTL_MVFP, buf);
517 if (ret < 0)
518 return ret;
520 if (vflip == 0)
521 buf[0] = buf[0] & (0xff ^ OV7670_VFLIP_BIT);
522 else
523 buf[0] = buf[0] | OV7670_VFLIP_BIT;
524 ret = sn9c20x_write_i2c_data(dev, 1,
525 OV7670_CTL_MVFP, buf);
527 return ret;
530 void ov965x_set_sxga_mode(struct usb_sn9c20x *dev, bool sxga)
532 __u8 value;
533 __u8 sxga_hstart[4] = {0x1b, 0xbc, 0x01, 0x82};
534 __u8 vga_hstart[4] = {0x24, 0xC5, 0x00, 0x3C};
536 if (sxga) {
537 sn9c20x_write_i2c_data(dev, 4, 0x17, sxga_hstart);
538 sn9c20x_read_i2c_data(dev, 1, 0x12, &value);
539 value = value & 0x7;
540 sn9c20x_write_i2c_data(dev, 1, 0x12, &value);
541 } else {
542 sn9c20x_write_i2c_data(dev, 4, 0x17, vga_hstart);
543 sn9c20x_read_i2c_data(dev, 1, 0x12, &value);
544 value = (value & 0x7) | 0x40;
545 sn9c20x_write_i2c_data(dev, 1, 0x12, &value);
550 * @brief Set hflip and vflip in ov965x sensors
552 * @param dev Pointer to device structure
554 * @returns 0 or negative error code
557 int ov965x_set_hvflip(struct usb_sn9c20x *dev)
559 int ret;
560 __u8 value;
561 __u8 tslb;
562 ret = sn9c20x_read_i2c_data(dev, 1, OV965X_CTL_MVFP, &value);
563 if (ret < 0)
564 return ret;
566 if (dev->vsettings.hflip)
567 value |= OV965X_MVFP_MIRROR;
568 else
569 value &= ~OV965X_MVFP_MIRROR;
571 if (dev->vsettings.vflip) {
572 value |= OV965X_MVFP_VFLIP;
573 tslb = 0x49;
574 } else {
575 value &= ~OV965X_MVFP_VFLIP;
576 tslb = 0x01;
579 ret = sn9c20x_write_i2c_data(dev, 1, OV965X_CTL_MVFP, &value);
580 ret = sn9c20x_write_i2c_data(dev, 1, OV965X_CTL_TSLB, &tslb);
582 return ret;
586 * @brief Set exposure for omnivision sensors
588 * @param dev
590 * @returns 0 or negative error value
592 * The used registers do not show up the datasheets.
595 int ov_set_exposure(struct usb_sn9c20x *dev)
597 int ret = 0;
598 __u8 val[2] = {(dev->vsettings.exposure & 0x0F) << 4,
599 dev->vsettings.exposure >> 4};
601 ret = sn9c20x_write_i2c_data_ext(dev, 2, 0x2d, val, 0x1e);
603 return ret;
607 * @brief Set autoexposure for omnivision sensors
609 * @param dev
611 * @returns 0 or negative error value
613 * @author Josua Grawitter
615 * For SOI968 sensor.
617 int soi968_set_autoexposure(struct usb_sn9c20x *dev)
619 __u8 buf[1];
620 int ret = 0;
622 ret = sn9c20x_read_i2c_data(dev, 1, 0x13, buf);
623 if (ret < 0)
624 return ret;
626 if (dev->vsettings.auto_exposure) {
627 buf[0] |= 0x01;
628 } else {
629 buf[0] &= ~0x01;
632 ret = sn9c20x_write_i2c_data(dev, 1, 0x13, buf);
634 return ret;
638 * @brief Set autowhitebalance for omnivision sensors
640 * @param dev
642 * @returns 0 or negative error value
644 * @author Josua Grawitter
646 * For SOI968 sensor.
648 int soi968_set_autowhitebalance(struct usb_sn9c20x *dev)
650 __u8 buf[1];
651 int ret = 0;
653 ret = sn9c20x_read_i2c_data(dev, 1, 0x13, buf);
654 if (ret < 0)
655 return ret;
657 if (dev->vsettings.auto_whitebalance)
658 buf[0] |= 0x02;
659 else
660 buf[0] &= ~0x02;
662 ret = sn9c20x_write_i2c_data(dev, 1, 0x13, buf);
664 return ret;
668 * @brief Set autogain for omnivision sensors
670 * @param dev
672 * @returns 0 or negative error value
674 * @author Josua Grawitter
676 * For all Omnivision sensors and SOI968.
678 int ov_set_autogain(struct usb_sn9c20x *dev)
680 __u8 buf[1];
681 int ret = 0;
683 ret = sn9c20x_read_i2c_data(dev, 1, 0x13, buf);
684 if (ret < 0)
685 return ret;
687 if (dev->vsettings.auto_gain == 1)
688 buf[0] |= 0x04;
689 else if (dev->vsettings.auto_gain == 0)
690 buf[0] &= ~0x04;
691 else
692 return -EINVAL;
694 ret = sn9c20x_write_i2c_data(dev, 1, 0x13, buf);
696 return ret;
700 * @brief Set exposure for SOI968 sensors
702 * @param dev
704 * @returns 0 or negative error value
706 * @author Josua Grawitter
708 * For SOI968 sensors.
710 int soi968_set_exposure(struct usb_sn9c20x *dev)
712 int value, ret;
713 int exposure = dev->vsettings.exposure;
714 __u8 buf1, buf2, buf3;
716 /* Read current value of the I2C-register
717 * containing exposure LSB:
719 ret = sn9c20x_read_i2c_data(dev, 1, 0x04, &buf1);
720 if (ret < 0) {
721 UDIA_ERROR("Error: setting exposure failed: "
722 "error while reading from I2C-register 0x04\n");
723 return ret;
726 value = (exposure * 0x08) & 0x7ff;
727 buf2 = ((__u8) (value & 0x07)) | (buf1 & ~0x07);
728 buf3 = (__u8) (value >> 3) & 0xff;
730 /* Write new value to I2C-register 0x04: */
731 ret = sn9c20x_write_i2c_data(dev, 1, 0x04, &buf2);
732 if (ret < 0) {
733 UDIA_ERROR("Error: setting exposure failed: "
734 "error while writing to I2C-register 0x04\n");
735 return ret;
738 /* Write new value to I2C-register 0x10: */
739 ret = sn9c20x_write_i2c_data(dev, 1, 0x10, &buf3);
740 if (ret < 0) {
741 UDIA_ERROR("Error: setting exposure failed: "
742 "error while writing to I2C-register 0x10\n");
743 return ret;
746 return 0;
749 int soi968_set_gain(struct usb_sn9c20x *dev)
751 int ret;
752 __u8 buf = (dev->vsettings.gain >> 2) & 0x3f;
754 ret = sn9c20x_write_i2c_data(dev, 1, 0x00, &buf);
755 return ret;
759 * @brief Set gain for ov9650 sensor
761 * @param dev
763 * @returns 0 or negative error value
765 * @author Vasily Khoruzhick
768 int ov9650_set_gain(struct usb_sn9c20x *dev)
770 __u8 buf[1];
771 int ret = 0;
773 buf[0] = (dev->vsettings.gain >> 1) & 0x0F;
774 switch (dev->vsettings.gain >> 1 & 0xF0) {
775 case 0x00:
776 break;
777 case 0x10:
778 buf[0] |= 0x10;
779 break;
780 case 0x20:
781 buf[0] |= 0x30;
782 break;
783 case 0x30:
784 buf[0] |= 0x70;
785 break;
786 case 0x40:
787 buf[0] |= 0xF0;
788 break;
789 default:
790 buf[0] |= 0xFF;
791 break;
793 ret |= sn9c20x_write_i2c_data(dev, 1, OV965X_CTL_GAIN, buf);
795 return ret;
799 * @brief Detect whether the image for 6260 has to be flipped
801 * @param dev Pointer to device structure
803 * @returns 0 or negative error code
806 int ov7670_flip_detect(struct usb_sn9c20x *dev)
808 const __u8 flip_bit = 0x01;
809 int ret = 0;
810 __u8 val;
811 static __u8 flip_reg = flip_bit;
812 __u8 vflip;
814 ret = usb_sn9c20x_control_read(dev, 0x1009, &val, 1);
815 if (ret < 0)
816 return -EAGAIN;
817 if (flip_reg != (val & flip_bit)) {
818 if (val & flip_bit)
819 vflip = 0;
820 else
821 vflip = 1;
822 ret = ov7670_auto_flip(dev, vflip);
823 flip_reg = (val & flip_bit);
826 return ret;
830 * @brief Detect whether the image for 624f has to be flipped
832 * @param dev Pointer to device structure
834 * @returns 0 or negative error code
837 int ov965x_flip_detect(struct usb_sn9c20x *dev)
839 int ret = 0;
840 __u8 val;
842 ret = usb_sn9c20x_control_read(dev, 0x1009, &val, 1);
843 if (ret < 0)
844 return -EAGAIN;
845 if (val & 0x01)
846 dev->vsettings.vflip = 1;
847 else
848 dev->vsettings.vflip = 0;
849 return ret;