Remove function usb_microdia_control_write_multi
[microdia.git] / ov7660.c
blob237004b5eacb4e88898a8b47a0da1bfa1c65cf53
1 /**
2 * @file ov7660.c
3 * @author Neekhil
4 * @date 2008-08-24
5 * @version v0.0.0
7 * @brief Common control functions for the Omnivision OV7660 series Image Sensors.
9 * @note Copyright (C) Neekhil
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 "ov7660.h"
32 int ov7660_sleep(struct usb_microdia *dev);
33 int ov7660_wakeup(struct usb_microdia *dev);
34 int ov7660_reset(struct usb_microdia *dev);
36 static __u8 ov7660_init[][2] = {
37 /* System CLK selection, to get a higher Frame Rate */
38 {OV7660_CTL_COM5, 0x80},
39 /* OV7660 Wakeup */
40 /* COM4 is Reserved : using default value 0x40 OR windows driver value 0x08 */
41 {OV7660_CTL_COM4, 0x08},
42 /* Enable HREF at optical black, Use optical black line as BLC signal
43 Reset all timing when format changes, Enable ADBLC option */
44 {OV7660_CTL_COM6, 0xc3},
45 /* windows 0x00, default 0x00, trying 0x60 to enable CCIR656 format */
46 {OV7660_CTL_COM1, 0xc3},
47 /* default is 0x40, windows sets it to 0x00 */
48 {OV7660_CTL_AECH, 0x40},
49 /* default is 0x00, windows sets it to 0x40 */
50 {OV7660_CTL_CLKRC, 0x40},
51 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
52 {OV7660_CTL_COM7, 0x05},
53 /* default is 0x8f, windows used 0xf8 */
54 /* Enable fast AGC/AEC algorithm, AEC - Step size limit = 1/16 x AEC */
55 /* Banding & Reserved are disabled. AGC, AEC enabled, 0x85 */
56 {OV7660_CTL_COM8, 0xb8},
57 /* video appears jagged w/o these ADC writes */
58 {OV7660_CTL_ADC, 0x0f},
59 {OV7660_CTL_ACOM, 0x02},
60 {OV7660_CTL_OFON, 0x43},
61 /* video appears jagged w/o this write */
62 /* Default 0x0c sets format to uYvY, Windows driver 0x00 sets format to YuYv */
63 {OV7660_CTL_TSLB, 0x00},
64 /* Not doing this write makes the video look green */
65 /* Manual Banding Filter MSB , set B & R channel pre-gain */
66 {OV7660_CTL_HV, 0x90},
67 /* No video stream w/o these ADVFL/ADVFH write totally black */
68 {OV7660_CTL_ADVFL, 0xf6},
69 {OV7660_CTL_ADVFH, 0x0b},
70 /* Setting BLUE to 0x78; RED to 0x78 to get natural colors in artificial light */
71 {OV7660_CTL_BLUE, 0x78},
72 /* Setting RED to 0x50 to get natural colors in natural light */
73 {OV7660_CTL_RED, 0x50},
76 int ov7660_initialize(struct usb_microdia *dev)
78 int ret, i;
79 __u8 value, reg;
81 ret = sn9c20x_i2c_initialize(dev);
82 ret = ov7660_reset(dev);
84 ret = ov7660_wakeup(dev);
86 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
87 reg = ov7660_init[i][0];
88 value = ov7660_init[i][1];
89 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
90 reg, dev->sensor_flags, &value);
91 if (ret < 0) {
92 UDIA_INFO("Sensor OV7660: Inititialization Error (%d) on array line %d", ret, i);
93 break;
97 return ret;
101 * @brief Set exposure for ov7660 sensors
103 * @param dev
105 * @return 0 or negative error value
107 * @author Neekhil
109 int ov7660_set_exposure(struct usb_microdia *dev)
111 int ret = 0;
112 __u8 v1 = (dev->vsettings.exposure >> 4) & 0xff;
113 __u8 v2 = dev->vsettings.exposure >> 12;
115 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, OV7660_CTL_ADVFL,
116 dev->sensor_flags, &v1);
118 ret |= sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1, OV7660_CTL_ADVFH,
119 dev->sensor_flags, &v2);
121 return ret;
125 * @brief Set autoexposure for ov7660 sensors
127 * @param dev
129 * @return 0 or negative error value
131 * @author Neekhil
133 int ov7660_set_autoexposure(struct usb_microdia *dev)
135 __u8 buf[1];
136 int ret = 0;
138 /* Read current value of the I2C-register
139 * controlling AutoExposureControl:
141 ret = sn9c20x_read_i2c_data(dev, dev->sensor_slave_address,
142 1, OV7660_CTL_COM8, dev->sensor_flags, buf);
143 if (ret < 0) {
144 UDIA_ERROR("Error: setting of auto exposure failed: "
145 "error while reading from I2C-register OV7660_CTL_COM8");
146 return ret;
149 /* Determine new value for OV7660_CTL_COM8 register */
150 if (dev->vsettings.auto_exposure == 1) {
151 /* Enable automatic exposure: */
152 buf[0] |= 0x01;
153 } else if (dev->vsettings.auto_exposure == 0) {
154 /* Disable automatic exposure: */
155 buf[0] &= ~0x01;
156 } else
157 return -EINVAL;
159 /* Write new value to I2C-register OV7660_CTL_COM8 */
160 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address,
161 1, OV7660_CTL_COM8, dev->sensor_flags, buf);
162 if (ret < 0) {
163 UDIA_ERROR("Error: setting of auto exposure failed: "
164 "error while writing to I2C-register OV7660_CTL_COM8");
165 return ret;
167 return 0;
171 * @brief Set ov7660 sensors to soft-sleep mode
172 * @param dev
173 * @return 0 or negative error value
174 * @author Neekhil
176 int ov7660_sleep(struct usb_microdia *dev)
178 __u8 buf[1];
179 int ret = 0;
181 /* Set the sensor to Soft Sleep mode, Set O/P drive capability to 4X*/
182 buf[0] = 0x13;
183 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
184 OV7660_CTL_COM2, dev->sensor_flags, buf);
185 if (ret < 0)
186 goto errI2C;
188 return 0;
190 errI2C:
191 UDIA_ERROR("Setting Image Sensor to soft sleep failed(%d)!\n", ret);
192 return ret;
196 * @brief Get ov7660 sensors to wake up from soft-sleep mode
197 * @param dev
198 * @return 0 or negative error value
199 * @author Neekhil
201 int ov7660_wakeup(struct usb_microdia *dev)
203 __u8 buf[1];
204 int ret = 0;
206 /* Wake the sensor from Soft Sleep mode, Set O/P drive capability to 4X */
207 buf[0] = 0x03;
208 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
209 OV7660_CTL_COM2, dev->sensor_flags, buf);
210 if (ret < 0)
211 goto errI2C;
213 return 0;
215 errI2C:
216 UDIA_ERROR("Image Sensor failed to wake-up from soft sleep (%d)!\n", ret);
217 return ret;
221 * @brief Resets all the registers on ov7660 sensor
222 * @param dev
223 * @return 0 or negative error value
224 * @author Neekhil
226 int ov7660_reset(struct usb_microdia *dev)
228 __u8 buf[1];
229 int ret = 0;
231 /* Reset all registers to default value */
232 /* Set O/P format - RGB Selection, Set O/P format Raw RGB */
233 buf[0] = 0x85;
234 ret = sn9c20x_write_i2c_data(dev, dev->sensor_slave_address, 1,
235 OV7660_CTL_COM7, dev->sensor_flags, buf);
236 if (ret < 0)
237 goto errI2C;
239 return 0;
241 errI2C:
242 UDIA_ERROR("Failed to reset the Image Sensor (%d)!\n", ret);
243 return ret;