V4L/DVB (4842): Updated camera driver
[pandora-kernel.git] / drivers / media / video / ov7670.c
1 /*
2  * A V4L2 driver for OmniVision OV7670 cameras.
3  *
4  * Copyright 2006 One Laptop Per Child Association, Inc.  Written
5  * by Jonathan Corbet with substantial inspiration from Mark
6  * McClelland's ovcamchip code.
7  *
8  * This file may be distributed under the terms of the GNU General
9  * Public License, version 2.
10  */
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/slab.h>
15 #include <linux/delay.h>
16 #include <linux/videodev.h>
17 #include <media/v4l2-common.h>
18 #include <linux/i2c.h>
19
20
21 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net.");
22 MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
23 MODULE_LICENSE("GPL");
24
25 /*
26  * Basic window sizes.  These probably belong somewhere more globally
27  * useful.
28  */
29 #define VGA_WIDTH       640
30 #define VGA_HEIGHT      480
31 #define QVGA_WIDTH      320
32 #define QVGA_HEIGHT     240
33 #define CIF_WIDTH       352
34 #define CIF_HEIGHT      288
35 #define QCIF_WIDTH      176
36 #define QCIF_HEIGHT     144
37
38 /*
39  * The 7670 sits on i2c with ID 0x42
40  */
41 #define OV7670_I2C_ADDR 0x42
42
43 /* Registers */
44 #define REG_GAIN        0x00    /* Gain lower 8 bits (rest in vref) */
45 #define REG_BLUE        0x01    /* blue gain */
46 #define REG_RED         0x02    /* red gain */
47 #define REG_VREF        0x03    /* Pieces of GAIN, VSTART, VSTOP */
48 #define REG_COM1        0x04    /* Control 1 */
49 #define  COM1_CCIR656     0x40  /* CCIR656 enable */
50 #define REG_BAVE        0x05    /* U/B Average level */
51 #define REG_GbAVE       0x06    /* Y/Gb Average level */
52 #define REG_AECHH       0x07    /* AEC MS 5 bits */
53 #define REG_RAVE        0x08    /* V/R Average level */
54 #define REG_COM2        0x09    /* Control 2 */
55 #define  COM2_SSLEEP      0x10  /* Soft sleep mode */
56 #define REG_PID         0x0a    /* Product ID MSB */
57 #define REG_VER         0x0b    /* Product ID LSB */
58 #define REG_COM3        0x0c    /* Control 3 */
59 #define  COM3_SWAP        0x40    /* Byte swap */
60 #define  COM3_SCALEEN     0x08    /* Enable scaling */
61 #define  COM3_DCWEN       0x04    /* Enable downsamp/crop/window */
62 #define REG_COM4        0x0d    /* Control 4 */
63 #define REG_COM5        0x0e    /* All "reserved" */
64 #define REG_COM6        0x0f    /* Control 6 */
65 #define REG_AECH        0x10    /* More bits of AEC value */
66 #define REG_CLKRC       0x11    /* Clocl control */
67 #define   CLK_EXT         0x40    /* Use external clock directly */
68 #define   CLK_SCALE       0x3f    /* Mask for internal clock scale */
69 #define REG_COM7        0x12    /* Control 7 */
70 #define   COM7_RESET      0x80    /* Register reset */
71 #define   COM7_FMT_MASK   0x38
72 #define   COM7_FMT_VGA    0x00
73 #define   COM7_FMT_CIF    0x20    /* CIF format */
74 #define   COM7_FMT_QVGA   0x10    /* QVGA format */
75 #define   COM7_FMT_QCIF   0x08    /* QCIF format */
76 #define   COM7_RGB        0x04    /* bits 0 and 2 - RGB format */
77 #define   COM7_YUV        0x00    /* YUV */
78 #define   COM7_BAYER      0x01    /* Bayer format */
79 #define   COM7_PBAYER     0x05    /* "Processed bayer" */
80 #define REG_COM8        0x13    /* Control 8 */
81 #define   COM8_FASTAEC    0x80    /* Enable fast AGC/AEC */
82 #define   COM8_AECSTEP    0x40    /* Unlimited AEC step size */
83 #define   COM8_BFILT      0x20    /* Band filter enable */
84 #define   COM8_AGC        0x04    /* Auto gain enable */
85 #define   COM8_AWB        0x02    /* White balance enable */
86 #define   COM8_AEC        0x01    /* Auto exposure enable */
87 #define REG_COM9        0x14    /* Control 9  - gain ceiling */
88 #define REG_COM10       0x15    /* Control 10 */
89 #define   COM10_HSYNC     0x40    /* HSYNC instead of HREF */
90 #define   COM10_PCLK_HB   0x20    /* Suppress PCLK on horiz blank */
91 #define   COM10_HREF_REV  0x08    /* Reverse HREF */
92 #define   COM10_VS_LEAD   0x04    /* VSYNC on clock leading edge */
93 #define   COM10_VS_NEG    0x02    /* VSYNC negative */
94 #define   COM10_HS_NEG    0x01    /* HSYNC negative */
95 #define REG_HSTART      0x17    /* Horiz start high bits */
96 #define REG_HSTOP       0x18    /* Horiz stop high bits */
97 #define REG_VSTART      0x19    /* Vert start high bits */
98 #define REG_VSTOP       0x1a    /* Vert stop high bits */
99 #define REG_PSHFT       0x1b    /* Pixel delay after HREF */
100 #define REG_MIDH        0x1c    /* Manuf. ID high */
101 #define REG_MIDL        0x1d    /* Manuf. ID low */
102 #define REG_MVFP        0x1e    /* Mirror / vflip */
103 #define   MVFP_MIRROR     0x20    /* Mirror image */
104 #define   MVFP_FLIP       0x10    /* Vertical flip */
105
106 #define REG_AEW         0x24    /* AGC upper limit */
107 #define REG_AEB         0x25    /* AGC lower limit */
108 #define REG_VPT         0x26    /* AGC/AEC fast mode op region */
109 #define REG_HSYST       0x30    /* HSYNC rising edge delay */
110 #define REG_HSYEN       0x31    /* HSYNC falling edge delay */
111 #define REG_HREF        0x32    /* HREF pieces */
112 #define REG_TSLB        0x3a    /* lots of stuff */
113 #define   TSLB_YLAST      0x04    /* UYVY or VYUY - see com13 */
114 #define REG_COM11       0x3b    /* Control 11 */
115 #define   COM11_NIGHT     0x80    /* NIght mode enable */
116 #define   COM11_NMFR      0x60    /* Two bit NM frame rate */
117 #define   COM11_HZAUTO    0x10    /* Auto detect 50/60 Hz */
118 #define   COM11_50HZ      0x08    /* Manual 50Hz select */
119 #define   COM11_EXP       0x02
120 #define REG_COM12       0x3c    /* Control 12 */
121 #define   COM12_HREF      0x80    /* HREF always */
122 #define REG_COM13       0x3d    /* Control 13 */
123 #define   COM13_GAMMA     0x80    /* Gamma enable */
124 #define   COM13_UVSAT     0x40    /* UV saturation auto adjustment */
125 #define   COM13_UVSWAP    0x01    /* V before U - w/TSLB */
126 #define REG_COM14       0x3e    /* Control 14 */
127 #define   COM14_DCWEN     0x10    /* DCW/PCLK-scale enable */
128 #define REG_EDGE        0x3f    /* Edge enhancement factor */
129 #define REG_COM15       0x40    /* Control 15 */
130 #define   COM15_R10F0     0x00    /* Data range 10 to F0 */
131 #define   COM15_R01FE     0x80    /*            01 to FE */
132 #define   COM15_R00FF     0xc0    /*            00 to FF */
133 #define   COM15_RGB565    0x10    /* RGB565 output */
134 #define   COM15_RGB555    0x30    /* RGB555 output */
135 #define REG_COM16       0x41    /* Control 16 */
136 #define   COM16_AWBGAIN   0x08    /* AWB gain enable */
137 #define REG_COM17       0x42    /* Control 17 */
138 #define   COM17_AECWIN    0xc0    /* AEC window - must match COM4 */
139 #define   COM17_CBAR      0x08    /* DSP Color bar */
140
141 /*
142  * This matrix defines how the colors are generated, must be
143  * tweaked to adjust hue and saturation.
144  *
145  * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
146  *
147  * They are nine-bit signed quantities, with the sign bit
148  * stored in 0x58.  Sign for v-red is bit 0, and up from there.
149  */
150 #define REG_CMATRIX_BASE 0x4f
151 #define   CMATRIX_LEN 6
152 #define REG_CMATRIX_SIGN 0x58
153
154
155 #define REG_BRIGHT      0x55    /* Brightness */
156 #define REG_CONTRAS     0x56    /* Contrast control */
157
158 #define REG_GFIX        0x69    /* Fix gain control */
159
160 #define REG_RGB444      0x8c    /* RGB 444 control */
161 #define   R444_ENABLE     0x02    /* Turn on RGB444, overrides 5x5 */
162 #define   R444_RGBX       0x01    /* Empty nibble at end */
163
164 #define REG_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
165 #define REG_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
166
167 #define REG_BD50MAX     0xa5    /* 50hz banding step limit */
168 #define REG_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
169 #define REG_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
170 #define REG_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
171 #define REG_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
172 #define REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
173 #define REG_BD60MAX     0xab    /* 60hz banding step limit */
174
175
176 /*
177  * Information we maintain about a known sensor.
178  */
179 struct ov7670_format_struct;  /* coming later */
180 struct ov7670_info {
181         struct ov7670_format_struct *fmt;  /* Current format */
182         unsigned char sat;              /* Saturation value */
183         int hue;                        /* Hue value */
184 };
185
186
187
188
189 /*
190  * The default register settings, as obtained from OmniVision.  There
191  * is really no making sense of most of these - lots of "reserved" values
192  * and such.
193  *
194  * These settings give VGA YUYV.
195  */
196
197 struct regval_list {
198         unsigned char reg_num;
199         unsigned char value;
200 };
201
202 static struct regval_list ov7670_default_regs[] = {
203         { REG_COM7, COM7_RESET },
204 /*
205  * Clock scale: 3 = 15fps
206  *              2 = 20fps
207  *              1 = 30fps
208  */
209         { REG_CLKRC, 0x1 },     /* OV: clock scale (30 fps) */
210         { REG_TSLB,  0x04 },    /* OV */
211         { REG_COM7, 0 },        /* VGA */
212         /*
213          * Set the hardware window.  These values from OV don't entirely
214          * make sense - hstop is less than hstart.  But they work...
215          */
216         { REG_HSTART, 0x13 },   { REG_HSTOP, 0x01 },
217         { REG_HREF, 0xb6 },     { REG_VSTART, 0x02 },
218         { REG_VSTOP, 0x7a },    { REG_VREF, 0x0a },
219
220         { REG_COM3, 0 },        { REG_COM14, 0 },
221         /* Mystery scaling numbers */
222         { 0x70, 0x3a },         { 0x71, 0x35 },
223         { 0x72, 0x11 },         { 0x73, 0xf0 },
224         { 0xa2, 0x02 },         { REG_COM10, 0x0 },
225
226         /* Gamma curve values */
227         { 0x7a, 0x20 },         { 0x7b, 0x10 },
228         { 0x7c, 0x1e },         { 0x7d, 0x35 },
229         { 0x7e, 0x5a },         { 0x7f, 0x69 },
230         { 0x80, 0x76 },         { 0x81, 0x80 },
231         { 0x82, 0x88 },         { 0x83, 0x8f },
232         { 0x84, 0x96 },         { 0x85, 0xa3 },
233         { 0x86, 0xaf },         { 0x87, 0xc4 },
234         { 0x88, 0xd7 },         { 0x89, 0xe8 },
235
236         /* AGC and AEC parameters.  Note we start by disabling those features,
237            then turn them only after tweaking the values. */
238         { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT },
239         { REG_GAIN, 0 },        { REG_AECH, 0 },
240         { REG_COM4, 0x40 }, /* magic reserved bit */
241         { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
242         { REG_BD50MAX, 0x05 },  { REG_BD60MAX, 0x07 },
243         { REG_AEW, 0x95 },      { REG_AEB, 0x33 },
244         { REG_VPT, 0xe3 },      { REG_HAECC1, 0x78 },
245         { REG_HAECC2, 0x68 },   { 0xa1, 0x03 }, /* magic */
246         { REG_HAECC3, 0xd8 },   { REG_HAECC4, 0xd8 },
247         { REG_HAECC5, 0xf0 },   { REG_HAECC6, 0x90 },
248         { REG_HAECC7, 0x94 },
249         { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC },
250
251         /* Almost all of these are magic "reserved" values.  */
252         { REG_COM5, 0x61 },     { REG_COM6, 0x4b },
253         { 0x16, 0x02 },         { REG_MVFP, 0x07|MVFP_MIRROR },
254         { 0x21, 0x02 },         { 0x22, 0x91 },
255         { 0x29, 0x07 },         { 0x33, 0x0b },
256         { 0x35, 0x0b },         { 0x37, 0x1d },
257         { 0x38, 0x71 },         { 0x39, 0x2a },
258         { REG_COM12, 0x78 },    { 0x4d, 0x40 },
259         { 0x4e, 0x20 },         { REG_GFIX, 0 },
260         { 0x6b, 0x4a },         { 0x74, 0x10 },
261         { 0x8d, 0x4f },         { 0x8e, 0 },
262         { 0x8f, 0 },            { 0x90, 0 },
263         { 0x91, 0 },            { 0x96, 0 },
264         { 0x9a, 0 },            { 0xb0, 0x84 },
265         { 0xb1, 0x0c },         { 0xb2, 0x0e },
266         { 0xb3, 0x82 },         { 0xb8, 0x0a },
267
268         /* More reserved magic, some of which tweaks white balance */
269         { 0x43, 0x0a },         { 0x44, 0xf0 },
270         { 0x45, 0x34 },         { 0x46, 0x58 },
271         { 0x47, 0x28 },         { 0x48, 0x3a },
272         { 0x59, 0x88 },         { 0x5a, 0x88 },
273         { 0x5b, 0x44 },         { 0x5c, 0x67 },
274         { 0x5d, 0x49 },         { 0x5e, 0x0e },
275         { 0x6c, 0x0a },         { 0x6d, 0x55 },
276         { 0x6e, 0x11 },         { 0x6f, 0x9f }, /* "9e for advance AWB" */
277         { 0x6a, 0x40 },         { REG_BLUE, 0x40 },
278         { REG_RED, 0x60 },
279         { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB },
280
281         /* Matrix coefficients */
282         { 0x4f, 0x80 },         { 0x50, 0x80 },
283         { 0x51, 0 },            { 0x52, 0x22 },
284         { 0x53, 0x5e },         { 0x54, 0x80 },
285         { 0x58, 0x9e },
286
287         { REG_COM16, COM16_AWBGAIN },   { REG_EDGE, 0 },
288         { 0x75, 0x05 },         { 0x76, 0xe1 },
289         { 0x4c, 0 },            { 0x77, 0x01 },
290         { REG_COM13, 0xc3 },    { 0x4b, 0x09 },
291         { 0xc9, 0x60 },         { REG_COM16, 0x38 },
292         { 0x56, 0x40 },
293
294         { 0x34, 0x11 },         { REG_COM11, COM11_EXP },
295         { 0xa4, 0x88 },         { 0x96, 0 },
296         { 0x97, 0x30 },         { 0x98, 0x20 },
297         { 0x99, 0x30 },         { 0x9a, 0x84 },
298         { 0x9b, 0x29 },         { 0x9c, 0x03 },
299         { 0x9d, 0x4c },         { 0x9e, 0x3f },
300         { 0x78, 0x04 },
301
302         /* Extra-weird stuff.  Some sort of multiplexor register */
303         { 0x79, 0x01 },         { 0xc8, 0xf0 },
304         { 0x79, 0x0f },         { 0xc8, 0x00 },
305         { 0x79, 0x10 },         { 0xc8, 0x7e },
306         { 0x79, 0x0a },         { 0xc8, 0x80 },
307         { 0x79, 0x0b },         { 0xc8, 0x01 },
308         { 0x79, 0x0c },         { 0xc8, 0x0f },
309         { 0x79, 0x0d },         { 0xc8, 0x20 },
310         { 0x79, 0x09 },         { 0xc8, 0x80 },
311         { 0x79, 0x02 },         { 0xc8, 0xc0 },
312         { 0x79, 0x03 },         { 0xc8, 0x40 },
313         { 0x79, 0x05 },         { 0xc8, 0x30 },
314         { 0x79, 0x26 },
315
316         { 0xff, 0xff }, /* END MARKER */
317 };
318
319
320 /*
321  * Here we'll try to encapsulate the changes for just the output
322  * video format.
323  *
324  * RGB656 and YUV422 come from OV; RGB444 is homebrewed.
325  *
326  * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why.
327  */
328
329
330 static struct regval_list ov7670_fmt_yuv422[] = {
331         { REG_COM7, 0x0 },  /* Selects YUV mode */
332         { REG_RGB444, 0 },      /* No RGB444 please */
333         { REG_COM1, 0 },
334         { REG_COM15, COM15_R00FF },
335         { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
336         { 0x4f, 0x80 },         /* "matrix coefficient 1" */
337         { 0x50, 0x80 },         /* "matrix coefficient 2" */
338         { 0x51, 0    },         /* vb */
339         { 0x52, 0x22 },         /* "matrix coefficient 4" */
340         { 0x53, 0x5e },         /* "matrix coefficient 5" */
341         { 0x54, 0x80 },         /* "matrix coefficient 6" */
342         { REG_COM13, COM13_GAMMA|COM13_UVSAT },
343         { 0xff, 0xff },
344 };
345
346 static struct regval_list ov7670_fmt_rgb565[] = {
347         { REG_COM7, COM7_RGB }, /* Selects RGB mode */
348         { REG_RGB444, 0 },      /* No RGB444 please */
349         { REG_COM1, 0x0 },
350         { REG_COM15, COM15_RGB565 },
351         { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
352         { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
353         { 0x50, 0xb3 },         /* "matrix coefficient 2" */
354         { 0x51, 0    },         /* vb */
355         { 0x52, 0x3d },         /* "matrix coefficient 4" */
356         { 0x53, 0xa7 },         /* "matrix coefficient 5" */
357         { 0x54, 0xe4 },         /* "matrix coefficient 6" */
358         { REG_COM13, COM13_GAMMA|COM13_UVSAT },
359         { 0xff, 0xff },
360 };
361
362 static struct regval_list ov7670_fmt_rgb444[] = {
363         { REG_COM7, COM7_RGB }, /* Selects RGB mode */
364         { REG_RGB444, R444_ENABLE },    /* Enable xxxxrrrr ggggbbbb */
365         { REG_COM1, 0x40 },     /* Magic reserved bit */
366         { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */
367         { REG_COM9, 0x38 },     /* 16x gain ceiling; 0x8 is reserved bit */
368         { 0x4f, 0xb3 },         /* "matrix coefficient 1" */
369         { 0x50, 0xb3 },         /* "matrix coefficient 2" */
370         { 0x51, 0    },         /* vb */
371         { 0x52, 0x3d },         /* "matrix coefficient 4" */
372         { 0x53, 0xa7 },         /* "matrix coefficient 5" */
373         { 0x54, 0xe4 },         /* "matrix coefficient 6" */
374         { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 },  /* Magic rsvd bit */
375         { 0xff, 0xff },
376 };
377
378
379
380
381 /*
382  * Low-level register I/O.
383  */
384
385 static int ov7670_read(struct i2c_client *c, unsigned char reg,
386                 unsigned char *value)
387 {
388         int ret;
389
390         ret = i2c_smbus_read_byte_data(c, reg);
391         if (ret >= 0)
392                 *value = (unsigned char) ret;
393         return ret;
394 }
395
396
397 static int ov7670_write(struct i2c_client *c, unsigned char reg,
398                 unsigned char value)
399 {
400         return i2c_smbus_write_byte_data(c, reg, value);
401 }
402
403
404 /*
405  * Write a list of register settings; ff/ff stops the process.
406  */
407 static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals)
408 {
409         while (vals->reg_num != 0xff || vals->value != 0xff) {
410                 int ret = ov7670_write(c, vals->reg_num, vals->value);
411                 if (ret < 0)
412                         return ret;
413                 vals++;
414         }
415         return 0;
416 }
417
418
419 /*
420  * Stuff that knows about the sensor.
421  */
422 static void ov7670_reset(struct i2c_client *client)
423 {
424         ov7670_write(client, REG_COM7, COM7_RESET);
425         msleep(1);
426 }
427
428
429 static int ov7670_init(struct i2c_client *client)
430 {
431         return ov7670_write_array(client, ov7670_default_regs);
432 }
433
434
435
436 static int ov7670_detect(struct i2c_client *client)
437 {
438         unsigned char v;
439         int ret;
440
441         ret = ov7670_init(client);
442         if (ret < 0)
443                 return ret;
444         ret = ov7670_read(client, REG_MIDH, &v);
445         if (ret < 0)
446                 return ret;
447         if (v != 0x7f) /* OV manuf. id. */
448                 return -ENODEV;
449         ret = ov7670_read(client, REG_MIDL, &v);
450         if (ret < 0)
451                 return ret;
452         if (v != 0xa2)
453                 return -ENODEV;
454         /*
455          * OK, we know we have an OmniVision chip...but which one?
456          */
457         ret = ov7670_read(client, REG_PID, &v);
458         if (ret < 0)
459                 return ret;
460         if (v != 0x76)  /* PID + VER = 0x76 / 0x73 */
461                 return -ENODEV;
462         ret = ov7670_read(client, REG_VER, &v);
463         if (ret < 0)
464                 return ret;
465         if (v != 0x73)  /* PID + VER = 0x76 / 0x73 */
466                 return -ENODEV;
467         return 0;
468 }
469
470
471 /*
472  * Store information about the video data format.  The color matrix
473  * is deeply tied into the format, so keep the relevant values here.
474  * The magic matrix nubmers come from OmniVision.
475  */
476 static struct ov7670_format_struct {
477         __u8 *desc;
478         __u32 pixelformat;
479         struct regval_list *regs;
480         int cmatrix[CMATRIX_LEN];
481 } ov7670_formats[] = {
482         {
483                 .desc           = "YUYV 4:2:2",
484                 .pixelformat    = V4L2_PIX_FMT_YUYV,
485                 .regs           = ov7670_fmt_yuv422,
486                 .cmatrix        = { 128, -128, 0, -34, -94, 128 },
487         },
488         {
489                 .desc           = "RGB 444",
490                 .pixelformat    = V4L2_PIX_FMT_RGB444,
491                 .regs           = ov7670_fmt_rgb444,
492                 .cmatrix        = { 179, -179, 0, -61, -176, 228 },
493         },
494         {
495                 .desc           = "RGB 565",
496                 .pixelformat    = V4L2_PIX_FMT_RGB565,
497                 .regs           = ov7670_fmt_rgb565,
498                 .cmatrix        = { 179, -179, 0, -61, -176, 228 },
499         },
500         /*
501          * Pretend we do RGB32.  This is here on the assumption that the
502          * upper layer will reformat RGB444 appropriately.
503          *
504          * The entire purpose for this thing's existence is to enable easy
505          * display of RGB444 for debugging purposes.  It will come out soon.
506          */
507         {
508                 .desc           = "RGB32 (faked)",
509                 .pixelformat    = V4L2_PIX_FMT_RGB32,
510                 .regs           = ov7670_fmt_rgb444,
511                 .cmatrix        = { 179, -179, 0, -61, -176, 228 },
512         },
513 };
514 #define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0]))
515
516 /*
517  * All formats we support are 2 bytes/pixel.
518  */
519 #define BYTES_PER_PIXEL 2
520
521 /*
522  * Then there is the issue of window sizes.  Try to capture the info here.
523  */
524
525 /*
526  * QCIF mode is done (by OV) in a very strange way - it actually looks like
527  * VGA with weird scaling options - they do *not* use the canned QCIF mode
528  * which is allegedly provided by the sensor.  So here's the weird register
529  * settings.
530  */
531 static struct regval_list ov7670_qcif_regs[] = {
532         { REG_COM3, COM3_SCALEEN|COM3_DCWEN },
533         { REG_COM3, COM3_DCWEN },
534         { REG_COM14, COM14_DCWEN | 0x01},
535         { 0x73, 0xf1 },
536         { 0xa2, 0x52 },
537         { 0x7b, 0x1c },
538         { 0x7c, 0x28 },
539         { 0x7d, 0x3c },
540         { 0x7f, 0x69 },
541         { REG_COM9, 0x38 },
542         { 0xa1, 0x0b },
543         { 0x74, 0x19 },
544         { 0x9a, 0x80 },
545         { 0x43, 0x14 },
546         { REG_COM13, 0xc0 },
547         { 0xff, 0xff },
548 };
549
550 static struct ov7670_win_size {
551         int     width;
552         int     height;
553         unsigned char com7_bit;
554         int     hstart;         /* Start/stop values for the camera.  Note */
555         int     hstop;          /* that they do not always make complete */
556         int     vstart;         /* sense to humans, but evidently the sensor */
557         int     vstop;          /* will do the right thing... */
558         struct regval_list *regs; /* Regs to tweak */
559 /* h/vref stuff */
560 } ov7670_win_sizes[] = {
561         /* VGA */
562         {
563                 .width          = VGA_WIDTH,
564                 .height         = VGA_HEIGHT,
565                 .com7_bit       = COM7_FMT_VGA,
566                 .hstart         = 158,          /* These values from */
567                 .hstop          =  14,          /* Omnivision */
568                 .vstart         =  10,
569                 .vstop          = 490,
570                 .regs           = NULL,
571         },
572         /* CIF */
573         {
574                 .width          = CIF_WIDTH,
575                 .height         = CIF_HEIGHT,
576                 .com7_bit       = COM7_FMT_CIF,
577                 .hstart         = 170,          /* Empirically determined */
578                 .hstop          =  90,
579                 .vstart         =  14,
580                 .vstop          = 494,
581                 .regs           = NULL,
582         },
583         /* QVGA */
584         {
585                 .width          = QVGA_WIDTH,
586                 .height         = QVGA_HEIGHT,
587                 .com7_bit       = COM7_FMT_QVGA,
588                 .hstart         = 164,          /* Empirically determined */
589                 .hstop          =  20,
590                 .vstart         =  14,
591                 .vstop          = 494,
592                 .regs           = NULL,
593         },
594         /* QCIF */
595         {
596                 .width          = QCIF_WIDTH,
597                 .height         = QCIF_HEIGHT,
598                 .com7_bit       = COM7_FMT_VGA, /* see comment above */
599                 .hstart         = 456,          /* Empirically determined */
600                 .hstop          =  24,
601                 .vstart         =  14,
602                 .vstop          = 494,
603                 .regs           = ov7670_qcif_regs,
604         },
605 };
606
607 #define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0]))
608
609
610 /*
611  * Store a set of start/stop values into the camera.
612  */
613 static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop,
614                 int vstart, int vstop)
615 {
616         int ret;
617         unsigned char v;
618 /*
619  * Horizontal: 11 bits, top 8 live in hstart and hstop.  Bottom 3 of
620  * hstart are in href[2:0], bottom 3 of hstop in href[5:3].  There is
621  * a mystery "edge offset" value in the top two bits of href.
622  */
623         ret =  ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff);
624         ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff);
625         ret += ov7670_read(client, REG_HREF, &v);
626         v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
627         msleep(10);
628         ret += ov7670_write(client, REG_HREF, v);
629 /*
630  * Vertical: similar arrangement, but only 10 bits.
631  */
632         ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff);
633         ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff);
634         ret += ov7670_read(client, REG_VREF, &v);
635         v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
636         msleep(10);
637         ret += ov7670_write(client, REG_VREF, v);
638         return ret;
639 }
640
641
642 static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt)
643 {
644         struct ov7670_format_struct *ofmt;
645
646         if (fmt->index >= N_OV7670_FMTS)
647                 return -EINVAL;
648
649         ofmt = ov7670_formats + fmt->index;
650         fmt->flags = 0;
651         strcpy(fmt->description, ofmt->desc);
652         fmt->pixelformat = ofmt->pixelformat;
653         return 0;
654 }
655
656
657 static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
658                 struct ov7670_format_struct **ret_fmt,
659                 struct ov7670_win_size **ret_wsize)
660 {
661         int index;
662         struct ov7670_win_size *wsize;
663         struct v4l2_pix_format *pix = &fmt->fmt.pix;
664
665         for (index = 0; index < N_OV7670_FMTS; index++)
666                 if (ov7670_formats[index].pixelformat == pix->pixelformat)
667                         break;
668         if (index >= N_OV7670_FMTS)
669                 return -EINVAL;
670         if (ret_fmt != NULL)
671                 *ret_fmt = ov7670_formats + index;
672         /*
673          * Fields: the OV devices claim to be progressive.
674          */
675         if (pix->field == V4L2_FIELD_ANY)
676                 pix->field = V4L2_FIELD_NONE;
677         else if (pix->field != V4L2_FIELD_NONE)
678                 return -EINVAL;
679         /*
680          * Round requested image size down to the nearest
681          * we support, but not below the smallest.
682          */
683         for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
684              wsize++)
685                 if (pix->width >= wsize->width && pix->height >= wsize->height)
686                         break;
687         if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
688                 wsize--;   /* Take the smallest one */
689         if (ret_wsize != NULL)
690                 *ret_wsize = wsize;
691         /*
692          * Note the size we'll actually handle.
693          */
694         pix->width = wsize->width;
695         pix->height = wsize->height;
696         pix->bytesperline = pix->width*BYTES_PER_PIXEL;
697         if (pix->pixelformat == V4L2_PIX_FMT_RGB32)
698                 pix->bytesperline *= 2;
699         pix->sizeimage = pix->height*pix->bytesperline;
700         return 0;
701 }
702
703 /*
704  * Set a format.
705  */
706 static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
707 {
708         int ret;
709         struct ov7670_format_struct *ovfmt;
710         struct ov7670_win_size *wsize;
711         struct ov7670_info *info = i2c_get_clientdata(c);
712         unsigned char com7;
713
714         ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
715         if (ret)
716                 return ret;
717         /*
718          * COM7 is a pain in the ass, it doesn't like to be read then
719          * quickly written afterward.  But we have everything we need
720          * to set it absolutely here, as long as the format-specific
721          * register sets list it first.
722          */
723         com7 = ovfmt->regs[0].value;
724         com7 |= wsize->com7_bit;
725         ov7670_write(c, REG_COM7, com7);
726         /*
727          * Now write the rest of the array.  Also store start/stops
728          */
729         ov7670_write_array(c, ovfmt->regs + 1);
730         ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart,
731                         wsize->vstop);
732         ret = 0;
733         if (wsize->regs)
734                 ret = ov7670_write_array(c, wsize->regs);
735         info->fmt = ovfmt;
736         return 0;
737 }
738
739 /*
740  * Code for dealing with controls.
741  */
742
743
744
745
746
747 static int ov7670_store_cmatrix(struct i2c_client *client,
748                 int matrix[CMATRIX_LEN])
749 {
750         int i, ret;
751         unsigned char signbits;
752
753         /*
754          * Weird crap seems to exist in the upper part of
755          * the sign bits register, so let's preserve it.
756          */
757         ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits);
758         signbits &= 0xc0;
759
760         for (i = 0; i < CMATRIX_LEN; i++) {
761                 unsigned char raw;
762
763                 if (matrix[i] < 0) {
764                         signbits |= (1 << i);
765                         if (matrix[i] < -255)
766                                 raw = 0xff;
767                         else
768                                 raw = (-1 * matrix[i]) & 0xff;
769                 }
770                 else {
771                         if (matrix[i] > 255)
772                                 raw = 0xff;
773                         else
774                                 raw = matrix[i] & 0xff;
775                 }
776                 ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw);
777         }
778         ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits);
779         return ret;
780 }
781
782
783 /*
784  * Hue also requires messing with the color matrix.  It also requires
785  * trig functions, which tend not to be well supported in the kernel.
786  * So here is a simple table of sine values, 0-90 degrees, in steps
787  * of five degrees.  Values are multiplied by 1000.
788  *
789  * The following naive approximate trig functions require an argument
790  * carefully limited to -180 <= theta <= 180.
791  */
792 #define SIN_STEP 5
793 static const int ov7670_sin_table[] = {
794            0,    87,   173,   258,   342,   422,
795          499,   573,   642,   707,   766,   819,
796          866,   906,   939,   965,   984,   996,
797         1000
798 };
799
800 static int ov7670_sine(int theta)
801 {
802         int chs = 1;
803         int sine;
804
805         if (theta < 0) {
806                 theta = -theta;
807                 chs = -1;
808         }
809         if (theta <= 90)
810                 sine = ov7670_sin_table[theta/SIN_STEP];
811         else {
812                 theta -= 90;
813                 sine = 1000 - ov7670_sin_table[theta/SIN_STEP];
814         }
815         return sine*chs;
816 }
817
818 static int ov7670_cosine(int theta)
819 {
820         theta = 90 - theta;
821         if (theta > 180)
822                 theta -= 360;
823         else if (theta < -180)
824                 theta += 360;
825         return ov7670_sine(theta);
826 }
827
828
829
830
831 static void ov7670_calc_cmatrix(struct ov7670_info *info,
832                 int matrix[CMATRIX_LEN])
833 {
834         int i;
835         /*
836          * Apply the current saturation setting first.
837          */
838         for (i = 0; i < CMATRIX_LEN; i++)
839                 matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7;
840         /*
841          * Then, if need be, rotate the hue value.
842          */
843         if (info->hue != 0) {
844                 int sinth, costh, tmpmatrix[CMATRIX_LEN];
845
846                 memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int));
847                 sinth = ov7670_sine(info->hue);
848                 costh = ov7670_cosine(info->hue);
849
850                 matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000;
851                 matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000;
852                 matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000;
853                 matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000;
854                 matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000;
855                 matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000;
856         }
857 }
858
859
860
861 static int ov7670_t_sat(struct i2c_client *client, int value)
862 {
863         struct ov7670_info *info = i2c_get_clientdata(client);
864         int matrix[CMATRIX_LEN];
865         int ret;
866
867         info->sat = value;
868         ov7670_calc_cmatrix(info, matrix);
869         ret = ov7670_store_cmatrix(client, matrix);
870         return ret;
871 }
872
873 static int ov7670_q_sat(struct i2c_client *client, __s32 *value)
874 {
875         struct ov7670_info *info = i2c_get_clientdata(client);
876
877         *value = info->sat;
878         return 0;
879 }
880
881 static int ov7670_t_hue(struct i2c_client *client, int value)
882 {
883         struct ov7670_info *info = i2c_get_clientdata(client);
884         int matrix[CMATRIX_LEN];
885         int ret;
886
887         if (value < -180 || value > 180)
888                 return -EINVAL;
889         info->hue = value;
890         ov7670_calc_cmatrix(info, matrix);
891         ret = ov7670_store_cmatrix(client, matrix);
892         return ret;
893 }
894
895
896 static int ov7670_q_hue(struct i2c_client *client, __s32 *value)
897 {
898         struct ov7670_info *info = i2c_get_clientdata(client);
899
900         *value = info->hue;
901         return 0;
902 }
903
904
905 /*
906  * Some weird registers seem to store values in a sign/magnitude format!
907  */
908 static unsigned char ov7670_sm_to_abs(unsigned char v)
909 {
910         if ((v & 0x80) == 0)
911                 return v + 128;
912         else
913                 return 128 - (v & 0x7f);
914 }
915
916
917 static unsigned char ov7670_abs_to_sm(unsigned char v)
918 {
919         if (v > 127)
920                 return v & 0x7f;
921         else
922                 return (128 - v) | 0x80;
923 }
924
925 static int ov7670_t_brightness(struct i2c_client *client, int value)
926 {
927         unsigned char com8, v;
928         int ret;
929
930         ov7670_read(client, REG_COM8, &com8);
931         com8 &= ~COM8_AEC;
932         ov7670_write(client, REG_COM8, com8);
933         v = ov7670_abs_to_sm(value);
934         ret = ov7670_write(client, REG_BRIGHT, v);
935         return ret;
936 }
937
938 static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
939 {
940         unsigned char v;
941         int ret = ov7670_read(client, REG_BRIGHT, &v);
942
943         *value = ov7670_sm_to_abs(v);
944         return ret;
945 }
946
947 static int ov7670_t_contrast(struct i2c_client *client, int value)
948 {
949         return ov7670_write(client, REG_CONTRAS, (unsigned char) value);
950 }
951
952 static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
953 {
954         unsigned char v;
955         int ret = ov7670_read(client, REG_CONTRAS, &v);
956
957         *value = v;
958         return ret;
959 }
960
961 static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
962 {
963         int ret;
964         unsigned char v;
965
966         ret = ov7670_read(client, REG_MVFP, &v);
967         *value = (v & MVFP_MIRROR) == MVFP_MIRROR;
968         return ret;
969 }
970
971
972 static int ov7670_t_hflip(struct i2c_client *client, int value)
973 {
974         unsigned char v;
975         int ret;
976
977         ret = ov7670_read(client, REG_MVFP, &v);
978         if (value)
979                 v |= MVFP_MIRROR;
980         else
981                 v &= ~MVFP_MIRROR;
982         msleep(10);  /* FIXME */
983         ret += ov7670_write(client, REG_MVFP, v);
984         return ret;
985 }
986
987
988
989 static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
990 {
991         int ret;
992         unsigned char v;
993
994         ret = ov7670_read(client, REG_MVFP, &v);
995         *value = (v & MVFP_FLIP) == MVFP_FLIP;
996         return ret;
997 }
998
999
1000 static int ov7670_t_vflip(struct i2c_client *client, int value)
1001 {
1002         unsigned char v;
1003         int ret;
1004
1005         ret = ov7670_read(client, REG_MVFP, &v);
1006         if (value)
1007                 v |= MVFP_FLIP;
1008         else
1009                 v &= ~MVFP_FLIP;
1010         msleep(10);  /* FIXME */
1011         ret += ov7670_write(client, REG_MVFP, v);
1012         return ret;
1013 }
1014
1015
1016 static struct ov7670_control {
1017         struct v4l2_queryctrl qc;
1018         int (*query)(struct i2c_client *c, __s32 *value);
1019         int (*tweak)(struct i2c_client *c, int value);
1020 } ov7670_controls[] =
1021 {
1022         {
1023                 .qc = {
1024                         .id = V4L2_CID_BRIGHTNESS,
1025                         .type = V4L2_CTRL_TYPE_INTEGER,
1026                         .name = "Brightness",
1027                         .minimum = 0,
1028                         .maximum = 255,
1029                         .step = 1,
1030                         .default_value = 0x80,
1031                         .flags = V4L2_CTRL_FLAG_SLIDER
1032                 },
1033                 .tweak = ov7670_t_brightness,
1034                 .query = ov7670_q_brightness,
1035         },
1036         {
1037                 .qc = {
1038                         .id = V4L2_CID_CONTRAST,
1039                         .type = V4L2_CTRL_TYPE_INTEGER,
1040                         .name = "Contrast",
1041                         .minimum = 0,
1042                         .maximum = 127,
1043                         .step = 1,
1044                         .default_value = 0x40,   /* XXX ov7670 spec */
1045                         .flags = V4L2_CTRL_FLAG_SLIDER
1046                 },
1047                 .tweak = ov7670_t_contrast,
1048                 .query = ov7670_q_contrast,
1049         },
1050         {
1051                 .qc = {
1052                         .id = V4L2_CID_SATURATION,
1053                         .type = V4L2_CTRL_TYPE_INTEGER,
1054                         .name = "Saturation",
1055                         .minimum = 0,
1056                         .maximum = 256,
1057                         .step = 1,
1058                         .default_value = 0x80,
1059                         .flags = V4L2_CTRL_FLAG_SLIDER
1060                 },
1061                 .tweak = ov7670_t_sat,
1062                 .query = ov7670_q_sat,
1063         },
1064         {
1065                 .qc = {
1066                         .id = V4L2_CID_HUE,
1067                         .type = V4L2_CTRL_TYPE_INTEGER,
1068                         .name = "HUE",
1069                         .minimum = -180,
1070                         .maximum = 180,
1071                         .step = 5,
1072                         .default_value = 0,
1073                         .flags = V4L2_CTRL_FLAG_SLIDER
1074                 },
1075                 .tweak = ov7670_t_hue,
1076                 .query = ov7670_q_hue,
1077         },
1078         {
1079                 .qc = {
1080                         .id = V4L2_CID_VFLIP,
1081                         .type = V4L2_CTRL_TYPE_BOOLEAN,
1082                         .name = "Vertical flip",
1083                         .minimum = 0,
1084                         .maximum = 1,
1085                         .step = 1,
1086                         .default_value = 0,
1087                 },
1088                 .tweak = ov7670_t_vflip,
1089                 .query = ov7670_q_vflip,
1090         },
1091         {
1092                 .qc = {
1093                         .id = V4L2_CID_HFLIP,
1094                         .type = V4L2_CTRL_TYPE_BOOLEAN,
1095                         .name = "Horizontal mirror",
1096                         .minimum = 0,
1097                         .maximum = 1,
1098                         .step = 1,
1099                         .default_value = 0,
1100                 },
1101                 .tweak = ov7670_t_hflip,
1102                 .query = ov7670_q_hflip,
1103         },
1104 };
1105 #define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0]))
1106
1107 static struct ov7670_control *ov7670_find_control(__u32 id)
1108 {
1109         int i;
1110
1111         for (i = 0; i < N_CONTROLS; i++)
1112                 if (ov7670_controls[i].qc.id == id)
1113                         return ov7670_controls + i;
1114         return NULL;
1115 }
1116
1117
1118 static int ov7670_queryctrl(struct i2c_client *client,
1119                 struct v4l2_queryctrl *qc)
1120 {
1121         struct ov7670_control *ctrl = ov7670_find_control(qc->id);
1122
1123         if (ctrl == NULL)
1124                 return -EINVAL;
1125         *qc = ctrl->qc;
1126         return 0;
1127 }
1128
1129 static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
1130 {
1131         struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
1132         int ret;
1133
1134         if (octrl == NULL)
1135                 return -EINVAL;
1136         ret = octrl->query(client, &ctrl->value);
1137         if (ret >= 0)
1138                 return 0;
1139         return ret;
1140 }
1141
1142 static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
1143 {
1144         struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
1145         int ret;
1146
1147         if (octrl == NULL)
1148                 return -EINVAL;
1149         ret =  octrl->tweak(client, ctrl->value);
1150         if (ret >= 0)
1151                 return 0;
1152         return ret;
1153 }
1154
1155
1156
1157
1158
1159
1160 /*
1161  * Basic i2c stuff.
1162  */
1163 static struct i2c_driver ov7670_driver;
1164
1165 static int ov7670_attach(struct i2c_adapter *adapter)
1166 {
1167         int ret;
1168         struct i2c_client *client;
1169         struct ov7670_info *info;
1170
1171         /*
1172          * For now: only deal with adapters we recognize.
1173          */
1174         if (adapter->id != I2C_HW_SMBUS_CAFE)
1175                 return -ENODEV;
1176
1177         client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL);
1178         if (! client)
1179                 return -ENOMEM;
1180         client->adapter = adapter;
1181         client->addr = OV7670_I2C_ADDR;
1182         client->driver = &ov7670_driver,
1183         strcpy(client->name, "OV7670");
1184         /*
1185          * Set up our info structure.
1186          */
1187         info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL);
1188         if (! info) {
1189                 ret = -ENOMEM;
1190                 goto out_free;
1191         }
1192         info->fmt = &ov7670_formats[0];
1193         info->sat = 128;        /* Review this */
1194         i2c_set_clientdata(client, info);
1195
1196         /*
1197          * Make sure it's an ov7670
1198          */
1199         ret = ov7670_detect(client);
1200         if (ret)
1201                 goto out_free_info;
1202         i2c_attach_client(client);
1203         return 0;
1204
1205   out_free_info:
1206         kfree(info);
1207   out_free:
1208         kfree(client);
1209         return ret;
1210 }
1211
1212
1213 static int ov7670_detach(struct i2c_client *client)
1214 {
1215         i2c_detach_client(client);
1216         kfree(i2c_get_clientdata(client));
1217         kfree(client);
1218         return 0;
1219 }
1220
1221
1222 static int ov7670_command(struct i2c_client *client, unsigned int cmd,
1223                 void *arg)
1224 {
1225         switch (cmd) {
1226         case VIDIOC_INT_G_CHIP_IDENT:
1227                 * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670;
1228                 return 0;
1229
1230         case VIDIOC_INT_RESET:
1231                 ov7670_reset(client);
1232                 return 0;
1233
1234         case VIDIOC_INT_INIT:
1235                 return ov7670_init(client);
1236
1237         case VIDIOC_ENUM_FMT:
1238                 return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg);
1239         case VIDIOC_TRY_FMT:
1240                 return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL);
1241         case VIDIOC_S_FMT:
1242                 return ov7670_s_fmt(client, (struct v4l2_format *) arg);
1243         case VIDIOC_QUERYCTRL:
1244                 return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg);
1245         case VIDIOC_S_CTRL:
1246                 return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
1247         case VIDIOC_G_CTRL:
1248                 return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
1249         /* Todo:
1250            g/s_parm
1251            initialization
1252         */
1253         }
1254         return -EINVAL;
1255 }
1256
1257
1258
1259 static struct i2c_driver ov7670_driver = {
1260         .driver = {
1261                 .name = "ov7670",
1262         },
1263         .id             = I2C_DRIVERID_OV7670,
1264         .class          = I2C_CLASS_CAM_DIGITAL,
1265         .attach_adapter = ov7670_attach,
1266         .detach_client  = ov7670_detach,
1267         .command        = ov7670_command,
1268 };
1269
1270
1271 /*
1272  * Module initialization
1273  */
1274 static int __init ov7670_mod_init(void)
1275 {
1276         printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n");
1277         return i2c_add_driver(&ov7670_driver);
1278 }
1279
1280 static void __exit ov7670_mod_exit(void)
1281 {
1282         i2c_del_driver(&ov7670_driver);
1283 }
1284
1285 module_init(ov7670_mod_init);
1286 module_exit(ov7670_mod_exit);