3 * drivers/media/video/omap/sensor_ov9640.c
5 * Ov9640 Sensor driver for OMAP camera sensor interface
7 * Author: Andy Lowe (source@mvista.com)
9 * Copyright (C) 2004 MontaVista Software, Inc.
10 * Copyright (C) 2004 Texas Instruments.
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program is licensed "as is" without any warranty of any
14 * kind, whether express or implied.
17 #include <linux/errno.h>
18 #include <linux/i2c.h>
19 #include <linux/videodev.h>
20 #include <media/video-buf.h>
21 #include <linux/delay.h>
22 #include <asm/mach-types.h>
23 #include <asm/arch/gpio.h>
25 #include "sensor_if.h"
27 #include "h3sensorpower.h"
28 #include "h4sensorpower.h"
31 struct ov9640_sensor {
33 struct i2c_client client;
34 int ver; /* OV9640 version */
37 static struct ov9640_sensor ov9640;
39 /* list of image formats supported by OV9640 sensor */
40 const static struct v4l2_fmtdesc ov9640_formats[] = {
42 /* Note: V4L2 defines RGB565 as:
45 * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3
47 * We interpret RGB565 as:
50 * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3
52 .description = "RGB565, le",
53 .pixelformat = V4L2_PIX_FMT_RGB565,
55 /* Note: V4L2 defines RGB565X as:
58 * b4 b3 b2 b1 b0 g5 g4 g3 g2 g1 g0 r4 r3 r2 r1 r0
60 * We interpret RGB565X as:
63 * r4 r3 r2 r1 r0 g5 g4 g3 g2 g1 g0 b4 b3 b2 b1 b0
65 .description = "RGB565, be",
66 .pixelformat = V4L2_PIX_FMT_RGB565X,
69 .description = "YUYV (YUV 4:2:2), packed",
70 .pixelformat = V4L2_PIX_FMT_YUYV,
72 .description = "UYVY, packed",
73 .pixelformat = V4L2_PIX_FMT_UYVY,
76 /* Note: V4L2 defines RGB555 as:
79 * g2 g1 g0 r4 r3 r2 r1 r0 x b4 b3 b2 b1 b0 g4 g3
81 * We interpret RGB555 as:
84 * g2 g1 g0 b4 b3 b2 b1 b0 x r4 r3 r2 r1 r0 g4 g3
86 .description = "RGB555, le",
87 .pixelformat = V4L2_PIX_FMT_RGB555,
89 /* Note: V4L2 defines RGB555X as:
92 * x b4 b3 b2 b1 b0 g4 g3 g2 g1 g0 r4 r3 r2 r1 r0
94 * We interpret RGB555X as:
97 * x r4 r3 r2 r1 r0 g4 g3 g2 g1 g0 b4 b3 b2 b1 b0
99 .description = "RGB555, be",
100 .pixelformat = V4L2_PIX_FMT_RGB555X,
104 #define NUM_CAPTURE_FORMATS ARRAY_SIZE(ov9640_formats)
105 #ifdef CONFIG_ARCH_OMAP24XX
106 #define NUM_OVERLAY_FORMATS 4
108 #define NUM_OVERLAY_FORMATS 2
111 /* register initialization tables for OV9640 */
113 #define OV9640_REG_TERM 0xFF /* terminating list entry for reg */
114 #define OV9640_VAL_TERM 0xFF /* terminating list entry for val */
116 /* common OV9640 register initialization for all image sizes, pixel formats,
119 const static struct ov9640_reg ov9640_common[] = {
120 #ifdef CONFIG_ARCH_OMAP24XX
121 { 0x12, 0x80 }, { 0x11, 0x80 }, { 0x13, 0x8F }, /* COM7, CLKRC, COM8 */
122 { 0x01, 0x80 }, { 0x02, 0x80 }, { 0x04, 0x00 }, /* BLUE, RED, COM1 */
123 { 0x0E, 0x81 }, { 0x0F, 0x4F }, { 0x14, 0x4A }, /* COM5, COM6, COM9 */
125 { 0x12, 0x80 }, { 0x11, 0x80 }, { 0x13, 0x88 }, /* COM7, CLKRC, COM8 */
126 { 0x01, 0x58 }, { 0x02, 0x24 }, { 0x04, 0x00 }, /* BLUE, RED, COM1 */
127 { 0x0E, 0x81 }, { 0x0F, 0x4F }, { 0x14, 0xcA }, /* COM5, COM6, COM9 */
129 { 0x16, 0x02 }, { 0x1B, 0x01 }, { 0x24, 0x70 }, /* ?, PSHFT, AEW */
130 { 0x25, 0x68 }, { 0x26, 0xD3 }, { 0x27, 0x90 }, /* AEB, VPT, BBIAS */
131 { 0x2A, 0x00 }, { 0x2B, 0x00 }, { 0x32, 0x24 }, /* EXHCH, EXHCL, HREF */
132 { 0x33, 0x02 }, { 0x37, 0x02 }, { 0x38, 0x13 }, /* CHLF, ADC, ACOM */
133 { 0x39, 0xF0 }, { 0x3A, 0x00 }, { 0x3B, 0x01 }, /* OFON, TSLB, COM11 */
134 { 0x3D, 0x90 }, { 0x3E, 0x02 }, { 0x3F, 0xF2 }, /* COM13, COM14, EDGE */
135 { 0x41, 0x02 }, { 0x42, 0xC8 }, /* COM16, COM17 */
136 { 0x43, 0xF0 }, { 0x44, 0x10 }, { 0x45, 0x6C }, /* ?, ?, ? */
137 { 0x46, 0x6C }, { 0x47, 0x44 }, { 0x48, 0x44 }, /* ?, ?, ? */
138 { 0x49, 0x03 }, { 0x59, 0x49 }, { 0x5A, 0x94 }, /* ?, ?, ? */
139 { 0x5B, 0x46 }, { 0x5C, 0x84 }, { 0x5D, 0x5C }, /* ?, ?, ? */
140 { 0x5E, 0x08 }, { 0x5F, 0x00 }, { 0x60, 0x14 }, /* ?, ?, ? */
141 { 0x61, 0xCE }, /* ? */
142 { 0x62, 0x70 }, { 0x63, 0x00 }, { 0x64, 0x04 }, /* LCC1, LCC2, LCC3 */
143 { 0x65, 0x00 }, { 0x66, 0x00 }, /* LCC4, LCC5 */
144 { 0x69, 0x00 }, { 0x6A, 0x3E }, { 0x6B, 0x3F }, /* HV, MBD, DBLV */
145 { 0x6C, 0x40 }, { 0x6D, 0x30 }, { 0x6E, 0x4B }, /* GSP1, GSP2, GSP3 */
146 { 0x6F, 0x60 }, { 0x70, 0x70 }, { 0x71, 0x70 }, /* GSP4, GSP5, GSP6 */
147 { 0x72, 0x70 }, { 0x73, 0x70 }, { 0x74, 0x60 }, /* GSP7, GSP8, GSP9 */
148 { 0x75, 0x60 }, { 0x76, 0x50 }, { 0x77, 0x48 }, /* GSP10,GSP11,GSP12 */
149 { 0x78, 0x3A }, { 0x79, 0x2E }, { 0x7A, 0x28 }, /* GSP13,GSP14,GSP15 */
150 { 0x7B, 0x22 }, { 0x7C, 0x04 }, { 0x7D, 0x07 }, /* GSP16,GST1, GST2 */
151 { 0x7E, 0x10 }, { 0x7F, 0x28 }, { 0x80, 0x36 }, /* GST3, GST4, GST5 */
152 { 0x81, 0x44 }, { 0x82, 0x52 }, { 0x83, 0x60 }, /* GST6, GST7, GST8 */
153 { 0x84, 0x6C }, { 0x85, 0x78 }, { 0x86, 0x8C }, /* GST9, GST10,GST11 */
154 { 0x87, 0x9E }, { 0x88, 0xBB }, { 0x89, 0xD2 }, /* GST12,GST13,GST14 */
155 #ifdef CONFIG_ARCH_OMAP24XX
156 { 0x8A, 0xE6 }, { 0x13, 0x8F }, { 0x00, 0x7F }, /* GST15, COM8 */
158 { 0x8A, 0xE6 }, { 0x13, 0xaF }, { 0x15, 0x02 }, /* GST15, COM8 */
159 { 0x22, 0x8a }, /* GROS */
161 { OV9640_REG_TERM, OV9640_VAL_TERM }
164 /* OV9640 register configuration for all combinations of pixel format and
167 /* YUV (YCbCr) QQCIF */
168 const static struct ov9640_reg qqcif_yuv[] = {
169 { 0x12, 0x08 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
170 { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
171 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
172 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
173 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
174 { 0x58, 0x0F }, /* MTXS */
175 { OV9640_REG_TERM, OV9640_VAL_TERM }
177 /* YUV (YCbCr) QQVGA */
178 const static struct ov9640_reg qqvga_yuv[] = {
179 { 0x12, 0x10 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
180 { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
181 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
182 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
183 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
184 { 0x58, 0x0F }, /* MTXS */
185 { OV9640_REG_TERM, OV9640_VAL_TERM }
187 /* YUV (YCbCr) QCIF */
188 const static struct ov9640_reg qcif_yuv[] = {
189 { 0x12, 0x08 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
190 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
191 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
192 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
193 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
194 { 0x58, 0x0F }, /* MTXS */
195 { OV9640_REG_TERM, OV9640_VAL_TERM }
197 /* YUV (YCbCr) QVGA */
198 const static struct ov9640_reg qvga_yuv[] = {
199 { 0x12, 0x10 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
200 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
201 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
202 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
203 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
204 { 0x58, 0x0F }, /* MTXS */
205 { OV9640_REG_TERM, OV9640_VAL_TERM }
207 /* YUV (YCbCr) CIF */
208 const static struct ov9640_reg cif_yuv[] = {
209 { 0x12, 0x20 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
210 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
211 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
212 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
213 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
214 { 0x58, 0x0F }, /* MTXS */
215 { OV9640_REG_TERM, OV9640_VAL_TERM }
217 /* YUV (YCbCr) VGA */
218 const static struct ov9640_reg vga_yuv[] = {
219 { 0x12, 0x40 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
220 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
221 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
222 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
223 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
224 { 0x58, 0x0F }, /* MTXS */
225 { OV9640_REG_TERM, OV9640_VAL_TERM }
227 /* YUV (YCbCr) SXGA */
228 const static struct ov9640_reg sxga_yuv[] = {
229 { 0x12, 0x00 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
230 { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
231 { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
232 { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
233 { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
234 { 0x58, 0x0F }, /* MTXS */
235 { OV9640_REG_TERM, OV9640_VAL_TERM }
238 const static struct ov9640_reg qqcif_565[] = {
239 { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
240 { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
241 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
242 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
243 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
244 { 0x58, 0x65 }, /* MTXS */
245 { OV9640_REG_TERM, OV9640_VAL_TERM }
248 const static struct ov9640_reg qqvga_565[] = {
249 { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
250 { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
251 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
252 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
253 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
254 { 0x58, 0x65 }, /* MTXS */
255 { OV9640_REG_TERM, OV9640_VAL_TERM }
258 const static struct ov9640_reg qcif_565[] = {
259 { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
260 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
261 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
262 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
263 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
264 { 0x58, 0x65 }, /* MTXS */
265 { OV9640_REG_TERM, OV9640_VAL_TERM }
268 const static struct ov9640_reg qvga_565[] = {
269 { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
270 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
271 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
272 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
273 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
274 { 0x58, 0x65 }, /* MTXS */
275 { OV9640_REG_TERM, OV9640_VAL_TERM }
278 const static struct ov9640_reg cif_565[] = {
279 { 0x12, 0x24 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
280 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
281 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
282 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
283 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
284 { 0x58, 0x65 }, /* MTXS */
285 { OV9640_REG_TERM, OV9640_VAL_TERM }
288 const static struct ov9640_reg vga_565[] = {
289 { 0x12, 0x44 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
290 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
291 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
292 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
293 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
294 { 0x58, 0x65 }, /* MTXS */
295 { OV9640_REG_TERM, OV9640_VAL_TERM }
298 const static struct ov9640_reg sxga_565[] = {
299 { 0x12, 0x04 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
300 { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
301 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
302 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
303 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
304 { 0x58, 0x65 }, /* MTXS */
305 { OV9640_REG_TERM, OV9640_VAL_TERM }
308 const static struct ov9640_reg qqcif_555[] = {
309 { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
310 { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
311 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
312 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
313 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
314 { 0x58, 0x65 }, /* MTXS */
315 { OV9640_REG_TERM, OV9640_VAL_TERM }
318 const static struct ov9640_reg qqvga_555[] = {
319 { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
320 { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
321 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
322 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
323 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
324 { 0x58, 0x65 }, /* MTXS */
325 { OV9640_REG_TERM, OV9640_VAL_TERM }
328 const static struct ov9640_reg qcif_555[] = {
329 { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
330 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
331 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
332 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
333 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
334 { 0x58, 0x65 }, /* MTXS */
335 { OV9640_REG_TERM, OV9640_VAL_TERM }
338 const static struct ov9640_reg qvga_555[] = {
339 { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
340 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
341 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
342 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
343 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
344 { 0x58, 0x65 }, /* MTXS */
345 { OV9640_REG_TERM, OV9640_VAL_TERM }
348 const static struct ov9640_reg cif_555[] = {
349 { 0x12, 0x24 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
350 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
351 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
352 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
353 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
354 { 0x58, 0x65 }, /* MTXS */
355 { OV9640_REG_TERM, OV9640_VAL_TERM }
358 const static struct ov9640_reg vga_555[] = {
359 { 0x12, 0x44 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
360 { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
361 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
362 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
363 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
364 { 0x58, 0x65 }, /* MTXS */
365 { OV9640_REG_TERM, OV9640_VAL_TERM }
368 const static struct ov9640_reg sxga_555[] = {
369 { 0x12, 0x04 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
370 { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
371 { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
372 { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
373 { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
374 { 0x58, 0x65 }, /* MTXS */
375 { OV9640_REG_TERM, OV9640_VAL_TERM }
380 #define DEF_AUTOGAIN 1
381 #define DEF_EXPOSURE 154
383 #define DEF_FREEZE_AGCAEC 0
385 #define DEF_RED (255 - DEF_BLUE)
390 /* Our own specific controls */
391 #define V4L2_CID_FREEZE_AGCAEC V4L2_CID_PRIVATE_BASE+0
392 #define V4L2_CID_AUTOEXPOSURE V4L2_CID_PRIVATE_BASE+1
393 #define V4L2_CID_LAST_PRIV V4L2_CID_AUTOEXPOSURE
396 static struct vcontrol {
397 struct v4l2_queryctrl qc;
403 { { V4L2_CID_GAIN, V4L2_CTRL_TYPE_INTEGER, "Gain", 0, 63, 1,
405 0, OV9640_GAIN, 0x3f, 0 },
406 { { V4L2_CID_AUTOGAIN, V4L2_CTRL_TYPE_BOOLEAN, "Auto Gain", 0, 1, 0,
408 0, OV9640_COM8, 0x04, 2 },
409 { { V4L2_CID_EXPOSURE, V4L2_CTRL_TYPE_INTEGER, "Exposure", 0, 255, 1,
411 0, OV9640_AECH, 0xff, 0 },
412 { { V4L2_CID_AUTOEXPOSURE, V4L2_CTRL_TYPE_BOOLEAN, "Auto Exposure", 0, 1, 0,
414 0, OV9640_COM8, 0x01, 0 },
415 { { V4L2_CID_FREEZE_AGCAEC, V4L2_CTRL_TYPE_BOOLEAN, "Freeze AGC/AEC", 0,1,0,
417 0, OV9640_COM9, 0x01, 0 },
418 { { V4L2_CID_RED_BALANCE, V4L2_CTRL_TYPE_INTEGER, "Red Balance", 0, 255, 1,
420 0, OV9640_RED, 0xff, 0 },
421 { { V4L2_CID_BLUE_BALANCE, V4L2_CTRL_TYPE_INTEGER, "Blue Balance", 0, 255, 1,
423 0, OV9640_BLUE, 0xff, 0 },
424 { { V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CTRL_TYPE_BOOLEAN, "Auto White Balance", 0,1,0,
426 0, OV9640_COM8, 0x02, 1 },
427 { { V4L2_CID_HFLIP, V4L2_CTRL_TYPE_BOOLEAN, "Mirror Image", 0, 1, 0,
429 0, OV9640_MVFP, 0x20, 5 },
430 { { V4L2_CID_VFLIP, V4L2_CTRL_TYPE_BOOLEAN, "Vertical Flip", 0, 1, 0,
432 0, OV9640_MVFP, 0x10, 4 },
435 #define NUM_CONTROLS ARRAY_SIZE(control)
437 const static struct ov9640_reg *
438 ov9640_reg_init[NUM_PIXEL_FORMATS][NUM_IMAGE_SIZES] =
440 { qqcif_yuv, qqvga_yuv, qcif_yuv, qvga_yuv, cif_yuv, vga_yuv, sxga_yuv },
441 { qqcif_565, qqvga_565, qcif_565, qvga_565, cif_565, vga_565, sxga_565 },
442 { qqcif_555, qqvga_555, qcif_555, qvga_555, cif_555, vga_555, sxga_555 },
447 * Read a value from a register in an OV9640 sensor device. The value is
449 * Returns zero if successful, or non-zero otherwise.
452 ov9640_read_reg(struct i2c_client *client, u8 reg, u8 *val)
455 struct i2c_msg msg[1];
456 unsigned char data[1];
458 if (!client->adapter)
461 msg->addr = client->addr;
466 err = i2c_transfer(client->adapter, msg, 1);
468 msg->flags = I2C_M_RD;
469 err = i2c_transfer(client->adapter, msg, 1);
478 /* Write a value to a register in an OV9640 sensor device.
479 * Returns zero if successful, or non-zero otherwise.
482 ov9640_write_reg(struct i2c_client *client, u8 reg, u8 val)
485 struct i2c_msg msg[1];
486 unsigned char data[2];
488 if (!client->adapter)
491 msg->addr = client->addr;
497 err = i2c_transfer(client->adapter, msg, 1);
504 ov9640_write_reg_mask(struct i2c_client *client, u8 reg, u8 *val, u8 mask)
512 /* need to do read - modify - write */
513 if ((rc = ov9640_read_reg(client, reg, &oldval)))
515 oldval &= (~mask); /* Clear the masked bits */
516 *val &= mask; /* Enforce mask on value */
517 newval = oldval | *val; /* Set the desired bits */
520 /* write the new value to the register */
521 if ((rc = ov9640_write_reg(client, reg, newval)))
524 if ((rc = ov9640_read_reg(client, reg, &newval)))
527 *val = newval & mask;
532 ov9640_read_reg_mask(struct i2c_client *client, u8 reg, u8 *val, u8 mask)
536 if ((rc = ov9640_read_reg(client, reg, val)))
543 /* Initialize a list of OV9640 registers.
544 * The list of registers is terminated by the pair of values
545 * { OV9640_REG_TERM, OV9640_VAL_TERM }.
546 * Returns zero if successful, or non-zero otherwise.
549 ov9640_write_regs(struct i2c_client *client, const struct ov9640_reg reglist[])
552 const struct ov9640_reg *next = reglist;
554 while (!((next->reg == OV9640_REG_TERM)
555 && (next->val == OV9640_VAL_TERM)))
557 err = ov9640_write_reg(client, next->reg, next->val);
566 /* Returns the index of the requested ID from the control structure array */
572 if (id < V4L2_CID_BASE)
575 for (i = NUM_CONTROLS - 1; i >= 0; i--)
576 if (control[i].qc.id == id)
583 /* Calculate the internal clock divisor (value of the CLKRC register) of the
584 * OV9640 given the image size, the frequency (in Hz) of its XCLK input and a
585 * desired frame period (in seconds). The frame period 'fper' is expressed as
586 * a fraction. The frame period is an input/output parameter.
587 * Returns the value of the OV9640 CLKRC register that will yield the frame
588 * period returned in 'fper' at the specified xclk frequency. The
589 * returned period will be as close to the requested period as possible.
592 ov9640_clkrc(enum image_size isize, unsigned long xclk, struct v4l2_fract *fper)
594 unsigned long fpm, fpm_max; /* frames per minute */
595 unsigned long divisor;
596 const unsigned long divisor_max = 64;
597 #ifdef CONFIG_ARCH_OMAP24XX
598 const static unsigned long clks_per_frame[] =
599 { 200000, 400000, 200000, 400000, 400000, 800000, 3200000 };
600 /* QQCIF QQVGA QCIF QVGA CIF VGA SXGA
601 * 199680,400000, 199680, 400000, 399360, 800000, 3200000
604 const static unsigned long clks_per_frame[] =
605 { 200000, 200000, 200000, 200000, 400000, 800000, 3200000 };
608 if (fper->numerator > 0)
609 fpm = (fper->denominator*60)/fper->numerator;
612 fpm_max = (xclk*60)/clks_per_frame[isize];
619 divisor = fpm_max/fpm;
620 if (divisor > divisor_max)
621 divisor = divisor_max;
622 fper->numerator = divisor*60;
623 fper->denominator = fpm_max;
625 /* try to reduce the fraction */
626 while (!(fper->denominator % 5) && !(fper->numerator % 5)) {
627 fper->numerator /= 5;
628 fper->denominator /= 5;
630 while (!(fper->denominator % 3) && !(fper->numerator % 3)) {
631 fper->numerator /= 3;
632 fper->denominator /= 3;
634 while (!(fper->denominator % 2) && !(fper->numerator % 2)) {
635 fper->numerator /= 2;
636 fper->denominator /= 2;
638 if (fper->numerator < fper->denominator) {
639 if (!(fper->denominator % fper->numerator)) {
640 fper->denominator /= fper->numerator;
645 if (!(fper->numerator % fper->denominator)) {
646 fper->numerator /= fper->denominator;
647 fper->denominator = 1;
651 /* we set bit 7 in CLKRC to enable the digital PLL */
652 return (0x80 | (divisor - 1));
655 /* Configure the OV9640 for a specified image size, pixel format, and frame
656 * period. xclk is the frequency (in Hz) of the xclk input to the OV9640.
657 * fper is the frame period (in seconds) expressed as a fraction.
658 * Returns zero if successful, or non-zero otherwise.
659 * The actual frame period is returned in fper.
662 ov9640_configure(struct i2c_client *client,
663 enum image_size isize,
664 enum pixel_format pfmt,
666 struct v4l2_fract *fper)
671 /* common register initialization */
672 err = ov9640_write_regs(client, ov9640_common);
676 /* configure image size and pixel format */
677 err = ov9640_write_regs(client, ov9640_reg_init[pfmt][isize]);
681 /* configure frame rate */
682 clkrc = ov9640_clkrc(isize, xclk, fper);
683 err = ov9640_write_reg(client, OV9640_CLKRC, clkrc);
695 if (machine_is_omap_h2())
698 #ifdef CONFIG_OMAP_OSK_MISTRAL
699 if (machine_is_omap_osk())
700 omap_set_gpio_dataout(11, 1);
703 if (machine_is_omap_h3()) {
704 err = h3_sensor_powerup();
709 if (machine_is_omap_h4()) {
710 err = h4_sensor_powerup();
718 ov9640_powerdown(void)
722 if (machine_is_omap_h2())
725 #ifdef CONFIG_OMAP_OSK_MISTRAL
726 if (machine_is_omap_osk())
727 omap_set_gpio_dataout(11, 0);
730 if (machine_is_omap_h3()) {
731 err = h3_sensor_powerdown();
736 if (machine_is_omap_h4()) {
737 err = h4_sensor_powerdown();
746 ov9640sensor_power_on(void *priv)
748 return ov9640_powerup();
752 ov9640sensor_power_off(void *priv)
754 return ov9640_powerdown();
757 /* Detect if an OV9640 is present, and if so which revision.
758 * A device is considered to be detected if the manufacturer ID (MIDH and MIDL)
759 * and the product ID (PID) registers match the expected values.
760 * Any value of the version ID (VER) register is accepted.
761 * Here are the version numbers we know about:
762 * 0x48 --> OV9640 Revision 1 or OV9640 Revision 2
763 * 0x49 --> OV9640 Revision 3
764 * Returns a negative error number if no device is detected, or the
765 * non-negative value of the version ID register if a device is detected.
768 ov9640_detect(struct i2c_client *client)
770 u8 midh, midl, pid, ver;
775 if (ov9640_read_reg(client, OV9640_MIDH, &midh))
777 if (ov9640_read_reg(client, OV9640_MIDL, &midl))
779 if (ov9640_read_reg(client, OV9640_PID, &pid))
781 if (ov9640_read_reg(client, OV9640_VER, &ver))
784 if ((midh != OV9640_MIDH_MAGIC)
785 || (midl != OV9640_MIDL_MAGIC)
786 || (pid != OV9640_PID_MAGIC))
788 /* We didn't read the values we expected, so
789 * this must not be an OV9640.
796 static struct i2c_driver ov9640sensor_i2c_driver;
798 /* This function registers an I2C client via i2c_attach_client() for an OV9640
799 * sensor device. If 'probe' is non-zero, then the I2C client is only
800 * registered if the device can be detected. If 'probe' is zero, then no
801 * device detection is attempted and the I2C client is always registered.
802 * Returns zero if an I2C client is successfully registered, or non-zero
806 ov9640_i2c_attach_client(struct i2c_adapter *adap, int addr, int probe)
808 struct ov9640_sensor *sensor = &ov9640;
809 struct i2c_client *client = &sensor->client;
813 return -EBUSY; /* our client is already attached */
816 client->driver = &ov9640sensor_i2c_driver;
817 client->adapter = adap;
818 strcpy(client->name, ov9640sensor_i2c_driver.driver.name);
820 err = i2c_attach_client(client);
822 client->adapter = NULL;
827 err = ov9640_detect(client);
829 i2c_detach_client(client);
830 client->adapter = NULL;
838 /* This function is called by i2c_del_adapter() and i2c_del_driver()
839 * if the adapter or driver with which this I2C client is associated is
840 * removed. This function unregisters the client via i2c_detach_client().
841 * Returns zero if the client is successfully detached, or non-zero
845 ov9640_i2c_detach_client(struct i2c_client *client)
849 if (!client->adapter)
850 return -ENODEV; /* our client isn't attached */
852 err = i2c_detach_client(client);
853 client->adapter = NULL;
858 /* This function will be called for each registered I2C bus adapter when our
859 * I2C driver is registered via i2c_add_driver(). It will also be called
860 * whenever a new I2C adapter is registered after our I2C driver is registered.
861 * This function probes the specified I2C bus adapter to determine if an
862 * OV9640 sensor device is present. If a device is detected, an I2C client
863 * is registered for it via ov9640_i2c_attach_client(). Note that we can't use
864 * the standard i2c_probe() function to look for the sensor because the OMAP
865 * I2C controller doesn't support probing.
866 * Returns zero if an OV9640 device is detected and an I2C client successfully
867 * registered for it, or non-zero otherwise.
870 ov9640_i2c_probe_adapter(struct i2c_adapter *adap)
872 return ov9640_i2c_attach_client(adap, OV9640_I2C_ADDR, 1);
875 /* Find the best match for a requested image capture size. The best match
876 * is chosen as the nearest match that has the same number or fewer pixels
877 * as the requested size, or the smallest image size if the requested size
878 * has fewer pixels than the smallest image.
880 static enum image_size
881 ov9640_find_size(unsigned int width, unsigned int height)
883 enum image_size isize;
884 unsigned long pixels = width*height;
886 for (isize = QQCIF; isize < SXGA; isize++) {
887 if (ov9640_sizes[isize + 1].height*
888 ov9640_sizes[isize + 1].width > pixels)
896 /* following are sensor interface functions implemented by
897 * OV9640 sensor driver.
900 ov9640sensor_query_control(struct v4l2_queryctrl *qc, void *priv)
904 i = find_vctrl (qc->id);
906 qc->flags = V4L2_CTRL_FLAG_DISABLED;
917 ov9640sensor_get_control(struct v4l2_control *vc, void *priv)
919 struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
920 struct i2c_client *client = &sensor->client;
922 struct vcontrol * lvc;
924 i = find_vctrl(vc->id);
929 if (ov9640_read_reg_mask(client, lvc->reg, (u8 *)&val, lvc->mask))
932 val = val >> lvc->start_bit;
934 vc->value = lvc->current_value = val;
941 ov9640sensor_set_control(struct v4l2_control *vc, void *priv)
943 struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
944 struct i2c_client *client = &sensor->client;
945 struct vcontrol *lvc;
949 i = find_vctrl(vc->id);
954 val = val << lvc->start_bit;
955 if (ov9640_write_reg_mask(client, lvc->reg, (u8 *)&val, (u8)lvc->mask))
958 val = val>> lvc->start_bit;
960 lvc->current_value = val;
966 /* Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
969 ov9640sensor_enum_pixformat(struct v4l2_fmtdesc *fmt, void *priv)
971 int index = fmt->index;
972 enum v4l2_buf_type type = fmt->type;
974 memset(fmt, 0, sizeof(*fmt));
979 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
980 if (index >= NUM_CAPTURE_FORMATS)
984 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
985 if (index >= NUM_OVERLAY_FORMATS)
993 fmt->flags = ov9640_formats[index].flags;
994 strlcpy(fmt->description, ov9640_formats[index].description, sizeof(fmt->description));
995 fmt->pixelformat = ov9640_formats[index].pixelformat;
1000 /* Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This
1001 * ioctl is used to negotiate the image capture size and pixel format
1002 * without actually making it take effect.
1005 ov9640sensor_try_format(struct v4l2_pix_format *pix, void *priv)
1007 enum image_size isize;
1010 isize = ov9640_find_size(pix->width, pix->height);
1011 pix->width = ov9640_sizes[isize].width;
1012 pix->height = ov9640_sizes[isize].height;
1013 for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
1014 if (pix->pixelformat == ov9640_formats[ifmt].pixelformat)
1017 if (ifmt == NUM_CAPTURE_FORMATS)
1019 pix->pixelformat = ov9640_formats[ifmt].pixelformat;
1020 pix->field = V4L2_FIELD_NONE;
1021 pix->bytesperline = pix->width*2;
1022 pix->sizeimage = pix->bytesperline*pix->height;
1024 switch (pix->pixelformat) {
1025 case V4L2_PIX_FMT_YUYV:
1026 case V4L2_PIX_FMT_UYVY:
1028 pix->colorspace = V4L2_COLORSPACE_JPEG;
1030 case V4L2_PIX_FMT_RGB565:
1031 case V4L2_PIX_FMT_RGB565X:
1032 case V4L2_PIX_FMT_RGB555:
1033 case V4L2_PIX_FMT_RGB555X:
1034 pix->colorspace = V4L2_COLORSPACE_SRGB;
1040 /* Given the image capture format in pix, the nominal frame period in
1041 * timeperframe, calculate the required xclk frequency
1042 * The nominal xclk input frequency of the OV9640 is 24MHz, maximum
1043 * frequency is 48MHz, and minimum frequency is 10MHz.
1045 static unsigned long
1046 ov9640sensor_calc_xclk(struct v4l2_pix_format *pix,
1047 struct v4l2_fract *timeperframe, void *priv)
1049 unsigned long tgt_xclk; /* target xclk */
1050 unsigned long tgt_fpm; /* target frames per minute */
1051 enum image_size isize;
1053 /* We use arbitrary rules to select the xclk frequency. If the
1054 * capture size is VGA and the frame rate is greater than 900
1055 * frames per minute, or if the capture size is SXGA and the
1056 * frame rate is greater than 450 frames per minutes, then the
1057 * xclk frequency will be set to 48MHz. Otherwise, the xclk
1058 * frequency will be set to 24MHz. If the mclk frequency is such that
1059 * the target xclk frequency is not achievable, then xclk will be set
1060 * as close as to the target as possible.
1062 if ((timeperframe->numerator == 0)
1063 || (timeperframe->denominator == 0))
1065 /* supply a default nominal_timeperframe of 15 fps */
1066 timeperframe->numerator = 1;
1067 timeperframe->denominator = 15;
1069 tgt_fpm = (timeperframe->denominator*60)
1070 / timeperframe->numerator;
1071 tgt_xclk = 24000000;
1072 isize = ov9640_find_size(pix->width, pix->height);
1076 tgt_xclk = 48000000;
1080 tgt_xclk = 48000000;
1088 /* Given a capture format in pix, the frame period in timeperframe, and
1089 * the xclk frequency, set the capture format of the OV9640 sensor.
1090 * The actual frame period will be returned in timeperframe.
1093 ov9640sensor_configure(struct v4l2_pix_format *pix, unsigned long xclk,
1094 struct v4l2_fract *timeperframe, void *priv)
1096 struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
1097 enum pixel_format pfmt = YUV;
1099 switch (pix->pixelformat) {
1100 case V4L2_PIX_FMT_RGB565:
1101 case V4L2_PIX_FMT_RGB565X:
1104 case V4L2_PIX_FMT_RGB555:
1105 case V4L2_PIX_FMT_RGB555X:
1108 case V4L2_PIX_FMT_YUYV:
1109 case V4L2_PIX_FMT_UYVY:
1114 return ov9640_configure(&sensor->client,
1115 ov9640_find_size(pix->width, pix->height),
1116 pfmt, xclk, timeperframe);
1119 /* Prepare for the driver to exit.
1120 * Balances ov9640sensor_init().
1121 * This function must de-initialize the sensor and its associated data
1125 ov9640sensor_cleanup(void *priv)
1127 struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
1130 i2c_del_driver(&ov9640sensor_i2c_driver);
1137 static struct i2c_driver ov9640sensor_i2c_driver = {
1141 .id = I2C_DRIVERID_MISC, /*FIXME:accroding to i2c-ids.h */
1142 .attach_adapter = ov9640_i2c_probe_adapter,
1143 .detach_client = ov9640_i2c_detach_client,
1147 /* Initialize the OV9640 sensor.
1148 * This routine allocates and initializes the data structure for the sensor,
1149 * powers up the sensor, registers the I2C driver, and sets a default image
1150 * capture format in pix. The capture format is not actually programmed
1151 * into the OV9640 sensor by this routine.
1152 * This function must return a non-NULL value to indicate that
1153 * initialization is successful.
1156 ov9640sensor_init(struct v4l2_pix_format *pix)
1158 struct ov9640_sensor *sensor = &ov9640;
1161 memset(sensor, 0, sizeof(*sensor));
1163 /* power-up the sensor */
1164 if (ov9640_powerup())
1167 err = i2c_add_driver(&ov9640sensor_i2c_driver);
1169 printk(KERN_ERR "Failed to register OV9640 I2C client.\n");
1172 if (!sensor->client.adapter) {
1174 "Failed to detect OV9640 sensor chip.\n");
1179 "OV9640 sensor chip version 0x%02x detected\n", sensor->ver);
1181 /* Make the default capture format QCIF RGB565 */
1182 pix->width = ov9640_sizes[QCIF].width;
1183 pix->height = ov9640_sizes[QCIF].height;
1184 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1185 ov9640sensor_try_format(pix, NULL);
1187 return (void *)sensor;
1190 struct omap_camera_sensor camera_sensor_if = {
1193 .init = ov9640sensor_init,
1194 .cleanup = ov9640sensor_cleanup,
1195 .enum_pixformat = ov9640sensor_enum_pixformat,
1196 .try_format = ov9640sensor_try_format,
1197 .calc_xclk = ov9640sensor_calc_xclk,
1198 .configure = ov9640sensor_configure,
1199 .query_control = ov9640sensor_query_control,
1200 .get_control = ov9640sensor_get_control,
1201 .set_control = ov9640sensor_set_control,
1202 .power_on = ov9640sensor_power_on,
1203 .power_off = ov9640sensor_power_off,
1205 EXPORT_SYMBOL_GPL(camera_sensor_if);
1207 MODULE_LICENSE("GPL");
1210 void print_ov9640_regs(void *priv)
1212 struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
1214 for (reg=0x00; reg <=0x8A; reg++)
1215 if (ov9640_read_reg(&sensor->client,reg,&val))
1216 printk("error reading %x\n", reg);
1218 printk("reg %x = %x\n", reg, val);