Change 624f to support bayer format
[microdia.git] / ov7660.c
blob5edb5f59722f254368cccbaff5755ad3f8ab1d3c
1 /**
2 * @file ov7660.c
3 * @author Neekhil
4 * @date 2008-08-24
6 * @brief Common control functions for the Omnivision OV7660 series Image Sensors.
8 * @note Copyright (C) Neekhil
10 * @par Licences
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
15 * any later version.
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
27 #include "microdia.h"
28 #include "sn9c20x.h"
29 #include "ov7660.h"
31 int ov7660_sleep(struct usb_microdia *dev);
32 int ov7660_wakeup(struct usb_microdia *dev);
33 int ov7660_reset(struct usb_microdia *dev);
35 static __u8 ov7660_init[][2] = {
36 /* System CLK selection, to get a higher Frame Rate */
37 {OV7660_CTL_COM5, 0x80},
38 /* OV7660 Wakeup */
39 /* COM4 is Reserved : using default value 0x40 OR windows driver value 0x08 */
40 {OV7660_CTL_COM4, 0x08},
41 /* Enable HREF at optical black, Use optical black line as BLC signal
42 Reset all timing when format changes, Enable ADBLC option */
43 {OV7660_CTL_COM6, 0xc3},
44 /* windows 0x00, default 0x00, trying 0x60 to enable CCIR656 format */
45 {OV7660_CTL_COM1, 0xc3},
46 /* default is 0x40, windows sets it to 0x00 */
47 {OV7660_CTL_AECH, 0x40},
48 /* default is 0x00, windows sets it to 0x40 */
49 {OV7660_CTL_CLKRC, 0x40},
50 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
51 {OV7660_CTL_COM7, 0x05},
52 /* default is 0x8f, windows used 0xf8 */
53 /* Enable fast AGC/AEC algorithm, AEC - Step size limit = 1/16 x AEC */
54 /* Banding & Reserved are disabled. AGC, AEC enabled, 0x85 */
55 {OV7660_CTL_COM8, 0xb8},
56 /* video appears jagged w/o these ADC writes */
57 {OV7660_CTL_ADC, 0x0f},
58 {OV7660_CTL_ACOM, 0x02},
59 {OV7660_CTL_OFON, 0x43},
60 /* video appears jagged w/o this write */
61 /* Default 0x0c sets format to uYvY, Windows driver 0x00 sets format to YuYv */
62 {OV7660_CTL_TSLB, 0x00},
63 /* Not doing this write makes the video look green */
64 /* Manual Banding Filter MSB , set B & R channel pre-gain */
65 {OV7660_CTL_HV, 0x90},
66 /* No video stream w/o these ADVFL/ADVFH write totally black */
67 {OV7660_CTL_ADVFL, 0xf6},
68 {OV7660_CTL_ADVFH, 0x0b},
69 /* Setting BLUE to 0x78; RED to 0x78 to get natural colors in artificial light */
70 {OV7660_CTL_BLUE, 0x78},
71 /* Setting RED to 0x50 to get natural colors in natural light */
72 {OV7660_CTL_RED, 0x50},
75 int ov7660_initialize(struct usb_microdia *dev)
77 int ret, i;
78 __u8 value, reg;
80 ret = sn9c20x_i2c_initialize(dev);
81 ret = ov7660_reset(dev);
83 ret = ov7660_wakeup(dev);
85 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
86 reg = ov7660_init[i][0];
87 value = ov7660_init[i][1];
88 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
89 reg, dev->sensor_flags, &value);
90 if (ret < 0) {
91 UDIA_INFO("Sensor OV7660: Inititialization Error (%d) on array line %d\n", ret, i);
92 break;
96 return ret;
99 /**
100 * @brief Set exposure for ov7660 sensors
102 * @param dev
104 * @return 0 or negative error value
106 * @author Neekhil
108 int ov7660_set_exposure(struct usb_microdia *dev)
110 int ret = 0;
111 __u8 v1 = (dev->vsettings.exposure >> 4) & 0xff;
112 __u8 v2 = dev->vsettings.exposure >> 12;
114 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, OV7660_CTL_ADVFL,
115 dev->sensor_flags, &v1);
117 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, OV7660_CTL_ADVFH,
118 dev->sensor_flags, &v2);
120 return ret;
124 * @brief Set autoexposure for ov7660 sensors
126 * @param dev
128 * @return 0 or negative error value
130 * @author Neekhil
132 int ov7660_set_autoexposure(struct usb_microdia *dev)
134 __u8 buf[1];
135 int ret = 0;
137 /* Read current value of the I2C-register
138 * controlling AutoExposureControl:
140 ret = sn9c20x_read_i2c_data(dev, dev->sensor_slave_address,
141 1, OV7660_CTL_COM8, dev->sensor_flags, buf);
142 if (ret < 0) {
143 UDIA_ERROR("Error: setting of auto exposure failed: "
144 "error while reading from I2C-register OV7660_CTL_COM8");
145 return ret;
148 /* Determine new value for OV7660_CTL_COM8 register */
149 if (dev->vsettings.auto_exposure == 1) {
150 /* Enable automatic exposure: */
151 buf[0] |= 0x01;
152 } else if (dev->vsettings.auto_exposure == 0) {
153 /* Disable automatic exposure: */
154 buf[0] &= ~0x01;
155 } else
156 return -EINVAL;
158 /* Write new value to I2C-register OV7660_CTL_COM8 */
159 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address,
160 1, OV7660_CTL_COM8, dev->sensor_flags, buf);
161 if (ret < 0) {
162 UDIA_ERROR("Error: setting of auto exposure failed: "
163 "error while writing to I2C-register OV7660_CTL_COM8");
164 return ret;
166 return 0;
170 * @brief Set ov7660 sensors to soft-sleep mode
171 * @param dev
172 * @return 0 or negative error value
173 * @author Neekhil
175 int ov7660_sleep(struct usb_microdia *dev)
177 __u8 buf[1];
178 int ret = 0;
180 /* Set the sensor to Soft Sleep mode, Set O/P drive capability to 4X*/
181 buf[0] = 0x13;
182 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
183 OV7660_CTL_COM2, dev->sensor_flags, buf);
184 if (ret < 0)
185 goto errI2C;
187 return 0;
189 errI2C:
190 UDIA_ERROR("Setting Image Sensor to soft sleep failed(%d)!\n", ret);
191 return ret;
195 * @brief Get ov7660 sensors to wake up from soft-sleep mode
196 * @param dev
197 * @return 0 or negative error value
198 * @author Neekhil
200 int ov7660_wakeup(struct usb_microdia *dev)
202 __u8 buf[1];
203 int ret = 0;
205 /* Wake the sensor from Soft Sleep mode, Set O/P drive capability to 4X */
206 buf[0] = 0x03;
207 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
208 OV7660_CTL_COM2, dev->sensor_flags, buf);
209 if (ret < 0)
210 goto errI2C;
212 return 0;
214 errI2C:
215 UDIA_ERROR("Image Sensor failed to wake-up from soft sleep (%d)!\n", ret);
216 return ret;
220 * @brief Resets all the registers on ov7660 sensor
221 * @param dev
222 * @return 0 or negative error value
223 * @author Neekhil
225 int ov7660_reset(struct usb_microdia *dev)
227 __u8 buf[1];
228 int ret = 0;
230 /* Reset all registers to default value */
231 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
232 buf[0] = 0x85;
233 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
234 OV7660_CTL_COM7, dev->sensor_flags, buf);
235 if (ret < 0)
236 goto errI2C;
238 return 0;
240 errI2C:
241 UDIA_ERROR("Failed to reset the Image Sensor (%d)!\n", ret);
242 return ret;