5 * @brief Common control functions for Omnivision Image Sensors.
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
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
30 static __u8 ov7660_init
[][2] = {
31 /* System CLK selection, to get a higher Frame Rate */
32 {OV7660_CTL_COM5
, 0x80},
34 /* COM4 is Reserved : using default value 0x40 OR windows driver value 0x08 */
35 {OV7660_CTL_COM4
, 0x08},
36 /* Enable HREF at optical black, Use optical black line as BLC signal
37 Reset all timing when format changes, Enable ADBLC option */
38 {OV7660_CTL_COM6
, 0xc3},
39 /* windows 0x00, default 0x00, trying 0x60 to enable CCIR656 format */
40 {OV7660_CTL_COM1
, 0xc3},
41 /* default is 0x40, windows sets it to 0x00 */
42 {OV7660_CTL_AECH
, 0x40},
43 /* default is 0x00, windows sets it to 0x40 */
44 {OV7660_CTL_CLKRC
, 0x40},
45 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
46 {OV7660_CTL_COM7
, 0x05},
47 /* default is 0x8f, windows used 0xf8 */
48 /* Enable fast AGC/AEC algorithm, AEC - Step size limit = 1/16 x AEC */
49 /* Banding & Reserved are disabled. AGC, AEC enabled, 0x85 */
50 {OV7660_CTL_COM8
, 0xb8},
51 /* video appears jagged w/o these ADC writes */
52 {OV7660_CTL_ADC
, 0x0f},
53 {OV7660_CTL_ACOM
, 0x02},
54 {OV7660_CTL_OFON
, 0x43},
55 /* video appears jagged w/o this write */
56 /* Default 0x0c sets format to uYvY, Windows driver 0x00 sets format to YuYv */
57 {OV7660_CTL_TSLB
, 0x00},
58 /* Not doing this write makes the video look green */
59 /* Manual Banding Filter MSB , set B & R channel pre-gain */
60 {OV7660_CTL_HV
, 0x90},
61 /* No video stream w/o these ADVFL/ADVFH write totally black */
62 {OV7660_CTL_ADVFL
, 0xf6},
63 {OV7660_CTL_ADVFH
, 0x0b},
64 /* Setting BLUE to 0x78; RED to 0x78 to get natural colors in artificial light */
65 {OV7660_CTL_BLUE
, 0x78},
66 /* Setting RED to 0x50 to get natural colors in natural light */
67 {OV7660_CTL_RED
, 0x50},
70 static __u8 ov7670_init
[][2] = {
72 {OV7670_CTL_COM7
, 0x80},
73 {OV7670_CTL_CLKRC
, 0x80},
74 {OV7670_CTL_TSLB
, 0x04},
75 {OV7670_CTL_COM7
, 0x00},
76 {OV7670_CTL_HREF
, 0xb6},
77 {OV7670_CTL_VREF
, 0x0a},
78 {OV7670_CTL_COM3
, 0x00},
79 {OV7670_CTL_COM14
, 0x00},
80 {OV7670_CTL_SCALING_XSC
, 0x3a},
81 {OV7670_CTL_SCALING_YSC
, 0x35},
82 {OV7670_CTL_SCALING_DCWCTR
, 0x11},
83 {OV7670_CTL_SCALING_PCLK_DIV
, 0xf0},
84 {OV7670_CTL_SCALING_PCLK_DELAY
, 0x02},
85 {OV7670_CTL_COM8
, 0xe0},
86 {OV7670_CTL_GAIN
, 0x00},
87 {OV7670_CTL_AECH
, 0x00},
88 {OV7670_CTL_COM4
, 0x40},
89 {OV7670_CTL_COM9
, 0x08},
90 {OV7670_CTL_BD50MAX
, 0x05},
91 {OV7670_CTL_BD60MAX
, 0x07},
92 {OV7670_CTL_AEW
, 0x95},
93 {OV7670_CTL_AEB
, 0x33},
94 {OV7670_CTL_VPT
, 0xe3},
95 {OV7670_CTL_HAECC1
, 0x75},
96 {OV7670_CTL_HAECC2
, 0x65},
98 {OV7670_CTL_HAECC3
, 0xd8},
99 {OV7670_CTL_HAECC4
, 0xd8},
100 {OV7670_CTL_HAECC5
, 0xf0},
101 {OV7670_CTL_HAECC6
, 0x90},
102 {OV7670_CTL_HAECC7
, 0x94},
103 {OV7670_CTL_COM8
, 0xe5},
104 {OV7670_CTL_COM5
, 0x61},
105 {OV7670_CTL_COM6
, 0x4b},
107 {OV7670_CTL_MVFP
, 0x27},
108 {OV7670_CTL_ADCCTR1
, 0x02},
109 {OV7670_CTL_ADCCTR2
, 0x91},
111 {OV7670_CTL_CHLF
, 0x0b},
113 {OV7670_CTL_ADC
, 0x1d},
114 {OV7670_CTL_ACOM
, 0x71},
115 {OV7670_CTL_OFON
, 0x2a},
116 {OV7670_CTL_COM12
, 0x78},
119 {OV7670_CTL_GFIX
, 0x00},
120 {OV7670_CTL_REG74
, 0x19},
129 {OV7670_CTL_ABLC1
, 0x0c},
131 {OV7670_CTL_THL_ST
, 0x82},
133 {OV7670_CTL_AWBC1
, 0x0a},
134 {OV7670_CTL_AWBC2
, 0xf0},
135 {OV7670_CTL_AWBC3
, 0x20},
136 {OV7670_CTL_AWBC4
, 0x7d},
137 {OV7670_CTL_AWBC5
, 0x29},
138 {OV7670_CTL_AWBC6
, 0x4a},
145 {OV7670_CTL_AWBCTR3
, 0x0a},
146 {OV7670_CTL_AWBCTR2
, 0x55},
147 {OV7670_CTL_AWBCTR1
, 0x11},
148 {OV7670_CTL_AWBCTR0
, 0x9e},
149 {OV7670_CTL_GGAIN
, 0x40},
150 {OV7670_CTL_BLUE
, 0x40},
151 {OV7670_CTL_RED
, 0x40},
152 {OV7670_CTL_COM8
, 0xe7},
153 {OV7670_CTL_MTX1
, 0x6e},
154 {OV7670_CTL_MTX2
, 0x70},
155 {OV7670_CTL_MTX3
, 0x02},
156 {OV7670_CTL_MTX4
, 0x1d},
157 {OV7670_CTL_MTX5
, 0x56},
158 {OV7670_CTL_MTX6
, 0x73},
159 {OV7670_CTL_BRIGHT
, 0x0a},
160 {OV7670_CTL_CONTRAS
, 0x55},
161 {OV7670_CTL_CONTRAS_CENTER
, 0x80},
162 {OV7670_CTL_MTXS
, 0x9e},
163 {OV7670_CTL_COM16
, 0x08},
164 {OV7670_CTL_EDGE
, 0x02},
165 {OV7670_CTL_REG75
, 0x03},
166 {OV7670_CTL_REG76
, 0x63},
167 {OV7670_CTL_DNSTH
, 0x04},
168 {OV7670_CTL_REG77
, 0x06},
169 {OV7670_CTL_COM13
, 0xc2},
170 {OV7670_CTL_REG4B
, 0x09},
171 {OV7670_CTL_SATCTR
, 0x30},
172 {OV7670_CTL_COM16
, 0x08},
173 {OV7670_CTL_CONTRAS
, 0x48},
174 {OV7670_CTL_ARBLM
, 0x11},
175 {OV7670_CTL_COM11
, 0xc2},
176 {OV7670_CTL_NT_CTRL
, 0x88},
184 {OV7670_CTL_BD50ST
, 0x99},
185 {OV7670_CTL_BD60ST
, 0x7f},
210 {OV7670_CTL_LCC1
, 0x20},
211 {OV7670_CTL_LCC2
, 0x00},
212 {OV7670_CTL_LCC3
, 0x06},
213 {OV7670_CTL_LCC4
, 0x00},
214 {OV7670_CTL_LCC5
, 0x05},
215 {OV7670_CTL_LCC6
, 0x05},
216 {OV7670_CTL_LCC7
, 0x0a},
217 {OV7670_CTL_HSTART
, 0x13},
218 {OV7670_CTL_HSTOP
, 0x01},
219 {OV7670_CTL_VSTRT
, 0x02},
220 {OV7670_CTL_VSTOP
, 0x7a},
221 {OV7670_CTL_AWBC4
, 0x59},
222 {OV7670_CTL_AWBC5
, 0x30},
223 {OV7670_CTL_MTXS
, 0x9a},
230 {OV7670_CTL_LCC3
, 0x07},
231 {OV7670_CTL_LCC6
, 0x07},
232 {OV7670_CTL_LCC7
, 0x0d},
233 {OV7670_CTL_HAECC3
, 0xdf},
234 {OV7670_CTL_HAECC4
, 0xdf},
235 {OV7670_CTL_AWBC6
, 0x4d},
236 {OV7670_CTL_MTX3
, 0x00},
238 {OV7670_CTL_DBLV
, 0x0a},
239 {OV7670_CTL_CLKRC
, 0x80},
240 {OV7670_CTL_EXHCH
, 0x00},
241 {OV7670_CTL_EXHCL
, 0x00},
242 {OV7670_CTL_DM_LNL
, 0x00},
243 {OV7670_CTL_DM_LNH
,0x00},
244 {OV7670_CTL_COM11
, 0xc2},
245 {OV7670_CTL_BRIGHT
, 0x0a},
246 {OV7670_CTL_CONTRAS
, 0x60},
247 {OV7670_CTL_MTX1
, 0x6e},
248 {OV7670_CTL_MTX1
+ 1, 0x70},
249 {OV7670_CTL_MTX1
+ 2, 0x00},
250 {OV7670_CTL_MTX1
+ 3, 0x1d},
251 {OV7670_CTL_MTX5
, 0x56},
252 {OV7670_CTL_MTX5
+ 1, 0x73},
253 {OV7670_CTL_MTXS
, 0x9a},
254 {OV7670_CTL_MTX1
, 0x6e},
255 {OV7670_CTL_MTX1
+ 1, 0x70},
256 {OV7670_CTL_MTX1
+ 2, 0x00},
257 {OV7670_CTL_MTX1
+ 3, 0x1d},
258 {OV7670_CTL_MTX5
, 0x56},
259 {OV7670_CTL_MTX5
+ 1, 0x73},
260 {OV7670_CTL_MTXS
, 0x9a},
261 {OV7670_CTL_EDGE
, 0x01},
262 {OV7670_CTL_GAM1
, 0x03},
263 {OV7670_CTL_GAM1
+ 1, 0x09},
264 {OV7670_CTL_GAM1
+ 2, 0x16},
265 {OV7670_CTL_GAM1
+ 3, 0x38},
266 {OV7670_CTL_GAM5
, 0x47},
267 {OV7670_CTL_GAM5
+ 1, 0x53},
268 {OV7670_CTL_GAM5
+ 2, 0x5e},
269 {OV7670_CTL_GAM5
+ 3, 0x6a},
270 {OV7670_CTL_GAM9
, 0x74},
271 {OV7670_CTL_GAM9
+ 1, 0x80},
272 {OV7670_CTL_GAM9
+ 2, 0x8c},
273 {OV7670_CTL_GAM9
+ 3, 0x9b},
274 {OV7670_CTL_GAM13
, 0xb2},
275 {OV7670_CTL_GAM13
+ 1, 0xcc},
276 {OV7670_CTL_GAM13
+ 2, 0xe5},
277 {OV7670_CTL_SLOP
, 0x24},
278 {OV7670_CTL_COM11
, 0xc0},
279 {OV7670_CTL_COM11
, 0xc0},
280 {OV7670_CTL_HAECC1
, 0x76},
281 {OV7670_CTL_HAECC1
+ 1, 0x65},
282 {OV7670_CTL_COM8
, 0xe7},
284 {OV7670_CTL_DBLV
, 0x0a},
285 {OV7670_CTL_CLKRC
, 0x80},
286 {OV7670_CTL_EXHCH
, 0x00},
287 {OV7670_CTL_EXHCL
, 0x00},
288 {OV7670_CTL_DM_LNL
, 0x00},
289 {OV7670_CTL_DM_LNH
, 0x00},
294 * @brief Addresses and values for the initialization of ov965x sensors
297 static __u8 ov9650_init
[][2] = {
298 {OV965X_CTL_COM7
, OV965X_COM7_SCCB_RESET
},
299 {OV965X_CTL_GAIN
, 0x00},
300 {OV965X_CTL_BLUE
, 0x78},
301 {OV965X_CTL_RED
, 0x78},
302 {OV965X_CTL_VREF
, OV965X_VREF_VSTOP_LOW3(0x06) |
303 OV965X_VREF_VSTART_LOW3(0x06)},
304 {OV965X_CTL_COM1
, 0x03},
305 {OV965X_CTL_BAVE
, 0x00}, /* default */
306 {OV965X_CTL_GEAVE
, 0x00}, /* default */
307 {OV965X_CTL_RAVE
, 0x00}, /* default */
308 {OV965X_CTL_COM2
, OV965X_COM2_OUTPUT_DRIVE_CAP_2X
},
309 {OV965X_CTL_COM3
, 0x00},
310 {OV965X_CTL_COM4
, 0x00},
311 {OV965X_CTL_COM5
, OV965X_COM5_15FPS_48MHZ_RGB
| 0x20},
312 {OV965X_CTL_COM6
, OV965X_COM6_TIMING_RESET_ON_FMT_CHANGE
| 0x50},
313 {OV965X_CTL_AECH
, 0x7c},
314 {OV965X_CTL_CLKRC
, OV965X_CLKRC_DBL_CLK_ENABLE
},
315 {OV965X_CTL_COM7
, OV965X_COM7_OUTPUT_VGA
| OV965X_COM7_OUTPUT_RAW_RGB
},
316 {OV965X_CTL_COM8
, OV965X_COM8_FAST_AGC_AEC
|
317 OV965X_COM8_AEC_STEP_SIZE_NOLIMIT
|
318 OV965X_COM8_AGC_ENABLE
|
319 OV965X_COM8_AEC_ENABLE
|
320 OV965X_COM8_AWB_ENABLE
},
321 {OV965X_CTL_COM9
, OV965X_COM9_MAX_AGC_8X
|
322 OV965X_COM9_RELAX_EXPOSURE_TIMING
|
323 OV965X_COM9_DROP_VSYNC_ON_FRAME_DROP
|
324 OV965X_COM9_DROP_FRAME_ON_BIG_AEC
},
325 {OV965X_CTL_COM10
, 0x00},
326 {0x16, 0x07}, /* reserved */
327 {OV965X_CTL_HSTART
, 0x24},
328 {OV965X_CTL_HSTOP
, 0xc5},
329 {OV965X_CTL_VSTRT
, 0x00},
330 {OV965X_CTL_VSTOP
, 0x3c},
331 {OV965X_CTL_PSHIFT
, 0x00}, /* default */
332 {OV965X_CTL_MVFP
, 0x04},
333 {OV965X_CTL_LAEC
, 0x00}, /* reserved */
334 {OV965X_CTL_AEW
, 0x78}, /* default */
335 {OV965X_CTL_AEB
, 0x68}, /* default */
336 {OV965X_CTL_VPT
, 0xd4}, /* default */
337 {OV965X_CTL_BBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
338 {OV965X_CTL_GbBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
339 {OV965X_CTL_Gr_COM
, OV965X_Gr_COM_BYPASS_ANALOG_BLC
|
340 OV965X_Gr_COM_BYPASS_REGULATOR
},
341 {OV965X_CTL_EXHCH
, 0x00}, /* default */
342 {OV965X_CTL_EXHCL
, 0x00}, /* default */
343 {OV965X_CTL_RBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
344 {OV965X_CTL_ADVFL
, 0x00}, /* default */
345 {OV965X_CTL_ADVFH
, 0x00}, /* default */
346 {OV965X_CTL_YAVE
, 0x00}, /* default */
347 {OV965X_CTL_HSYST
, 0x08}, /* default */
348 {OV965X_CTL_HSYEN
, 0x30}, /* default */
349 {OV965X_CTL_HREF
, OV965X_HREF_EDGE_OFT_TO_DATA_OUT(2) |
350 OV965X_HREF_HSTOP_LOW3(0) |
351 OV965X_HREF_HSTART_LOW3(4)},
352 {OV965X_CTL_CHLF
, 0xe2}, /* reserved */
353 {OV965X_CTL_ARBLM
, 0xbf}, /* reserved */
354 {0x35, 0x81}, /* reserved */
355 {0x36, 0xf9}, /* reserved */
356 {OV965X_CTL_ADC
, 0x00}, /* reserved */
357 {OV965X_CTL_ACOM
, 0x93}, /* reserved */
358 {OV965X_CTL_OFON
, 0x50},
359 {OV965X_CTL_TSLB
, OV965X_TSLB_OUTPUT_SEQ_UYVY
|
360 OV965X_TSLB_DIGITAL_BLC_ENABLE
},
361 {OV965X_CTL_COM11
, OV965X_COM11_MANUAL_BANDING_FILTER
},
362 {OV965X_CTL_COM12
, 0x73},
363 {OV965X_CTL_COM13
, OV965X_COM13_ENABLE_COLOR_MATRIX
|
364 OV965X_COM13_DELAY_Y_CHANNEL
|
365 OV965X_COM13_OUTPUT_DELAY(1)},
366 {OV965X_CTL_COM14
, OV965X_COM14_YUV_EDGE_ENHANCE
|
367 OV965X_COM14_EDGE_ENHANCE_FACTOR_DBL
| 0x0b},
368 {OV965X_CTL_EDGE
, OV965X_EDGE_EDGE_ENHANCE_LOW4(8) |
369 OV965X_EDGE_EDGE_ENHANCE_FACTOR(8)},
370 {OV965X_CTL_COM15
, OV965X_COM15_OUTPUT_RANGE_O0_TO_FF
| 0x01},
371 {OV965X_CTL_COM16
, 0x00},
372 {OV965X_CTL_COM17
, 0x08},
373 {OV965X_CTL_MANU
, 0x80}, /* default */
374 {OV965X_CTL_MANV
, 0x80}, /* default */
375 {OV965X_CTL_HV
, 0x40},
376 {OV965X_CTL_MBD
, 0x00}, /* default */
377 {OV965X_CTL_DBLV
, 0x0a}, /* reserved */
378 {OV965X_CTL_COM21
, 0x06}, /* reserved */
379 {OV965X_CTL_COM22
, 0x20},
380 {OV965X_CTL_COM23
, 0x00}, /* default */
381 {OV965X_CTL_COM24
, 0x00}, /* reserved */
382 {OV965X_CTL_DBLC1
, 0xdf},
383 {OV965X_CTL_DM_LNL
, 0x00}, /* default */
384 {OV965X_CTL_DM_LNH
, 0x00}, /* default */
385 {0x94, 0x88}, /* reserved */
386 {0x95, 0x88}, /* reserved */
387 {0x96, 0x04}, /* reserved */
388 {OV965X_CTL_AECHM
, 0x00},
389 {OV965X_CTL_COM26
, 0x80}, /* reserved */
390 {0xa8, 0x80}, /* reserved */
391 {0xa9, 0xb8}, /* reserved */
392 {0xaa, 0x92}, /* reserved */
393 {0xab, 0x0a}, /* reserved */
398 * @brief Addresses and values for the initialization of SOI968 sensors
402 static __u8 soi968_init
[][2] = {
403 /* reset all registers */
407 /* snapshot mode: off */
409 /* enable offset adjustment,
411 * analogue2digital control black-level calibration
414 /* Clock: internal PLL on */
416 /* Analoge Black-level calibration off , no anaolgue gain */
420 /* special system settings (voltage, analogue2digital, ...) */
425 /* next 7 are unknown/reserved */
433 /* disable banding filter in dark environment,
434 * VSYNC is dropped when framerate is dropped,
435 * drop frmaes when exposure out of tolerance,
436 * unfreeze exposure and gain values
439 /* AEC, AGC, AWB disabled; fast AEC */
441 /* output: VGA, master mode */
443 /* set HSTART, HSTOP, VSTART and VSTOP */
448 {0x32, 0x24}, /* LSB for all four */
449 /* AWB update threshold,
450 * blue and red gain LSB
453 /* CLock: internal PLL off */
455 /* Line interval adjustment */
462 /* blue and red gain - default*/
467 static __u8 ov9655_init
[][2] = {
606 struct microdia_video_format ov_fmts
[] = {
608 .pix_fmt
= V4L2_PIX_FMT_SBGGR8
,
609 .desc
= "Bayer 8bit (BGGR)",
611 .set_format
= sn9c20x_set_raw
614 .pix_fmt
= V4L2_PIX_FMT_JPEG
,
615 .desc
= "JPEG (YUV 4:2:2)",
617 .set_format
= sn9c20x_set_jpeg
621 struct microdia_video_resolution ov965x_resolutions
[] = {
625 .scale
= SN9C20X_1_4_SCALE
,
626 .window
= {0, 17, 640, 480}
631 .scale
= SN9C20X_1_2_SCALE
,
632 .window
= {0, 7, 640, 480}
637 .scale
= SN9C20X_NO_SCALE
,
638 .window
= {0, 7, 640, 480}
642 struct microdia_video_resolution soi968_resolutions
[] = {
646 .scale
= SN9C20X_1_4_SCALE
,
647 .window
= {60, 17, 640, 480}
652 .scale
= SN9C20X_1_2_SCALE
,
653 .window
= {60, 11, 640, 480}
658 .scale
= SN9C20X_NO_SCALE
,
659 .window
= {60, 11, 640, 480}
663 struct microdia_video_resolution ov7670_resolutions
[] = {
667 .scale
= SN9C20X_1_4_SCALE
,
668 .window
= {0, 1, 640, 480}
673 .scale
= SN9C20X_1_2_SCALE
,
674 .window
= {0, 1, 640, 480}
679 .scale
= SN9C20X_NO_SCALE
,
680 .window
= {0, 1, 640, 480}
684 struct microdia_video_resolution ov7660_resolutions
[] = {
688 .scale
= SN9C20X_1_4_SCALE
,
689 .window
= {1, 1, 640, 480}
694 .scale
= SN9C20X_1_2_SCALE
,
695 .window
= {1, 1, 640, 480}
700 .scale
= SN9C20X_NO_SCALE
,
701 .window
= {1, 1, 640, 480}
705 int ov_probe(struct usb_microdia
*dev
)
709 dev
->camera
.sensor_slave_address
= 0x30;
710 ret
= sn9c20x_read_i2c_data(dev
, 2, 0x0a, buf
);
712 if (buf
[0] != 0x76 && buf
[0] != 0x96)
714 if (buf
[1] == 0x60) {
715 ov_initialize(dev
, ov7660_init
, ARRAY_SIZE(ov7660_init
));
716 dev
->camera
.set_exposure
= ov7660_set_exposure
;
717 dev
->camera
.set_auto_exposure
= ov7660_set_autoexposure
;
718 dev
->camera
.modes
= ov7660_resolutions
;
719 dev
->camera
.nmodes
= ARRAY_SIZE(ov7660_resolutions
);
720 dev
->camera
.fmts
= ov_fmts
;
721 dev
->camera
.nfmts
= ARRAY_SIZE(ov_fmts
);
722 return OV7660_SENSOR
;
724 if (buf
[1] == 0x70) {
725 ov_initialize(dev
, ov7670_init
, ARRAY_SIZE(ov7670_init
));
726 dev
->camera
.flip_detect
= ov7670_flip_detect
;
727 dev
->camera
.modes
= ov7670_resolutions
;
728 dev
->camera
.nmodes
= ARRAY_SIZE(ov7670_resolutions
);
729 dev
->camera
.fmts
= ov_fmts
;
730 dev
->camera
.nfmts
= ARRAY_SIZE(ov_fmts
);
731 return OV7670_SENSOR
;
733 if (buf
[1] == 0x52) {
734 ov_initialize(dev
, ov9650_init
, ARRAY_SIZE(ov9650_init
));
735 dev
->camera
.set_hvflip
= ov965x_set_hvflip
;
736 dev
->camera
.set_exposure
= ov965x_set_exposure
;
737 dev
->camera
.set_auto_exposure
= ov965x_set_autoexposure
;
738 dev
->camera
.flip_detect
= ov965x_flip_detect
;
739 dev
->camera
.modes
= ov965x_resolutions
;
740 dev
->camera
.nmodes
= ARRAY_SIZE(ov965x_resolutions
);
741 dev
->camera
.fmts
= ov_fmts
;
742 dev
->camera
.nfmts
= ARRAY_SIZE(ov_fmts
);
743 return OV9650_SENSOR
;
745 if (buf
[1] == 0x56 || buf
[1] == 0x57) {
746 ov_initialize(dev
, ov9655_init
, ARRAY_SIZE(ov9655_init
));
747 dev
->camera
.modes
= ov7670_resolutions
;
748 dev
->camera
.nmodes
= ARRAY_SIZE(ov7670_resolutions
);
749 dev
->camera
.fmts
= ov_fmts
;
750 dev
->camera
.nfmts
= ARRAY_SIZE(ov_fmts
);
751 return OV9655_SENSOR
;
753 if (buf
[1] == 0x28) {
754 ov_initialize(dev
, soi968_init
, ARRAY_SIZE(soi968_init
));
755 dev
->camera
.set_exposure
= soi968_set_exposure
;
756 dev
->camera
.set_auto_exposure
= ov965x_set_autoexposure
;
757 dev
->camera
.modes
= soi968_resolutions
;
758 dev
->camera
.nmodes
= ARRAY_SIZE(soi968_resolutions
);
759 dev
->camera
.fmts
= ov_fmts
;
760 dev
->camera
.nfmts
= ARRAY_SIZE(ov_fmts
);
761 return SOI968_SENSOR
;
764 UDIA_INFO("Failed on i2c read in ov_probe\n");
770 * @brief Initialize ov sensors
772 * @param dev Pointer to device structure
773 * @param ov_init Data array for initialization
774 * @param array_size size of ov_init
776 * @return 0 or negative error code
779 int ov_initialize(struct usb_microdia
*dev
, __u8 ov_init
[][2], int array_size
)
785 for (i
= 0; i
< array_size
; i
++) {
787 value
= ov_init
[i
][1];
788 ret
= sn9c20x_write_i2c_data(dev
, 1, reg
, &value
);
790 UDIA_INFO("Sensor Init Error (%d). line %d\n", ret
, i
);
800 * @brief Set exposure for ov7660 sensors
804 * @return 0 or negative error value
808 int ov7660_set_exposure(struct usb_microdia
*dev
)
811 __u8 v1
= (dev
->vsettings
.exposure
>> 4) & 0xff;
812 __u8 v2
= dev
->vsettings
.exposure
>> 12;
814 ret
|= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_ADVFL
, &v1
);
816 ret
|= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_ADVFH
, &v2
);
822 * @brief Set autoexposure for ov7660 sensors
826 * @return 0 or negative error value
830 int ov7660_set_autoexposure(struct usb_microdia
*dev
)
835 /* Read current value of the I2C-register
836 * controlling AutoExposureControl:
838 ret
= sn9c20x_read_i2c_data(dev
, 1, OV7660_CTL_COM8
, buf
);
840 UDIA_ERROR("Error: setting of auto exposure failed: "
841 "error while reading from I2C-register OV7660_CTL_COM8\n");
845 /* Determine new value for OV7660_CTL_COM8 register */
846 if (dev
->vsettings
.auto_exposure
== 1) {
847 /* Enable automatic exposure: */
849 } else if (dev
->vsettings
.auto_exposure
== 0) {
850 /* Disable automatic exposure: */
855 /* Write new value to I2C-register OV7660_CTL_COM8 */
856 ret
= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_COM8
, buf
);
858 UDIA_ERROR("Error: setting of auto exposure failed: "
859 "error while writing to I2C-register OV7660_CTL_COM8\n");
866 * @brief Set ov7660 sensors to soft-sleep mode
868 * @return 0 or negative error value
871 int ov7660_sleep(struct usb_microdia
*dev
)
876 /* Set the sensor to Soft Sleep mode, Set O/P drive capability to 4X*/
878 ret
= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_COM2
, buf
);
885 UDIA_ERROR("Setting Image Sensor to soft sleep failed(%d)!\n", ret
);
890 * @brief Get ov7660 sensors to wake up from soft-sleep mode
892 * @return 0 or negative error value
895 int ov7660_wakeup(struct usb_microdia
*dev
)
900 /* Wake the sensor from Soft Sleep mode, Set O/P drive capability to 4X */
902 ret
= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_COM2
, buf
);
909 UDIA_ERROR("Image Sensor failed to wake-up from soft sleep (%d)!\n", ret
);
914 * @brief Resets all the registers on ov7660 sensor
916 * @return 0 or negative error value
919 int ov7660_reset(struct usb_microdia
*dev
)
924 /* Reset all registers to default value */
925 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
927 ret
= sn9c20x_write_i2c_data(dev
, 1, OV7660_CTL_COM7
, buf
);
934 UDIA_ERROR("Failed to reset the Image Sensor (%d)!\n", ret
);
939 * @brief OV7670 Auto-Flip
941 * @param dev Pointer to the device
942 * @param vflip Flag to indicate whether or not Camera is currently flipped
944 * @return Zero (success) or negative (USB-error value)
947 int ov7670_auto_flip(struct usb_microdia
*dev
, __u8 vflip
)
952 ret
= sn9c20x_read_i2c_data(dev
, 1,
953 OV7670_CTL_MVFP
, buf
);
958 buf
[0] = buf
[0] & (0xff ^ OV7670_VFLIP_BIT
);
960 buf
[0] = buf
[0] | OV7670_VFLIP_BIT
;
961 ret
= sn9c20x_write_i2c_data(dev
, 1,
962 OV7670_CTL_MVFP
, buf
);
968 * @brief Set hflip and vflip in ov965x sensors
970 * @param dev Pointer to device structure
972 * @returns 0 or negative error code
975 int ov965x_set_hvflip(struct usb_microdia
*dev
)
980 * Changing hstop value seems to be necessary to keep correct
981 * colors during a vflip. The values don't seem to make much
982 * sense since to keep the correct color value i'm setting hstop
983 * to the same value as hstart is set for.
986 ret
= sn9c20x_read_i2c_data(dev
, 1, OV965X_CTL_MVFP
, &value
);
990 if (dev
->vsettings
.hflip
)
991 value
|= OV965X_MVFP_MIRROR
;
993 value
&= ~OV965X_MVFP_MIRROR
;
995 if (dev
->vsettings
.vflip
) {
997 value
|= OV965X_MVFP_VFLIP
;
999 value
&= ~OV965X_MVFP_VFLIP
;
1002 ret
= sn9c20x_write_i2c_data(dev
, 1, OV965X_CTL_HSTOP
, &hstop
);
1004 ret
= sn9c20x_write_i2c_data(dev
, 1, OV965X_CTL_MVFP
, &value
);
1010 * @brief Set exposure for ov965x sensors
1014 * @returns 0 or negative error value
1016 * The used registers do not show up the datasheets.
1019 int ov965x_set_exposure(struct usb_microdia
*dev
)
1022 __u8 v1
= (dev
->vsettings
.exposure
>> 4) & 0xff;
1023 __u8 v2
= dev
->vsettings
.exposure
>> 12;
1025 ret
|= sn9c20x_write_i2c_data(dev
, 1, 0x2d, &v1
);
1027 ret
|= sn9c20x_write_i2c_data(dev
, 1, 0x2e, &v2
);
1033 * @brief Set autoexposure for ov96xx sensors
1037 * @returns 0 or negative error value
1041 * For all OV965x and SOI968 sensors.
1043 int ov965x_set_autoexposure(struct usb_microdia
*dev
)
1048 /* Read current value of the I2C-register
1049 * controlling AutoExposureControl:
1051 ret
= sn9c20x_read_i2c_data(dev
, 1, 0x13, buf
);
1053 UDIA_ERROR("Error: setting of auto exposure failed: "
1054 "error while reading from I2C-register 0x13\n");
1058 /* Determine new value for register 0x13: */
1059 if (dev
->vsettings
.auto_exposure
== 1) {
1060 /* Enable automatic exposure: */
1062 } else if (dev
->vsettings
.auto_exposure
== 0) {
1063 /* Disable automatic exposure: */
1068 /* Write new value to I2C-register 0x13: */
1069 ret
= sn9c20x_write_i2c_data(dev
, 1, 0x13, buf
);
1071 UDIA_ERROR("Error: setting of auto exposure failed: "
1072 "error while writing to I2C-register 0x13\n");
1079 * @brief Set exposure for SOI968 sensors
1083 * @returns 0 or negative error value
1087 * For SOI968 sensors.
1089 int soi968_set_exposure(struct usb_microdia
*dev
)
1092 int exposure
= dev
->vsettings
.exposure
;
1093 __u8 buf1
, buf2
, buf3
;
1095 /* Read current value of the I2C-register
1096 * containing exposure LSB:
1098 ret
= sn9c20x_read_i2c_data(dev
, 1, 0x04, &buf1
);
1100 UDIA_ERROR("Error: setting exposure failed: "
1101 "error while reading from I2C-register 0x04\n");
1105 value
= (exposure
* 0x07ff / 0xffff) & 0x07ff;
1106 buf2
= ((__u8
) (value
& 0x07)) | (buf1
& ~0x07);
1107 buf3
= (__u8
) (value
>> 3) & 0xff;
1109 /* Write new value to I2C-register 0x04: */
1110 ret
= sn9c20x_write_i2c_data(dev
, 1, 0x04, &buf2
);
1112 UDIA_ERROR("Error: setting exposure failed: "
1113 "error while writing to I2C-register 0x04\n");
1117 /* Write new value to I2C-register 0x10: */
1118 ret
= sn9c20x_write_i2c_data(dev
, 1, 0x10, &buf3
);
1120 UDIA_ERROR("Error: setting exposure failed: "
1121 "error while writing to I2C-register 0x10\n");
1129 * @brief Detect whether the image for 6260 has to be flipped
1131 * @param dev Pointer to device structure
1133 * @returns 0 or negative error code
1136 int ov7670_flip_detect(struct usb_microdia
*dev
)
1138 const __u8 flip_bit
= 0x01;
1141 static __u8 flip_reg
= flip_bit
;
1144 ret
= usb_microdia_control_read(dev
, 0x1009, &val
, 1);
1147 if (flip_reg
!= (val
& flip_bit
)) {
1152 ret
= ov7670_auto_flip(dev
, vflip
);
1153 flip_reg
= (val
& flip_bit
);
1160 * @brief Detect whether the image for 624f has to be flipped
1162 * @param dev Pointer to device structure
1164 * @returns 0 or negative error code
1167 int ov965x_flip_detect(struct usb_microdia
*dev
)
1172 ret
= usb_microdia_control_read(dev
, 0x1009, &val
, 1);
1176 dev
->vsettings
.vflip
= 1;
1178 dev
->vsettings
.vflip
= 0;