3 * @author Brian Johnson
6 * @brief Common functions and data for the Omnivision OV965x sensor series.
8 * @note Copyright (C) Brian Johnson
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 static __u8 ov965x_init
[][2] = {
32 {OV965X_CTL_COM7
, OV965X_COM7_SCCB_RESET
},
33 {OV965X_CTL_GAIN
, 0x00},
34 {OV965X_CTL_BLUE
, 0x78},
35 {OV965X_CTL_RED
, 0x78},
36 {OV965X_CTL_VREF
, OV965X_VREF_VSTOP_LOW3(0x06) |
37 OV965X_VREF_VSTART_LOW3(0x06)},
38 {OV965X_CTL_COM1
, 0x03},
39 {OV965X_CTL_BAVE
, 0x00}, /* default */
40 {OV965X_CTL_GEAVE
, 0x00}, /* default */
41 {OV965X_CTL_RAVE
, 0x00}, /* default */
42 {OV965X_CTL_COM2
, OV965X_COM2_OUTPUT_DRIVE_CAP_2X
},
43 {OV965X_CTL_COM3
, 0x00},
44 {OV965X_CTL_COM4
, 0x00},
45 {OV965X_CTL_COM5
, OV965X_COM5_15FPS_48MHZ_RGB
| 0x20},
46 {OV965X_CTL_COM6
, OV965X_COM6_TIMING_RESET_ON_FMT_CHANGE
| 0x50},
47 {OV965X_CTL_AECH
, 0x7c},
48 {OV965X_CTL_CLKRC
, OV965X_CLKRC_DBL_CLK_ENABLE
},
49 {OV965X_CTL_COM7
, OV965X_COM7_OUTPUT_VGA
| OV965X_COM7_OUTPUT_RAW_RGB
},
50 {OV965X_CTL_COM8
, OV965X_COM8_FAST_AGC_AEC
|
51 OV965X_COM8_AEC_STEP_SIZE_NOLIMIT
|
52 OV965X_COM8_AGC_ENABLE
|
53 OV965X_COM8_AEC_ENABLE
|
54 OV965X_COM8_AWB_ENABLE
},
55 {OV965X_CTL_COM9
, OV965X_COM9_MAX_AGC_8X
|
56 OV965X_COM9_RELAX_EXPOSURE_TIMING
|
57 OV965X_COM9_DROP_VSYNC_ON_FRAME_DROP
|
58 OV965X_COM9_DROP_FRAME_ON_BIG_AEC
},
59 {OV965X_CTL_COM10
, 0x00},
60 {0x16, 0x07}, /* reserved */
61 {OV965X_CTL_HSTART
, 0x24},
62 {OV965X_CTL_HSTOP
, 0xc5},
63 {OV965X_CTL_VSTRT
, 0x00},
64 {OV965X_CTL_VSTOP
, 0x3c},
65 {OV965X_CTL_PSHIFT
, 0x00}, /* default */
66 {OV965X_CTL_MVFP
, 0x04},
67 {OV965X_CTL_LAEC
, 0x00}, /* reserved */
68 {OV965X_CTL_AEW
, 0x78}, /* default */
69 {OV965X_CTL_AEB
, 0x68}, /* default */
70 {OV965X_CTL_VPT
, 0xd4}, /* default */
71 {OV965X_CTL_BBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
72 {OV965X_CTL_GbBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
73 {OV965X_CTL_Gr_COM
, OV965X_Gr_COM_BYPASS_ANALOG_BLC
|
74 OV965X_Gr_COM_BYPASS_REGULATOR
},
75 {OV965X_CTL_EXHCH
, 0x00}, /* default */
76 {OV965X_CTL_EXHCL
, 0x00}, /* default */
77 {OV965X_CTL_RBIAS
, OV965X_BIAS_SUBTRACT
}, /* default */
78 {OV965X_CTL_ADVFL
, 0x00}, /* default */
79 {OV965X_CTL_ADVFH
, 0x00}, /* default */
80 {OV965X_CTL_YAVE
, 0x00}, /* default */
81 {OV965X_CTL_HSYST
, 0x08}, /* default */
82 {OV965X_CTL_HSYEN
, 0x30}, /* default */
83 {OV965X_CTL_HREF
, OV965X_HREF_EDGE_OFT_TO_DATA_OUT(2) |
84 OV965X_HREF_HSTOP_LOW3(0) |
85 OV965X_HREF_HSTART_LOW3(4)},
86 {OV965X_CTL_CHLF
, 0xe2}, /* reserved */
87 {OV965X_CTL_ARBLM
, 0xbf}, /* reserved */
88 {0x35, 0x81}, /* reserved */
89 {0x36, 0xf9}, /* reserved */
90 {OV965X_CTL_ADC
, 0x00}, /* reserved */
91 {OV965X_CTL_ACOM
, 0x93}, /* reserved */
92 {OV965X_CTL_OFON
, 0x50},
93 {OV965X_CTL_TSLB
, OV965X_TSLB_OUTPUT_SEQ_UYVY
|
94 OV965X_TSLB_DIGITAL_BLC_ENABLE
},
95 {OV965X_CTL_COM11
, OV965X_COM11_MANUAL_BANDING_FILTER
},
96 {OV965X_CTL_COM12
, 0x73},
97 {OV965X_CTL_COM13
, OV965X_COM13_ENABLE_COLOR_MATRIX
|
98 OV965X_COM13_DELAY_Y_CHANNEL
|
99 OV965X_COM13_OUTPUT_DELAY(1)},
100 {OV965X_CTL_COM14
, OV965X_COM14_YUV_EDGE_ENHANCE
|
101 OV965X_COM14_EDGE_ENHANCE_FACTOR_DBL
| 0x0b},
102 {OV965X_CTL_EDGE
, OV965X_EDGE_EDGE_ENHANCE_LOW4(8) |
103 OV965X_EDGE_EDGE_ENHANCE_FACTOR(8)},
104 {OV965X_CTL_COM15
, OV965X_COM15_OUTPUT_RANGE_O0_TO_FF
| 0x01},
105 {OV965X_CTL_COM16
, 0x00},
106 {OV965X_CTL_COM17
, 0x08},
107 {OV965X_CTL_MANU
, 0x80}, /* default */
108 {OV965X_CTL_MANV
, 0x80}, /* default */
109 {OV965X_CTL_HV
, 0x40},
110 {OV965X_CTL_MBD
, 0x00}, /* default */
111 {OV965X_CTL_DBLV
, 0x0a}, /* reserved */
112 {OV965X_CTL_COM21
, 0x06}, /* reserved */
113 {OV965X_CTL_COM22
, 0x20},
114 {OV965X_CTL_COM23
, 0x00}, /* default */
115 {OV965X_CTL_COM24
, 0x00}, /* reserved */
116 {OV965X_CTL_DBLC1
, 0xdf},
117 {OV965X_CTL_DM_LNL
, 0x00}, /* default */
118 {OV965X_CTL_DM_LNH
, 0x00}, /* default */
119 {0x94, 0x88}, /* reserved */
120 {0x95, 0x88}, /* reserved */
121 {0x96, 0x04}, /* reserved */
122 {OV965X_CTL_AECHM
, 0x00},
123 {OV965X_CTL_COM26
, 0x80}, /* reserved */
124 {0xa8, 0x80}, /* reserved */
125 {0xa9, 0xb8}, /* reserved */
126 {0xaa, 0x92}, /* reserved */
127 {0xab, 0x0a}, /* reserved */
130 int ov965x_initialize(struct usb_microdia
*dev
)
135 for (i
= 0; i
< ARRAY_SIZE(ov965x_init
); i
++) {
136 reg
= ov965x_init
[i
][0];
137 value
= ov965x_init
[i
][1];
138 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1,
139 reg
, dev
->sensor_flags
, &value
);
141 UDIA_INFO("Sensor Init Error (%d). line %d\n", ret
, i
);
150 static __u8 soi968_init
[][2] = {
151 /* reset all registers */
156 /* snapshot mode: off */
159 /* enable offset adjustment,
161 * analogue2digital control black-level calibration
165 /* Clock: internal PLL on */
169 /* Analoge Black-level calibration off , no anaolgue gain */
175 /* special system settings (voltage, analogue2digital, ...) */
181 /* next 7 are unknown/reserved */
190 /* disable banding filter in dark environment,
191 * VSYNC is dropped when framerate is dropped,
192 * drop frmaes when exposure out of tolerance,
193 * unfreeze exposure and gain values
197 /* AEC, AGC, AWB disabled; fast AEC */
200 /* output: VGA, master mode */
203 /* set HSTART, HSTOP, VSTART and VSTOP */
208 {0x32, 0x24}, /* LSB for all four */
210 /* this register contains the product ID, it is read-only
213 /* AWB update threshold,
214 * blue and red gain LSB
218 /* CLock: internal PLL off */
221 /* Line interval adjustment */
231 /* blue and red gain - default*/
236 int soi968_initialize(struct usb_microdia
*dev
)
241 for (i
= 0; i
< ARRAY_SIZE(soi968_init
); i
++) {
242 reg
= soi968_init
[i
][0];
243 value
= soi968_init
[i
][1];
244 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1,
245 reg
, dev
->sensor_flags
, &value
);
247 UDIA_INFO("Sensor Init Error (%d). line %d\n", ret
, i
);
256 int ov965x_set_hvflip(struct usb_microdia
*dev
)
261 * Changing hstop value seems to be necessary to keep correct
262 * colors during a vflip. The values don't seem to make much
263 * sense since to keep the correct color value i'm setting hstop
264 * to the same value as hstart is set for.
267 ret
= sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
, 1,
268 OV965X_CTL_MVFP
, dev
->sensor_flags
, &value
);
272 if (dev
->vsettings
.hflip
)
273 value
|= OV965X_MVFP_MIRROR
;
275 value
&= ~OV965X_MVFP_MIRROR
;
277 if (dev
->vsettings
.vflip
) {
279 value
|= OV965X_MVFP_VFLIP
;
281 value
&= ~OV965X_MVFP_VFLIP
;
284 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1,
285 OV965X_CTL_HSTOP
, dev
->sensor_flags
, &hstop
);
287 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1,
288 OV965X_CTL_MVFP
, dev
->sensor_flags
, &value
);
293 int ov965x_set_exposure(struct usb_microdia
*dev
)
296 __u8 v1
= (dev
->vsettings
.exposure
>> 4) & 0xff;
297 __u8 v2
= dev
->vsettings
.exposure
>> 12;
299 ret
|= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1, 0x2d,
300 dev
->sensor_flags
, &v1
);
302 ret
|= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
, 1, 0x2e,
303 dev
->sensor_flags
, &v2
);
309 * @brief Set autoexposure for ov96xx sensors
313 * @returns 0 or negative error value
317 * For all OV965x and SOI968 sensors.
319 int ov965x_set_autoexposure(struct usb_microdia
*dev
)
324 /* Read current value of the I2C-register
325 * controlling AutoExposureControl:
327 ret
= sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
,
328 1, 0x13, dev
->sensor_flags
, buf
);
330 UDIA_ERROR("Error: setting of auto exposure failed: "
331 "error while reading from I2C-register 0x13");
335 /* Determine new value for register 0x13: */
336 if (dev
->vsettings
.auto_exposure
== 1) {
337 /* Enable automatic exposure: */
339 } else if (dev
->vsettings
.auto_exposure
== 0) {
340 /* Disable automatic exposure: */
345 /* Write new value to I2C-register 0x13: */
346 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
347 1, 0x13, dev
->sensor_flags
, buf
);
349 UDIA_ERROR("Error: setting of auto exposure failed: "
350 "error while writing to I2C-register 0x13");
357 * @brief Set exposure for SOI968 sensors
361 * @returns 0 or negative error value
365 * For SOI968 sensors.
367 int soi968_set_exposure(struct usb_microdia
*dev
)
370 int exposure
= dev
->vsettings
.exposure
;
371 __u8 buf1
, buf2
, buf3
;
373 /* Read current value of the I2C-register
374 * containing exposure LSB:
376 ret
= sn9c20x_read_i2c_data(dev
, dev
->sensor_slave_address
,
377 1, 0x04, dev
->sensor_flags
, &buf1
);
379 UDIA_ERROR("Error: setting exposure failed: "
380 "error while reading from I2C-register 0x04");
384 value
= (exposure
* 0x07ff / 0xffff) & 0x07ff;
385 buf2
= ((__u8
) (value
& 0x07)) | (buf1
& ~0x07);
386 buf3
= (__u8
) (value
>> 3) & 0xff;
388 /* Write new value to I2C-register 0x04: */
389 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
390 1, 0x04, dev
->sensor_flags
, &buf2
);
392 UDIA_ERROR("Error: setting exposure failed: "
393 "error while writing to I2C-register 0x04");
397 /* Write new value to I2C-register 0x10: */
398 ret
= sn9c20x_write_i2c_data(dev
, dev
->sensor_slave_address
,
399 1, 0x10, dev
->sensor_flags
, &buf3
);
401 UDIA_ERROR("Error: setting exposure failed: "
402 "error while writing to I2C-register 0x10");