Auto-exposure for ov96xx sensors.
[microdia.git] / ov965x.c
blob308f3b71ae867d2bf376c13614a7c5e8109966e9
1 /**
2 * @file ov965x.c
3 * @author Brian Johnson
4 * @date 2008-08-06
5 * @version v0.0.0
7 * @brief Common functions and data for the Omnivision OV965x sensor series.
9 * @note Copyright (C) Brian Johnson
11 * @par Licences
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "microdia.h"
29 #include "sn9c20x.h"
30 #include "ov965x.h"
32 static __u8 ov965x_init[][2] = {
33 {OV965X_CTL_COM7, OV965X_COM7_SCCB_RESET},
34 {OV965X_CTL_GAIN, 0x00},
35 {OV965X_CTL_BLUE, 0x78},
36 {OV965X_CTL_RED, 0x78},
37 {OV965X_CTL_VREF, OV965X_VREF_VSTOP_LOW3(0x06) |
38 OV965X_VREF_VSTART_LOW3(0x06)},
39 {OV965X_CTL_COM1, 0x03},
40 {OV965X_CTL_BAVE, 0x00}, /* default */
41 {OV965X_CTL_GEAVE, 0x00}, /* default */
42 {OV965X_CTL_RAVE, 0x00}, /* default */
43 {OV965X_CTL_COM2, OV965X_COM2_OUTPUT_DRIVE_CAP_2X},
44 {OV965X_CTL_COM3, 0x00},
45 {OV965X_CTL_COM4, 0x00},
46 {OV965X_CTL_COM5, OV965X_COM5_15FPS_48MHZ_RGB | 0x20},
47 {OV965X_CTL_COM6, OV965X_COM6_TIMING_RESET_ON_FMT_CHANGE | 0x50},
48 {OV965X_CTL_AECH, 0x7c},
49 {OV965X_CTL_CLKRC, OV965X_CLKRC_DBL_CLK_ENABLE},
50 {OV965X_CTL_COM7, OV965X_COM7_OUTPUT_VGA | OV965X_COM7_OUTPUT_RAW_RGB},
51 {OV965X_CTL_COM8, OV965X_COM8_FAST_AGC_AEC |
52 OV965X_COM8_AEC_STEP_SIZE_NOLIMIT |
53 OV965X_COM8_AGC_ENABLE |
54 OV965X_COM8_AEC_ENABLE |
55 OV965X_COM8_AWB_ENABLE},
56 {OV965X_CTL_COM9, OV965X_COM9_MAX_AGC_8X |
57 OV965X_COM9_RELAX_EXPOSURE_TIMING |
58 OV965X_COM9_DROP_VSYNC_ON_FRAME_DROP |
59 OV965X_COM9_DROP_FRAME_ON_BIG_AEC},
60 {OV965X_CTL_COM10, 0x00},
61 {0x16, 0x07}, /* reserved */
62 {OV965X_CTL_HSTART, 0x24},
63 {OV965X_CTL_HSTOP, 0xc5},
64 {OV965X_CTL_VSTRT, 0x00},
65 {OV965X_CTL_VSTOP, 0x3c},
66 {OV965X_CTL_PSHIFT, 0x00}, /* default */
67 {OV965X_CTL_MVFP, 0x04},
68 {OV965X_CTL_LAEC, 0x00}, /* reserved */
69 {OV965X_CTL_AEW, 0x78}, /* default */
70 {OV965X_CTL_AEB, 0x68}, /* default */
71 {OV965X_CTL_VPT, 0xd4}, /* default */
72 {OV965X_CTL_BBIAS, OV965X_BIAS_SUBTRACT}, /* default */
73 {OV965X_CTL_GbBIAS, OV965X_BIAS_SUBTRACT}, /* default */
74 {OV965X_CTL_Gr_COM, OV965X_Gr_COM_BYPASS_ANALOG_BLC |
75 OV965X_Gr_COM_BYPASS_REGULATOR},
76 {OV965X_CTL_EXHCH, 0x00}, /* default */
77 {OV965X_CTL_EXHCL, 0x00}, /* default */
78 {OV965X_CTL_RBIAS, OV965X_BIAS_SUBTRACT}, /* default */
79 {OV965X_CTL_ADVFL, 0x00}, /* default */
80 {OV965X_CTL_ADVFH, 0x00}, /* default */
81 {OV965X_CTL_YAVE, 0x00}, /* default */
82 {OV965X_CTL_HSYST, 0x08}, /* default */
83 {OV965X_CTL_HSYEN, 0x30}, /* default */
84 {OV965X_CTL_HREF, OV965X_HREF_EDGE_OFT_TO_DATA_OUT(2) |
85 OV965X_HREF_HSTOP_LOW3(0) |
86 OV965X_HREF_HSTART_LOW3(4)},
87 {OV965X_CTL_CHLF, 0xe2}, /* reserved */
88 {OV965X_CTL_ARBLM, 0xbf}, /* reserved */
89 {0x35, 0x81}, /* reserved */
90 {0x36, 0xf9}, /* reserved */
91 {OV965X_CTL_ADC, 0x00}, /* reserved */
92 {OV965X_CTL_ACOM, 0x93}, /* reserved */
93 {OV965X_CTL_OFON, 0x50},
94 {OV965X_CTL_TSLB, OV965X_TSLB_OUTPUT_SEQ_UYVY |
95 OV965X_TSLB_DIGITAL_BLC_ENABLE},
96 {OV965X_CTL_COM11, OV965X_COM11_MANUAL_BANDING_FILTER},
97 {OV965X_CTL_COM12, 0x73},
98 {OV965X_CTL_COM13, OV965X_COM13_ENABLE_COLOR_MATRIX |
99 OV965X_COM13_DELAY_Y_CHANNEL |
100 OV965X_COM13_OUTPUT_DELAY(1)},
101 {OV965X_CTL_COM14, OV965X_COM14_YUV_EDGE_ENHANCE |
102 OV965X_COM14_EDGE_ENHANCE_FACTOR_DBL | 0x0b},
103 {OV965X_CTL_EDGE, OV965X_EDGE_EDGE_ENHANCE_LOW4(8) |
104 OV965X_EDGE_EDGE_ENHANCE_FACTOR(8)},
105 {OV965X_CTL_COM15, OV965X_COM15_OUTPUT_RANGE_O0_TO_FF | 0x01},
106 {OV965X_CTL_COM16, 0x00},
107 {OV965X_CTL_COM17, 0x08},
108 {OV965X_CTL_MANU, 0x80}, /* default */
109 {OV965X_CTL_MANV, 0x80}, /* default */
110 {OV965X_CTL_HV, 0x40},
111 {OV965X_CTL_MBD, 0x00}, /* default */
112 {OV965X_CTL_DBLV, 0x0a}, /* reserved */
113 {OV965X_CTL_COM21, 0x06}, /* reserved */
114 {OV965X_CTL_COM22, 0x20},
115 {OV965X_CTL_COM23, 0x00}, /* default */
116 {OV965X_CTL_COM24, 0x00}, /* reserved */
117 {OV965X_CTL_DBLC1, 0xdf},
118 {OV965X_CTL_DM_LNL, 0x00}, /* default */
119 {OV965X_CTL_DM_LNH, 0x00}, /* default */
120 {0x94, 0x88}, /* reserved */
121 {0x95, 0x88}, /* reserved */
122 {0x96, 0x04}, /* reserved */
123 {OV965X_CTL_AECHM, 0x00},
124 {OV965X_CTL_COM26, 0x80}, /* reserved */
125 {0xa8, 0x80}, /* reserved */
126 {0xa9, 0xb8}, /* reserved */
127 {0xaa, 0x92}, /* reserved */
128 {0xab, 0x0a}, /* reserved */
131 int ov965x_initialize(struct usb_microdia *dev)
133 int ret, i;
134 __u8 value, reg;
136 for (i = 0; i < ARRAY_SIZE(ov965x_init); i++) {
137 reg = ov965x_init[i][0];
138 value = ov965x_init[i][1];
139 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
140 reg, dev->sensor_flags, &value);
141 if (ret < 0) {
142 UDIA_INFO("Sensor Init Error (%d). line %d", ret, i);
143 break;
147 return ret;
151 int ov965x_set_hvflip(struct usb_microdia *dev)
153 int ret;
154 __u8 value;
155 ret = sn9c20x_read_i2c_data(dev, dev->sensor_slave_address, 1,
156 OV965X_CTL_MVFP, dev->sensor_flags, &value);
157 if (ret < 0)
158 return ret;
160 if (dev->vsettings.hflip)
161 value |= OV965X_MVFP_MIRROR;
162 else
163 value &= ~OV965X_MVFP_MIRROR;
165 if (dev->vsettings.vflip)
166 value |= OV965X_MVFP_VFLIP;
167 else
168 value &= ~OV965X_MVFP_VFLIP;
170 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
171 OV965X_CTL_MVFP, dev->sensor_flags, &value);
173 return ret;
176 int ov965x_set_exposure(struct usb_microdia *dev)
178 int ret = 0;
179 __u8 v1 = (dev->vsettings.exposure >> 4) & 0xff;
180 __u8 v2 = dev->vsettings.exposure >> 12;
182 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, 0x2d,
183 dev->sensor_flags, &v1);
185 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, 0x2e,
186 dev->sensor_flags, &v2);
188 return ret;
192 * @brief Set autoexposure for ov96xx sensors
194 * @param dev
196 * @returns 0 or negative error value
198 * @author GWater
200 * For all OV965x and SOI968 sensors.
202 int ov965x_set_autoexposure(struct usb_microdia *dev)
204 __u8 buf[1];
205 int ret = 0;
207 /* Read current value of the I2C-register
208 * controlling AutoExposureControl:
210 ret = sn9c20x_read_i2c_data(dev, dev->sensor_slave_address,
211 1, 0x13, dev->sensor_flags, buf);
212 if (ret < 0) {
213 UDIA_ERROR("Error: setting of auto exposure failed: "
214 "error while reading from I2C-register 0x13");
215 return ret;
218 /* Determine new value for register 0x13: */
219 if (dev->vsettings.auto_exposure == 1) {
220 /* Enable automatic exposure: */
221 buf[0] |= 0x01;
222 } else if (dev->vsettings.auto_exposure == 0) {
223 /* Disable automatic exposure: */
224 buf[0] &= ~0x01;
225 } else
226 return -EINVAL;
228 /* Write new value to I2C-register 0x13: */
229 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address,
230 1, 0x13, dev->sensor_flags, buf);
231 if (ret < 0) {
232 UDIA_ERROR("Error: setting of auto exposure failed: "
233 "error while writing to I2C-register 0x13");
234 return ret;
236 return 0;