blob: 1f8e2613ecc5201c590e75ff793f92124642ad38 [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/**
2 * OV519 driver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
Romain Beauxis2961e872008-12-05 06:25:26 -03006 * This module is adapted from the ov51x-jpeg package, which itself
7 * was adapted from the ov511 driver.
8 *
9 * Original copyright for the ov511 driver is:
10 *
11 * Copyright (c) 1999-2004 Mark W. McClelland
12 * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach
13 *
14 * ov51x-jpeg original copyright is:
15 *
16 * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org>
17 * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com>
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030018 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 *
33 */
34#define MODULE_NAME "ov519"
35
36#include "gspca.h"
37
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030038MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
39MODULE_DESCRIPTION("OV519 USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42/* global parameters */
43static int frame_rate;
44
45/* Number of times to retry a failed I2C transaction. Increase this if you
46 * are getting "Failed to read sensor ID..." */
47static int i2c_detect_tries = 10;
48
49/* ov519 device descriptor */
50struct sd {
51 struct gspca_dev gspca_dev; /* !! must be the first item */
52
Hans de Goede92918a52009-06-14 06:21:35 -030053 __u8 packet_nr;
54
Hans de Goede49809d62009-06-07 12:10:39 -030055 char bridge;
56#define BRIDGE_OV511 0
57#define BRIDGE_OV511PLUS 1
58#define BRIDGE_OV518 2
59#define BRIDGE_OV518PLUS 3
60#define BRIDGE_OV519 4
Hans de Goede9e4d8252009-06-14 06:25:06 -030061#define BRIDGE_MASK 7
62
63 char invert_led;
64#define BRIDGE_INVERT_LED 8
Hans de Goede49809d62009-06-07 12:10:39 -030065
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030066 /* Determined by sensor type */
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -030067 __u8 sif;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030068
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -030069 __u8 brightness;
70 __u8 contrast;
71 __u8 colors;
Jean-Francois Moine0cd67592008-07-29 05:25:28 -030072 __u8 hflip;
73 __u8 vflip;
Hans de Goede02ab18b2009-06-14 04:32:04 -030074 __u8 autobrightness;
75 __u8 freq;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030076
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -030077 __u8 stopped; /* Streaming is temporarily paused */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030078
Hans de Goede1876bb92009-06-14 06:45:50 -030079 __u8 frame_rate; /* current Framerate */
80 __u8 clockdiv; /* clockdiv override */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030081
82 char sensor; /* Type of image sensor chip (SEN_*) */
83#define SEN_UNKNOWN 0
84#define SEN_OV6620 1
85#define SEN_OV6630 2
Hans de Goede7d971372009-06-14 05:28:17 -030086#define SEN_OV66308AF 3
87#define SEN_OV7610 4
88#define SEN_OV7620 5
89#define SEN_OV7640 6
90#define SEN_OV7670 7
91#define SEN_OV76BE 8
92#define SEN_OV8610 9
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030093};
94
95/* V4L2 controls supported by the driver */
96static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
97static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
98static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
99static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
100static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
Jean-Francois Moine0cd67592008-07-29 05:25:28 -0300102static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
103static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
104static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
105static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede02ab18b2009-06-14 04:32:04 -0300106static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val);
108static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
Hans de Goede49809d62009-06-07 12:10:39 -0300110static void setbrightness(struct gspca_dev *gspca_dev);
111static void setcontrast(struct gspca_dev *gspca_dev);
112static void setcolors(struct gspca_dev *gspca_dev);
Hans de Goede02ab18b2009-06-14 04:32:04 -0300113static void setautobrightness(struct sd *sd);
114static void setfreq(struct sd *sd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115
Hans de Goede02ab18b2009-06-14 04:32:04 -0300116static const struct ctrl sd_ctrls[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117 {
118 {
119 .id = V4L2_CID_BRIGHTNESS,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Brightness",
122 .minimum = 0,
123 .maximum = 255,
124 .step = 1,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300125#define BRIGHTNESS_DEF 127
126 .default_value = BRIGHTNESS_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300127 },
128 .set = sd_setbrightness,
129 .get = sd_getbrightness,
130 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300131 {
132 {
133 .id = V4L2_CID_CONTRAST,
134 .type = V4L2_CTRL_TYPE_INTEGER,
135 .name = "Contrast",
136 .minimum = 0,
137 .maximum = 255,
138 .step = 1,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300139#define CONTRAST_DEF 127
140 .default_value = CONTRAST_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300141 },
142 .set = sd_setcontrast,
143 .get = sd_getcontrast,
144 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300145 {
146 {
147 .id = V4L2_CID_SATURATION,
148 .type = V4L2_CTRL_TYPE_INTEGER,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300149 .name = "Color",
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150 .minimum = 0,
151 .maximum = 255,
152 .step = 1,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300153#define COLOR_DEF 127
154 .default_value = COLOR_DEF,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300155 },
156 .set = sd_setcolors,
157 .get = sd_getcolors,
158 },
Hans de Goede02ab18b2009-06-14 04:32:04 -0300159/* The flip controls work with ov7670 only */
Jean-Francois Moinede004482008-09-03 17:12:16 -0300160#define HFLIP_IDX 3
Jean-Francois Moine0cd67592008-07-29 05:25:28 -0300161 {
162 {
163 .id = V4L2_CID_HFLIP,
164 .type = V4L2_CTRL_TYPE_BOOLEAN,
165 .name = "Mirror",
166 .minimum = 0,
167 .maximum = 1,
168 .step = 1,
169#define HFLIP_DEF 0
170 .default_value = HFLIP_DEF,
171 },
172 .set = sd_sethflip,
173 .get = sd_gethflip,
174 },
Jean-Francois Moinede004482008-09-03 17:12:16 -0300175#define VFLIP_IDX 4
Jean-Francois Moine0cd67592008-07-29 05:25:28 -0300176 {
177 {
178 .id = V4L2_CID_VFLIP,
179 .type = V4L2_CTRL_TYPE_BOOLEAN,
180 .name = "Vflip",
181 .minimum = 0,
182 .maximum = 1,
183 .step = 1,
184#define VFLIP_DEF 0
185 .default_value = VFLIP_DEF,
186 },
187 .set = sd_setvflip,
188 .get = sd_getvflip,
189 },
Hans de Goede02ab18b2009-06-14 04:32:04 -0300190#define AUTOBRIGHT_IDX 5
191 {
192 {
193 .id = V4L2_CID_AUTOBRIGHTNESS,
194 .type = V4L2_CTRL_TYPE_BOOLEAN,
195 .name = "Auto Brightness",
196 .minimum = 0,
197 .maximum = 1,
198 .step = 1,
199#define AUTOBRIGHT_DEF 1
200 .default_value = AUTOBRIGHT_DEF,
201 },
202 .set = sd_setautobrightness,
203 .get = sd_getautobrightness,
204 },
205#define FREQ_IDX 6
206 {
207 {
208 .id = V4L2_CID_POWER_LINE_FREQUENCY,
209 .type = V4L2_CTRL_TYPE_MENU,
210 .name = "Light frequency filter",
211 .minimum = 0,
212 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
213 .step = 1,
214#define FREQ_DEF 0
215 .default_value = FREQ_DEF,
216 },
217 .set = sd_setfreq,
218 .get = sd_getfreq,
219 },
220#define OV7670_FREQ_IDX 7
221 {
222 {
223 .id = V4L2_CID_POWER_LINE_FREQUENCY,
224 .type = V4L2_CTRL_TYPE_MENU,
225 .name = "Light frequency filter",
226 .minimum = 0,
227 .maximum = 3, /* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */
228 .step = 1,
229#define OV7670_FREQ_DEF 3
230 .default_value = OV7670_FREQ_DEF,
231 },
232 .set = sd_setfreq,
233 .get = sd_getfreq,
234 },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300235};
236
Hans de Goede49809d62009-06-07 12:10:39 -0300237static const struct v4l2_pix_format ov519_vga_mode[] = {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300238 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
239 .bytesperline = 320,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300240 .sizeimage = 320 * 240 * 3 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300241 .colorspace = V4L2_COLORSPACE_JPEG,
242 .priv = 1},
243 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
244 .bytesperline = 640,
245 .sizeimage = 640 * 480 * 3 / 8 + 590,
246 .colorspace = V4L2_COLORSPACE_JPEG,
247 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300248};
Hans de Goede49809d62009-06-07 12:10:39 -0300249static const struct v4l2_pix_format ov519_sif_mode[] = {
Hans de Goede124cc9c2009-06-14 05:48:00 -0300250 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
251 .bytesperline = 160,
252 .sizeimage = 160 * 120 * 3 / 8 + 590,
253 .colorspace = V4L2_COLORSPACE_JPEG,
254 .priv = 3},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300255 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
256 .bytesperline = 176,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300257 .sizeimage = 176 * 144 * 3 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300258 .colorspace = V4L2_COLORSPACE_JPEG,
259 .priv = 1},
Hans de Goede124cc9c2009-06-14 05:48:00 -0300260 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
261 .bytesperline = 320,
262 .sizeimage = 320 * 240 * 3 / 8 + 590,
263 .colorspace = V4L2_COLORSPACE_JPEG,
264 .priv = 2},
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300265 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
266 .bytesperline = 352,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -0300267 .sizeimage = 352 * 288 * 3 / 8 + 590,
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300268 .colorspace = V4L2_COLORSPACE_JPEG,
269 .priv = 0},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300270};
271
Hans de Goede49809d62009-06-07 12:10:39 -0300272static const struct v4l2_pix_format ov518_vga_mode[] = {
273 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
274 .bytesperline = 320,
275 .sizeimage = 320 * 240 * 3 / 8 + 590,
276 .colorspace = V4L2_COLORSPACE_JPEG,
277 .priv = 1},
278 {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
279 .bytesperline = 640,
280 .sizeimage = 640 * 480 * 3 / 8 + 590,
281 .colorspace = V4L2_COLORSPACE_JPEG,
282 .priv = 0},
283};
284static const struct v4l2_pix_format ov518_sif_mode[] = {
Hans de Goede124cc9c2009-06-14 05:48:00 -0300285 {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
286 .bytesperline = 160,
287 .sizeimage = 40000,
288 .colorspace = V4L2_COLORSPACE_JPEG,
289 .priv = 3},
Hans de Goede49809d62009-06-07 12:10:39 -0300290 {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
291 .bytesperline = 176,
292 .sizeimage = 40000,
293 .colorspace = V4L2_COLORSPACE_JPEG,
294 .priv = 1},
Hans de Goede124cc9c2009-06-14 05:48:00 -0300295 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
296 .bytesperline = 320,
297 .sizeimage = 320 * 240 * 3 / 8 + 590,
298 .colorspace = V4L2_COLORSPACE_JPEG,
299 .priv = 2},
Hans de Goede49809d62009-06-07 12:10:39 -0300300 {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
301 .bytesperline = 352,
302 .sizeimage = 352 * 288 * 3 / 8 + 590,
303 .colorspace = V4L2_COLORSPACE_JPEG,
304 .priv = 0},
305};
306
Hans de Goede1876bb92009-06-14 06:45:50 -0300307static const struct v4l2_pix_format ov511_vga_mode[] = {
308 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
309 .bytesperline = 320,
310 .sizeimage = 320 * 240 * 3,
311 .colorspace = V4L2_COLORSPACE_JPEG,
312 .priv = 1},
313 {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
314 .bytesperline = 640,
315 .sizeimage = 640 * 480 * 2,
316 .colorspace = V4L2_COLORSPACE_JPEG,
317 .priv = 0},
318};
319static const struct v4l2_pix_format ov511_sif_mode[] = {
320 {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
321 .bytesperline = 160,
322 .sizeimage = 40000,
323 .colorspace = V4L2_COLORSPACE_JPEG,
324 .priv = 3},
325 {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
326 .bytesperline = 176,
327 .sizeimage = 40000,
328 .colorspace = V4L2_COLORSPACE_JPEG,
329 .priv = 1},
330 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
331 .bytesperline = 320,
332 .sizeimage = 320 * 240 * 3,
333 .colorspace = V4L2_COLORSPACE_JPEG,
334 .priv = 2},
335 {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
336 .bytesperline = 352,
337 .sizeimage = 352 * 288 * 3,
338 .colorspace = V4L2_COLORSPACE_JPEG,
339 .priv = 0},
340};
Hans de Goede49809d62009-06-07 12:10:39 -0300341
342/* Registers common to OV511 / OV518 */
Hans de Goede1876bb92009-06-14 06:45:50 -0300343#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
Hans de Goede49809d62009-06-07 12:10:39 -0300344#define R51x_SYS_RESET 0x50
Hans de Goede1876bb92009-06-14 06:45:50 -0300345 /* Reset type flags */
346 #define OV511_RESET_OMNICE 0x08
Hans de Goede49809d62009-06-07 12:10:39 -0300347#define R51x_SYS_INIT 0x53
348#define R51x_SYS_SNAP 0x52
349#define R51x_SYS_CUST_ID 0x5F
350#define R51x_COMP_LUT_BEGIN 0x80
351
352/* OV511 Camera interface register numbers */
Hans de Goede1876bb92009-06-14 06:45:50 -0300353#define R511_CAM_DELAY 0x10
354#define R511_CAM_EDGE 0x11
355#define R511_CAM_PXCNT 0x12
356#define R511_CAM_LNCNT 0x13
357#define R511_CAM_PXDIV 0x14
358#define R511_CAM_LNDIV 0x15
359#define R511_CAM_UV_EN 0x16
360#define R511_CAM_LINE_MODE 0x17
361#define R511_CAM_OPTS 0x18
362
363#define R511_SNAP_FRAME 0x19
364#define R511_SNAP_PXCNT 0x1A
365#define R511_SNAP_LNCNT 0x1B
366#define R511_SNAP_PXDIV 0x1C
367#define R511_SNAP_LNDIV 0x1D
368#define R511_SNAP_UV_EN 0x1E
369#define R511_SNAP_UV_EN 0x1E
370#define R511_SNAP_OPTS 0x1F
371
372#define R511_DRAM_FLOW_CTL 0x20
373#define R511_FIFO_OPTS 0x31
374#define R511_I2C_CTL 0x40
Hans de Goede49809d62009-06-07 12:10:39 -0300375#define R511_SYS_LED_CTL 0x55 /* OV511+ only */
Hans de Goede1876bb92009-06-14 06:45:50 -0300376#define R511_COMP_EN 0x78
377#define R511_COMP_LUT_EN 0x79
Hans de Goede49809d62009-06-07 12:10:39 -0300378
379/* OV518 Camera interface register numbers */
380#define R518_GPIO_OUT 0x56 /* OV518(+) only */
381#define R518_GPIO_CTL 0x57 /* OV518(+) only */
382
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383/* OV519 Camera interface register numbers */
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300384#define OV519_R10_H_SIZE 0x10
385#define OV519_R11_V_SIZE 0x11
386#define OV519_R12_X_OFFSETL 0x12
387#define OV519_R13_X_OFFSETH 0x13
388#define OV519_R14_Y_OFFSETL 0x14
389#define OV519_R15_Y_OFFSETH 0x15
390#define OV519_R16_DIVIDER 0x16
391#define OV519_R20_DFR 0x20
392#define OV519_R25_FORMAT 0x25
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300393
394/* OV519 System Controller register numbers */
395#define OV519_SYS_RESET1 0x51
396#define OV519_SYS_EN_CLK1 0x54
397
398#define OV519_GPIO_DATA_OUT0 0x71
399#define OV519_GPIO_IO_CTRL0 0x72
400
401#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
402
403/* I2C registers */
404#define R51x_I2C_W_SID 0x41
405#define R51x_I2C_SADDR_3 0x42
406#define R51x_I2C_SADDR_2 0x43
407#define R51x_I2C_R_SID 0x44
408#define R51x_I2C_DATA 0x45
409#define R518_I2C_CTL 0x47 /* OV518(+) only */
410
411/* I2C ADDRESSES */
412#define OV7xx0_SID 0x42
413#define OV8xx0_SID 0xa0
414#define OV6xx0_SID 0xc0
415
416/* OV7610 registers */
417#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
Hans de Goede49809d62009-06-07 12:10:39 -0300418#define OV7610_REG_BLUE 0x01 /* blue channel balance */
419#define OV7610_REG_RED 0x02 /* red channel balance */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300420#define OV7610_REG_SAT 0x03 /* saturation */
421#define OV8610_REG_HUE 0x04 /* 04 reserved */
422#define OV7610_REG_CNT 0x05 /* Y contrast */
423#define OV7610_REG_BRT 0x06 /* Y brightness */
424#define OV7610_REG_COM_C 0x14 /* misc common regs */
425#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
426#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
427#define OV7610_REG_COM_I 0x29 /* misc settings */
428
429/* OV7670 registers */
430#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
431#define OV7670_REG_BLUE 0x01 /* blue gain */
432#define OV7670_REG_RED 0x02 /* red gain */
433#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
434#define OV7670_REG_COM1 0x04 /* Control 1 */
435#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */
436#define OV7670_REG_COM3 0x0c /* Control 3 */
437#define OV7670_REG_COM4 0x0d /* Control 4 */
438#define OV7670_REG_COM5 0x0e /* All "reserved" */
439#define OV7670_REG_COM6 0x0f /* Control 6 */
440#define OV7670_REG_AECH 0x10 /* More bits of AEC value */
441#define OV7670_REG_CLKRC 0x11 /* Clock control */
442#define OV7670_REG_COM7 0x12 /* Control 7 */
443#define OV7670_COM7_FMT_VGA 0x00
444#define OV7670_COM7_YUV 0x00 /* YUV */
445#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */
446#define OV7670_COM7_FMT_MASK 0x38
447#define OV7670_COM7_RESET 0x80 /* Register reset */
448#define OV7670_REG_COM8 0x13 /* Control 8 */
449#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */
450#define OV7670_COM8_AWB 0x02 /* White balance enable */
451#define OV7670_COM8_AGC 0x04 /* Auto gain enable */
452#define OV7670_COM8_BFILT 0x20 /* Band filter enable */
453#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */
454#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
455#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */
456#define OV7670_REG_COM10 0x15 /* Control 10 */
457#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */
458#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */
459#define OV7670_REG_VSTART 0x19 /* Vert start high bits */
460#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */
461#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */
Jean-Francois Moine0cd67592008-07-29 05:25:28 -0300462#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300463#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
464#define OV7670_REG_AEW 0x24 /* AGC upper limit */
465#define OV7670_REG_AEB 0x25 /* AGC lower limit */
466#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */
467#define OV7670_REG_HREF 0x32 /* HREF pieces */
468#define OV7670_REG_TSLB 0x3a /* lots of stuff */
469#define OV7670_REG_COM11 0x3b /* Control 11 */
470#define OV7670_COM11_EXP 0x02
471#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
472#define OV7670_REG_COM12 0x3c /* Control 12 */
473#define OV7670_REG_COM13 0x3d /* Control 13 */
474#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */
475#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */
476#define OV7670_REG_COM14 0x3e /* Control 14 */
477#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */
478#define OV7670_REG_COM15 0x40 /* Control 15 */
479#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */
480#define OV7670_REG_COM16 0x41 /* Control 16 */
481#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */
482#define OV7670_REG_BRIGHT 0x55 /* Brightness */
483#define OV7670_REG_CONTRAS 0x56 /* Contrast control */
484#define OV7670_REG_GFIX 0x69 /* Fix gain control */
485#define OV7670_REG_RGB444 0x8c /* RGB 444 control */
486#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */
487#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
488#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */
489#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
490#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
491#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
492#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
493#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
494#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
495
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300496struct ov_regvals {
497 __u8 reg;
498 __u8 val;
499};
500struct ov_i2c_regvals {
501 __u8 reg;
502 __u8 val;
503};
504
505static const struct ov_i2c_regvals norm_6x20[] = {
506 { 0x12, 0x80 }, /* reset */
507 { 0x11, 0x01 },
508 { 0x03, 0x60 },
509 { 0x05, 0x7f }, /* For when autoadjust is off */
510 { 0x07, 0xa8 },
511 /* The ratio of 0x0c and 0x0d controls the white point */
512 { 0x0c, 0x24 },
513 { 0x0d, 0x24 },
514 { 0x0f, 0x15 }, /* COMS */
515 { 0x10, 0x75 }, /* AEC Exposure time */
516 { 0x12, 0x24 }, /* Enable AGC */
517 { 0x14, 0x04 },
518 /* 0x16: 0x06 helps frame stability with moving objects */
519 { 0x16, 0x06 },
520/* { 0x20, 0x30 }, * Aperture correction enable */
521 { 0x26, 0xb2 }, /* BLC enable */
522 /* 0x28: 0x05 Selects RGB format if RGB on */
523 { 0x28, 0x05 },
524 { 0x2a, 0x04 }, /* Disable framerate adjust */
525/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
526 { 0x2d, 0x99 },
527 { 0x33, 0xa0 }, /* Color Processing Parameter */
528 { 0x34, 0xd2 }, /* Max A/D range */
529 { 0x38, 0x8b },
530 { 0x39, 0x40 },
531
532 { 0x3c, 0x39 }, /* Enable AEC mode changing */
533 { 0x3c, 0x3c }, /* Change AEC mode */
534 { 0x3c, 0x24 }, /* Disable AEC mode changing */
535
536 { 0x3d, 0x80 },
537 /* These next two registers (0x4a, 0x4b) are undocumented.
538 * They control the color balance */
539 { 0x4a, 0x80 },
540 { 0x4b, 0x80 },
541 { 0x4d, 0xd2 }, /* This reduces noise a bit */
542 { 0x4e, 0xc1 },
543 { 0x4f, 0x04 },
544/* Do 50-53 have any effect? */
545/* Toggle 0x12[2] off and on here? */
546};
547
548static const struct ov_i2c_regvals norm_6x30[] = {
549 { 0x12, 0x80 }, /* Reset */
550 { 0x00, 0x1f }, /* Gain */
551 { 0x01, 0x99 }, /* Blue gain */
552 { 0x02, 0x7c }, /* Red gain */
553 { 0x03, 0xc0 }, /* Saturation */
554 { 0x05, 0x0a }, /* Contrast */
555 { 0x06, 0x95 }, /* Brightness */
556 { 0x07, 0x2d }, /* Sharpness */
557 { 0x0c, 0x20 },
558 { 0x0d, 0x20 },
Hans de Goede02ab18b2009-06-14 04:32:04 -0300559 { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300560 { 0x0f, 0x05 },
561 { 0x10, 0x9a },
562 { 0x11, 0x00 }, /* Pixel clock = fastest */
563 { 0x12, 0x24 }, /* Enable AGC and AWB */
564 { 0x13, 0x21 },
565 { 0x14, 0x80 },
566 { 0x15, 0x01 },
567 { 0x16, 0x03 },
568 { 0x17, 0x38 },
569 { 0x18, 0xea },
570 { 0x19, 0x04 },
571 { 0x1a, 0x93 },
572 { 0x1b, 0x00 },
573 { 0x1e, 0xc4 },
574 { 0x1f, 0x04 },
575 { 0x20, 0x20 },
576 { 0x21, 0x10 },
577 { 0x22, 0x88 },
578 { 0x23, 0xc0 }, /* Crystal circuit power level */
579 { 0x25, 0x9a }, /* Increase AEC black ratio */
580 { 0x26, 0xb2 }, /* BLC enable */
581 { 0x27, 0xa2 },
582 { 0x28, 0x00 },
583 { 0x29, 0x00 },
584 { 0x2a, 0x84 }, /* 60 Hz power */
585 { 0x2b, 0xa8 }, /* 60 Hz power */
586 { 0x2c, 0xa0 },
587 { 0x2d, 0x95 }, /* Enable auto-brightness */
588 { 0x2e, 0x88 },
589 { 0x33, 0x26 },
590 { 0x34, 0x03 },
591 { 0x36, 0x8f },
592 { 0x37, 0x80 },
593 { 0x38, 0x83 },
594 { 0x39, 0x80 },
595 { 0x3a, 0x0f },
596 { 0x3b, 0x3c },
597 { 0x3c, 0x1a },
598 { 0x3d, 0x80 },
599 { 0x3e, 0x80 },
600 { 0x3f, 0x0e },
601 { 0x40, 0x00 }, /* White bal */
602 { 0x41, 0x00 }, /* White bal */
603 { 0x42, 0x80 },
604 { 0x43, 0x3f }, /* White bal */
605 { 0x44, 0x80 },
606 { 0x45, 0x20 },
607 { 0x46, 0x20 },
608 { 0x47, 0x80 },
609 { 0x48, 0x7f },
610 { 0x49, 0x00 },
611 { 0x4a, 0x00 },
612 { 0x4b, 0x80 },
613 { 0x4c, 0xd0 },
614 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
615 { 0x4e, 0x40 },
616 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
617 { 0x50, 0xff },
618 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
619 { 0x55, 0xff },
620 { 0x56, 0x12 },
621 { 0x57, 0x81 },
622 { 0x58, 0x75 },
623 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
624 { 0x5a, 0x2c },
625 { 0x5b, 0x0f }, /* AWB chrominance levels */
626 { 0x5c, 0x10 },
627 { 0x3d, 0x80 },
628 { 0x27, 0xa6 },
629 { 0x12, 0x20 }, /* Toggle AWB */
630 { 0x12, 0x24 },
631};
632
633/* Lawrence Glaister <lg@jfm.bc.ca> reports:
634 *
635 * Register 0x0f in the 7610 has the following effects:
636 *
637 * 0x85 (AEC method 1): Best overall, good contrast range
638 * 0x45 (AEC method 2): Very overexposed
639 * 0xa5 (spec sheet default): Ok, but the black level is
640 * shifted resulting in loss of contrast
641 * 0x05 (old driver setting): very overexposed, too much
642 * contrast
643 */
644static const struct ov_i2c_regvals norm_7610[] = {
645 { 0x10, 0xff },
646 { 0x16, 0x06 },
647 { 0x28, 0x24 },
648 { 0x2b, 0xac },
649 { 0x12, 0x00 },
650 { 0x38, 0x81 },
651 { 0x28, 0x24 }, /* 0c */
652 { 0x0f, 0x85 }, /* lg's setting */
653 { 0x15, 0x01 },
654 { 0x20, 0x1c },
655 { 0x23, 0x2a },
656 { 0x24, 0x10 },
657 { 0x25, 0x8a },
658 { 0x26, 0xa2 },
659 { 0x27, 0xc2 },
660 { 0x2a, 0x04 },
661 { 0x2c, 0xfe },
662 { 0x2d, 0x93 },
663 { 0x30, 0x71 },
664 { 0x31, 0x60 },
665 { 0x32, 0x26 },
666 { 0x33, 0x20 },
667 { 0x34, 0x48 },
668 { 0x12, 0x24 },
669 { 0x11, 0x01 },
670 { 0x0c, 0x24 },
671 { 0x0d, 0x24 },
672};
673
674static const struct ov_i2c_regvals norm_7620[] = {
675 { 0x00, 0x00 }, /* gain */
676 { 0x01, 0x80 }, /* blue gain */
677 { 0x02, 0x80 }, /* red gain */
678 { 0x03, 0xc0 }, /* OV7670_REG_VREF */
679 { 0x06, 0x60 },
680 { 0x07, 0x00 },
681 { 0x0c, 0x24 },
682 { 0x0c, 0x24 },
683 { 0x0d, 0x24 },
684 { 0x11, 0x01 },
685 { 0x12, 0x24 },
686 { 0x13, 0x01 },
687 { 0x14, 0x84 },
688 { 0x15, 0x01 },
689 { 0x16, 0x03 },
690 { 0x17, 0x2f },
691 { 0x18, 0xcf },
692 { 0x19, 0x06 },
693 { 0x1a, 0xf5 },
694 { 0x1b, 0x00 },
695 { 0x20, 0x18 },
696 { 0x21, 0x80 },
697 { 0x22, 0x80 },
698 { 0x23, 0x00 },
699 { 0x26, 0xa2 },
700 { 0x27, 0xea },
701 { 0x28, 0x20 },
702 { 0x29, 0x00 },
703 { 0x2a, 0x10 },
704 { 0x2b, 0x00 },
705 { 0x2c, 0x88 },
706 { 0x2d, 0x91 },
707 { 0x2e, 0x80 },
708 { 0x2f, 0x44 },
709 { 0x60, 0x27 },
710 { 0x61, 0x02 },
711 { 0x62, 0x5f },
712 { 0x63, 0xd5 },
713 { 0x64, 0x57 },
714 { 0x65, 0x83 },
715 { 0x66, 0x55 },
716 { 0x67, 0x92 },
717 { 0x68, 0xcf },
718 { 0x69, 0x76 },
719 { 0x6a, 0x22 },
720 { 0x6b, 0x00 },
721 { 0x6c, 0x02 },
722 { 0x6d, 0x44 },
723 { 0x6e, 0x80 },
724 { 0x6f, 0x1d },
725 { 0x70, 0x8b },
726 { 0x71, 0x00 },
727 { 0x72, 0x14 },
728 { 0x73, 0x54 },
729 { 0x74, 0x00 },
730 { 0x75, 0x8e },
731 { 0x76, 0x00 },
732 { 0x77, 0xff },
733 { 0x78, 0x80 },
734 { 0x79, 0x80 },
735 { 0x7a, 0x80 },
736 { 0x7b, 0xe2 },
737 { 0x7c, 0x00 },
738};
739
740/* 7640 and 7648. The defaults should be OK for most registers. */
741static const struct ov_i2c_regvals norm_7640[] = {
742 { 0x12, 0x80 },
743 { 0x12, 0x14 },
744};
745
746/* 7670. Defaults taken from OmniVision provided data,
747* as provided by Jonathan Corbet of OLPC */
748static const struct ov_i2c_regvals norm_7670[] = {
749 { OV7670_REG_COM7, OV7670_COM7_RESET },
750 { OV7670_REG_TSLB, 0x04 }, /* OV */
751 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
752 { OV7670_REG_CLKRC, 0x01 },
753/*
754 * Set the hardware window. These values from OV don't entirely
755 * make sense - hstop is less than hstart. But they work...
756 */
757 { OV7670_REG_HSTART, 0x13 },
758 { OV7670_REG_HSTOP, 0x01 },
759 { OV7670_REG_HREF, 0xb6 },
760 { OV7670_REG_VSTART, 0x02 },
761 { OV7670_REG_VSTOP, 0x7a },
762 { OV7670_REG_VREF, 0x0a },
763
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300764 { OV7670_REG_COM3, 0x00 },
765 { OV7670_REG_COM14, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300766/* Mystery scaling numbers */
767 { 0x70, 0x3a },
768 { 0x71, 0x35 },
769 { 0x72, 0x11 },
770 { 0x73, 0xf0 },
771 { 0xa2, 0x02 },
772/* { OV7670_REG_COM10, 0x0 }, */
773
774/* Gamma curve values */
775 { 0x7a, 0x20 },
776 { 0x7b, 0x10 },
777 { 0x7c, 0x1e },
778 { 0x7d, 0x35 },
779 { 0x7e, 0x5a },
780 { 0x7f, 0x69 },
781 { 0x80, 0x76 },
782 { 0x81, 0x80 },
783 { 0x82, 0x88 },
784 { 0x83, 0x8f },
785 { 0x84, 0x96 },
786 { 0x85, 0xa3 },
787 { 0x86, 0xaf },
788 { 0x87, 0xc4 },
789 { 0x88, 0xd7 },
790 { 0x89, 0xe8 },
791
792/* AGC and AEC parameters. Note we start by disabling those features,
793 then turn them only after tweaking the values. */
794 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
795 | OV7670_COM8_AECSTEP
796 | OV7670_COM8_BFILT },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300797 { OV7670_REG_GAIN, 0x00 },
798 { OV7670_REG_AECH, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300799 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
800 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
801 { OV7670_REG_BD50MAX, 0x05 },
802 { OV7670_REG_BD60MAX, 0x07 },
803 { OV7670_REG_AEW, 0x95 },
804 { OV7670_REG_AEB, 0x33 },
805 { OV7670_REG_VPT, 0xe3 },
806 { OV7670_REG_HAECC1, 0x78 },
807 { OV7670_REG_HAECC2, 0x68 },
808 { 0xa1, 0x03 }, /* magic */
809 { OV7670_REG_HAECC3, 0xd8 },
810 { OV7670_REG_HAECC4, 0xd8 },
811 { OV7670_REG_HAECC5, 0xf0 },
812 { OV7670_REG_HAECC6, 0x90 },
813 { OV7670_REG_HAECC7, 0x94 },
814 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
815 | OV7670_COM8_AECSTEP
816 | OV7670_COM8_BFILT
817 | OV7670_COM8_AGC
818 | OV7670_COM8_AEC },
819
820/* Almost all of these are magic "reserved" values. */
821 { OV7670_REG_COM5, 0x61 },
822 { OV7670_REG_COM6, 0x4b },
823 { 0x16, 0x02 },
824 { OV7670_REG_MVFP, 0x07 },
825 { 0x21, 0x02 },
826 { 0x22, 0x91 },
827 { 0x29, 0x07 },
828 { 0x33, 0x0b },
829 { 0x35, 0x0b },
830 { 0x37, 0x1d },
831 { 0x38, 0x71 },
832 { 0x39, 0x2a },
833 { OV7670_REG_COM12, 0x78 },
834 { 0x4d, 0x40 },
835 { 0x4e, 0x20 },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300836 { OV7670_REG_GFIX, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300837 { 0x6b, 0x4a },
838 { 0x74, 0x10 },
839 { 0x8d, 0x4f },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300840 { 0x8e, 0x00 },
841 { 0x8f, 0x00 },
842 { 0x90, 0x00 },
843 { 0x91, 0x00 },
844 { 0x96, 0x00 },
845 { 0x9a, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300846 { 0xb0, 0x84 },
847 { 0xb1, 0x0c },
848 { 0xb2, 0x0e },
849 { 0xb3, 0x82 },
850 { 0xb8, 0x0a },
851
852/* More reserved magic, some of which tweaks white balance */
853 { 0x43, 0x0a },
854 { 0x44, 0xf0 },
855 { 0x45, 0x34 },
856 { 0x46, 0x58 },
857 { 0x47, 0x28 },
858 { 0x48, 0x3a },
859 { 0x59, 0x88 },
860 { 0x5a, 0x88 },
861 { 0x5b, 0x44 },
862 { 0x5c, 0x67 },
863 { 0x5d, 0x49 },
864 { 0x5e, 0x0e },
865 { 0x6c, 0x0a },
866 { 0x6d, 0x55 },
867 { 0x6e, 0x11 },
868 { 0x6f, 0x9f },
869 /* "9e for advance AWB" */
870 { 0x6a, 0x40 },
871 { OV7670_REG_BLUE, 0x40 },
872 { OV7670_REG_RED, 0x60 },
873 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
874 | OV7670_COM8_AECSTEP
875 | OV7670_COM8_BFILT
876 | OV7670_COM8_AGC
877 | OV7670_COM8_AEC
878 | OV7670_COM8_AWB },
879
880/* Matrix coefficients */
881 { 0x4f, 0x80 },
882 { 0x50, 0x80 },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300883 { 0x51, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300884 { 0x52, 0x22 },
885 { 0x53, 0x5e },
886 { 0x54, 0x80 },
887 { 0x58, 0x9e },
888
889 { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300890 { OV7670_REG_EDGE, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300891 { 0x75, 0x05 },
892 { 0x76, 0xe1 },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300893 { 0x4c, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300894 { 0x77, 0x01 },
895 { OV7670_REG_COM13, OV7670_COM13_GAMMA
896 | OV7670_COM13_UVSAT
897 | 2}, /* was 3 */
898 { 0x4b, 0x09 },
899 { 0xc9, 0x60 },
900 { OV7670_REG_COM16, 0x38 },
901 { 0x56, 0x40 },
902
903 { 0x34, 0x11 },
904 { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
905 { 0xa4, 0x88 },
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -0300906 { 0x96, 0x00 },
Jean-Francois Moine4202f712008-09-03 17:12:15 -0300907 { 0x97, 0x30 },
908 { 0x98, 0x20 },
909 { 0x99, 0x30 },
910 { 0x9a, 0x84 },
911 { 0x9b, 0x29 },
912 { 0x9c, 0x03 },
913 { 0x9d, 0x4c },
914 { 0x9e, 0x3f },
915 { 0x78, 0x04 },
916
917/* Extra-weird stuff. Some sort of multiplexor register */
918 { 0x79, 0x01 },
919 { 0xc8, 0xf0 },
920 { 0x79, 0x0f },
921 { 0xc8, 0x00 },
922 { 0x79, 0x10 },
923 { 0xc8, 0x7e },
924 { 0x79, 0x0a },
925 { 0xc8, 0x80 },
926 { 0x79, 0x0b },
927 { 0xc8, 0x01 },
928 { 0x79, 0x0c },
929 { 0xc8, 0x0f },
930 { 0x79, 0x0d },
931 { 0xc8, 0x20 },
932 { 0x79, 0x09 },
933 { 0xc8, 0x80 },
934 { 0x79, 0x02 },
935 { 0xc8, 0xc0 },
936 { 0x79, 0x03 },
937 { 0xc8, 0x40 },
938 { 0x79, 0x05 },
939 { 0xc8, 0x30 },
940 { 0x79, 0x26 },
941};
942
943static const struct ov_i2c_regvals norm_8610[] = {
944 { 0x12, 0x80 },
945 { 0x00, 0x00 },
946 { 0x01, 0x80 },
947 { 0x02, 0x80 },
948 { 0x03, 0xc0 },
949 { 0x04, 0x30 },
950 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
951 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
952 { 0x0a, 0x86 },
953 { 0x0b, 0xb0 },
954 { 0x0c, 0x20 },
955 { 0x0d, 0x20 },
956 { 0x11, 0x01 },
957 { 0x12, 0x25 },
958 { 0x13, 0x01 },
959 { 0x14, 0x04 },
960 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
961 { 0x16, 0x03 },
962 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
963 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
964 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
965 { 0x1a, 0xf5 },
966 { 0x1b, 0x00 },
967 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
968 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
969 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
970 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
971 { 0x26, 0xa2 },
972 { 0x27, 0xea },
973 { 0x28, 0x00 },
974 { 0x29, 0x00 },
975 { 0x2a, 0x80 },
976 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
977 { 0x2c, 0xac },
978 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
979 { 0x2e, 0x80 },
980 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
981 { 0x4c, 0x00 },
982 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
983 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
984 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
985 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
986 { 0x63, 0xff },
987 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
988 * maybe thats wrong */
989 { 0x65, 0x00 },
990 { 0x66, 0x55 },
991 { 0x67, 0xb0 },
992 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
993 { 0x69, 0x02 },
994 { 0x6a, 0x22 },
995 { 0x6b, 0x00 },
996 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
997 * deleting bit7 colors the first images red */
998 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
999 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
1000 { 0x6f, 0x01 },
1001 { 0x70, 0x8b },
1002 { 0x71, 0x00 },
1003 { 0x72, 0x14 },
1004 { 0x73, 0x54 },
1005 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
1006 { 0x75, 0x0e },
1007 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
1008 { 0x77, 0xff },
1009 { 0x78, 0x80 },
1010 { 0x79, 0x80 },
1011 { 0x7a, 0x80 },
1012 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
1013 { 0x7c, 0x00 },
1014 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
1015 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
1016 { 0x7f, 0xfb },
1017 { 0x80, 0x28 },
1018 { 0x81, 0x00 },
1019 { 0x82, 0x23 },
1020 { 0x83, 0x0b },
1021 { 0x84, 0x00 },
1022 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
1023 { 0x86, 0xc9 },
1024 { 0x87, 0x00 },
1025 { 0x88, 0x00 },
1026 { 0x89, 0x01 },
1027 { 0x12, 0x20 },
1028 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
1029};
1030
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001031static unsigned char ov7670_abs_to_sm(unsigned char v)
1032{
1033 if (v > 127)
1034 return v & 0x7f;
1035 return (128 - v) | 0x80;
1036}
1037
1038/* Write a OV519 register */
1039static int reg_w(struct sd *sd, __u16 index, __u8 value)
1040{
1041 int ret;
Hans de Goede49809d62009-06-07 12:10:39 -03001042 int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001043
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001044 sd->gspca_dev.usb_buf[0] = value;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001045 ret = usb_control_msg(sd->gspca_dev.dev,
1046 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
Hans de Goede49809d62009-06-07 12:10:39 -03001047 req,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001048 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1049 0, index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001050 sd->gspca_dev.usb_buf, 1, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001051 if (ret < 0)
1052 PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value);
1053 return ret;
1054}
1055
1056/* Read from a OV519 register */
1057/* returns: negative is error, pos or zero is data */
1058static int reg_r(struct sd *sd, __u16 index)
1059{
1060 int ret;
Hans de Goede49809d62009-06-07 12:10:39 -03001061 int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001062
1063 ret = usb_control_msg(sd->gspca_dev.dev,
1064 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
Hans de Goede49809d62009-06-07 12:10:39 -03001065 req,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001066 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001067 0, index, sd->gspca_dev.usb_buf, 1, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001068
1069 if (ret >= 0)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001070 ret = sd->gspca_dev.usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071 else
1072 PDEBUG(D_ERR, "Read reg [0x%02x] failed", index);
1073 return ret;
1074}
1075
1076/* Read 8 values from a OV519 register */
1077static int reg_r8(struct sd *sd,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001078 __u16 index)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001079{
1080 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001081
1082 ret = usb_control_msg(sd->gspca_dev.dev,
1083 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
1084 1, /* REQ_IO */
1085 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001086 0, index, sd->gspca_dev.usb_buf, 8, 500);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001087
1088 if (ret >= 0)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001089 ret = sd->gspca_dev.usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090 else
1091 PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index);
1092 return ret;
1093}
1094
1095/*
1096 * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
1097 * the same position as 1's in "mask" are cleared and set to "value". Bits
1098 * that are in the same position as 0's in "mask" are preserved, regardless
1099 * of their respective state in "value".
1100 */
1101static int reg_w_mask(struct sd *sd,
1102 __u16 index,
1103 __u8 value,
1104 __u8 mask)
1105{
1106 int ret;
1107 __u8 oldval;
1108
1109 if (mask != 0xff) {
1110 value &= mask; /* Enforce mask on value */
1111 ret = reg_r(sd, index);
1112 if (ret < 0)
1113 return ret;
1114
1115 oldval = ret & ~mask; /* Clear the masked bits */
1116 value |= oldval; /* Set the desired bits */
1117 }
1118 return reg_w(sd, index, value);
1119}
1120
1121/*
Hans de Goede49809d62009-06-07 12:10:39 -03001122 * Writes multiple (n) byte value to a single register. Only valid with certain
1123 * registers (0x30 and 0xc4 - 0xce).
1124 */
1125static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
1126{
1127 int ret;
1128
1129 *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
1130
1131 ret = usb_control_msg(sd->gspca_dev.dev,
1132 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
1133 1 /* REG_IO */,
1134 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1135 0, index,
1136 sd->gspca_dev.usb_buf, n, 500);
1137 if (ret < 0)
1138 PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value);
1139 return ret;
1140}
1141
Hans de Goede1876bb92009-06-14 06:45:50 -03001142static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
1143{
1144 int rc, retries;
1145
1146 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
1147
1148 /* Three byte write cycle */
1149 for (retries = 6; ; ) {
1150 /* Select camera register */
1151 rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
1152 if (rc < 0)
1153 return rc;
1154
1155 /* Write "value" to I2C data port of OV511 */
1156 rc = reg_w(sd, R51x_I2C_DATA, value);
1157 if (rc < 0)
1158 return rc;
1159
1160 /* Initiate 3-byte write cycle */
1161 rc = reg_w(sd, R511_I2C_CTL, 0x01);
1162 if (rc < 0)
1163 return rc;
1164
1165 do
1166 rc = reg_r(sd, R511_I2C_CTL);
1167 while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
1168
1169 if (rc < 0)
1170 return rc;
1171
1172 if ((rc & 2) == 0) /* Ack? */
1173 break;
1174 if (--retries < 0) {
1175 PDEBUG(D_USBO, "i2c write retries exhausted");
1176 return -1;
1177 }
1178 }
1179
1180 return 0;
1181}
1182
1183static int ov511_i2c_r(struct sd *sd, __u8 reg)
1184{
1185 int rc, value, retries;
1186
1187 /* Two byte write cycle */
1188 for (retries = 6; ; ) {
1189 /* Select camera register */
1190 rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
1191 if (rc < 0)
1192 return rc;
1193
1194 /* Initiate 2-byte write cycle */
1195 rc = reg_w(sd, R511_I2C_CTL, 0x03);
1196 if (rc < 0)
1197 return rc;
1198
1199 do
1200 rc = reg_r(sd, R511_I2C_CTL);
1201 while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
1202
1203 if (rc < 0)
1204 return rc;
1205
1206 if ((rc & 2) == 0) /* Ack? */
1207 break;
1208
1209 /* I2C abort */
1210 reg_w(sd, R511_I2C_CTL, 0x10);
1211
1212 if (--retries < 0) {
1213 PDEBUG(D_USBI, "i2c write retries exhausted");
1214 return -1;
1215 }
1216 }
1217
1218 /* Two byte read cycle */
1219 for (retries = 6; ; ) {
1220 /* Initiate 2-byte read cycle */
1221 rc = reg_w(sd, R511_I2C_CTL, 0x05);
1222 if (rc < 0)
1223 return rc;
1224
1225 do
1226 rc = reg_r(sd, R511_I2C_CTL);
1227 while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
1228
1229 if (rc < 0)
1230 return rc;
1231
1232 if ((rc & 2) == 0) /* Ack? */
1233 break;
1234
1235 /* I2C abort */
1236 rc = reg_w(sd, R511_I2C_CTL, 0x10);
1237 if (rc < 0)
1238 return rc;
1239
1240 if (--retries < 0) {
1241 PDEBUG(D_USBI, "i2c read retries exhausted");
1242 return -1;
1243 }
1244 }
1245
1246 value = reg_r(sd, R51x_I2C_DATA);
1247
1248 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
1249
1250 /* This is needed to make i2c_w() work */
1251 rc = reg_w(sd, R511_I2C_CTL, 0x05);
1252 if (rc < 0)
1253 return rc;
1254
1255 return value;
1256}
Hans de Goede49809d62009-06-07 12:10:39 -03001257
1258/*
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001259 * The OV518 I2C I/O procedure is different, hence, this function.
1260 * This is normally only called from i2c_w(). Note that this function
1261 * always succeeds regardless of whether the sensor is present and working.
1262 */
Hans de Goede1876bb92009-06-14 06:45:50 -03001263static int ov518_i2c_w(struct sd *sd,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001264 __u8 reg,
1265 __u8 value)
1266{
1267 int rc;
1268
1269 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
1270
1271 /* Select camera register */
1272 rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
1273 if (rc < 0)
1274 return rc;
1275
1276 /* Write "value" to I2C data port of OV511 */
1277 rc = reg_w(sd, R51x_I2C_DATA, value);
1278 if (rc < 0)
1279 return rc;
1280
1281 /* Initiate 3-byte write cycle */
1282 rc = reg_w(sd, R518_I2C_CTL, 0x01);
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03001283 if (rc < 0)
1284 return rc;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285
1286 /* wait for write complete */
1287 msleep(4);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001288 return reg_r8(sd, R518_I2C_CTL);
1289}
1290
1291/*
1292 * returns: negative is error, pos or zero is data
1293 *
1294 * The OV518 I2C I/O procedure is different, hence, this function.
1295 * This is normally only called from i2c_r(). Note that this function
1296 * always succeeds regardless of whether the sensor is present and working.
1297 */
Hans de Goede1876bb92009-06-14 06:45:50 -03001298static int ov518_i2c_r(struct sd *sd, __u8 reg)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001299{
1300 int rc, value;
1301
1302 /* Select camera register */
1303 rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
1304 if (rc < 0)
1305 return rc;
1306
1307 /* Initiate 2-byte write cycle */
1308 rc = reg_w(sd, R518_I2C_CTL, 0x03);
1309 if (rc < 0)
1310 return rc;
1311
1312 /* Initiate 2-byte read cycle */
1313 rc = reg_w(sd, R518_I2C_CTL, 0x05);
1314 if (rc < 0)
1315 return rc;
1316 value = reg_r(sd, R51x_I2C_DATA);
1317 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
1318 return value;
1319}
1320
Hans de Goede1876bb92009-06-14 06:45:50 -03001321static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
1322{
1323 switch (sd->bridge) {
1324 case BRIDGE_OV511:
1325 case BRIDGE_OV511PLUS:
1326 return ov511_i2c_w(sd, reg, value);
1327 case BRIDGE_OV518:
1328 case BRIDGE_OV518PLUS:
1329 case BRIDGE_OV519:
1330 return ov518_i2c_w(sd, reg, value);
1331 }
1332 return -1; /* Should never happen */
1333}
1334
1335static int i2c_r(struct sd *sd, __u8 reg)
1336{
1337 switch (sd->bridge) {
1338 case BRIDGE_OV511:
1339 case BRIDGE_OV511PLUS:
1340 return ov511_i2c_r(sd, reg);
1341 case BRIDGE_OV518:
1342 case BRIDGE_OV518PLUS:
1343 case BRIDGE_OV519:
1344 return ov518_i2c_r(sd, reg);
1345 }
1346 return -1; /* Should never happen */
1347}
1348
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001349/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
1350 * the same position as 1's in "mask" are cleared and set to "value". Bits
1351 * that are in the same position as 0's in "mask" are preserved, regardless
1352 * of their respective state in "value".
1353 */
1354static int i2c_w_mask(struct sd *sd,
1355 __u8 reg,
1356 __u8 value,
1357 __u8 mask)
1358{
1359 int rc;
1360 __u8 oldval;
1361
1362 value &= mask; /* Enforce mask on value */
1363 rc = i2c_r(sd, reg);
1364 if (rc < 0)
1365 return rc;
1366 oldval = rc & ~mask; /* Clear the masked bits */
1367 value |= oldval; /* Set the desired bits */
1368 return i2c_w(sd, reg, value);
1369}
1370
1371/* Temporarily stops OV511 from functioning. Must do this before changing
1372 * registers while the camera is streaming */
1373static inline int ov51x_stop(struct sd *sd)
1374{
1375 PDEBUG(D_STREAM, "stopping");
1376 sd->stopped = 1;
Hans de Goede49809d62009-06-07 12:10:39 -03001377 switch (sd->bridge) {
1378 case BRIDGE_OV511:
1379 case BRIDGE_OV511PLUS:
1380 return reg_w(sd, R51x_SYS_RESET, 0x3d);
1381 case BRIDGE_OV518:
1382 case BRIDGE_OV518PLUS:
1383 return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
1384 case BRIDGE_OV519:
1385 return reg_w(sd, OV519_SYS_RESET1, 0x0f);
1386 }
1387
1388 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001389}
1390
1391/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
1392 * actually stopped (for performance). */
1393static inline int ov51x_restart(struct sd *sd)
1394{
Hans de Goede49809d62009-06-07 12:10:39 -03001395 int rc;
1396
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001397 PDEBUG(D_STREAM, "restarting");
1398 if (!sd->stopped)
1399 return 0;
1400 sd->stopped = 0;
1401
1402 /* Reinitialize the stream */
Hans de Goede49809d62009-06-07 12:10:39 -03001403 switch (sd->bridge) {
1404 case BRIDGE_OV511:
1405 case BRIDGE_OV511PLUS:
1406 return reg_w(sd, R51x_SYS_RESET, 0x00);
1407 case BRIDGE_OV518:
1408 case BRIDGE_OV518PLUS:
1409 rc = reg_w(sd, 0x2f, 0x80);
1410 if (rc < 0)
1411 return rc;
1412 return reg_w(sd, R51x_SYS_RESET, 0x00);
1413 case BRIDGE_OV519:
1414 return reg_w(sd, OV519_SYS_RESET1, 0x00);
1415 }
1416
1417 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001418}
1419
1420/* This does an initial reset of an OmniVision sensor and ensures that I2C
1421 * is synchronized. Returns <0 on failure.
1422 */
1423static int init_ov_sensor(struct sd *sd)
1424{
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03001425 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001426
1427 /* Reset the sensor */
1428 if (i2c_w(sd, 0x12, 0x80) < 0)
1429 return -EIO;
1430
1431 /* Wait for it to initialize */
1432 msleep(150);
1433
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03001434 for (i = 0; i < i2c_detect_tries; i++) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001435 if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
1436 i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03001437 PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
1438 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001439 }
1440
1441 /* Reset the sensor */
1442 if (i2c_w(sd, 0x12, 0x80) < 0)
1443 return -EIO;
1444 /* Wait for it to initialize */
1445 msleep(150);
1446 /* Dummy read to sync I2C */
1447 if (i2c_r(sd, 0x00) < 0)
1448 return -EIO;
1449 }
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03001450 return -EIO;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001451}
1452
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001453/* Set the read and write slave IDs. The "slave" argument is the write slave,
1454 * and the read slave will be set to (slave + 1).
1455 * This should not be called from outside the i2c I/O functions.
1456 * Sets I2C read and write slave IDs. Returns <0 for error
1457 */
1458static int ov51x_set_slave_ids(struct sd *sd,
1459 __u8 slave)
1460{
1461 int rc;
1462
1463 rc = reg_w(sd, R51x_I2C_W_SID, slave);
1464 if (rc < 0)
1465 return rc;
1466 return reg_w(sd, R51x_I2C_R_SID, slave + 1);
1467}
1468
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001469static int write_regvals(struct sd *sd,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001470 const struct ov_regvals *regvals,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001471 int n)
1472{
1473 int rc;
1474
1475 while (--n >= 0) {
1476 rc = reg_w(sd, regvals->reg, regvals->val);
1477 if (rc < 0)
1478 return rc;
1479 regvals++;
1480 }
1481 return 0;
1482}
1483
1484static int write_i2c_regvals(struct sd *sd,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001485 const struct ov_i2c_regvals *regvals,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001486 int n)
1487{
1488 int rc;
1489
1490 while (--n >= 0) {
1491 rc = i2c_w(sd, regvals->reg, regvals->val);
1492 if (rc < 0)
1493 return rc;
1494 regvals++;
1495 }
1496 return 0;
1497}
1498
1499/****************************************************************************
1500 *
1501 * OV511 and sensor configuration
1502 *
1503 ***************************************************************************/
1504
1505/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
1506 * the same register settings as the OV8610, since they are very similar.
1507 */
1508static int ov8xx0_configure(struct sd *sd)
1509{
1510 int rc;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001511
1512 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
1513
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001514 /* Detect sensor (sub)type */
1515 rc = i2c_r(sd, OV7610_REG_COM_I);
1516 if (rc < 0) {
1517 PDEBUG(D_ERR, "Error detecting sensor type");
1518 return -1;
1519 }
1520 if ((rc & 3) == 1) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001521 sd->sensor = SEN_OV8610;
1522 } else {
1523 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
1524 return -1;
1525 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001526
1527 /* Set sensor-specific vars */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001528/* sd->sif = 0; already done */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001529 return 0;
1530}
1531
1532/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
1533 * the same register settings as the OV7610, since they are very similar.
1534 */
1535static int ov7xx0_configure(struct sd *sd)
1536{
1537 int rc, high, low;
1538
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001539
1540 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
1541
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001542 /* Detect sensor (sub)type */
1543 rc = i2c_r(sd, OV7610_REG_COM_I);
1544
1545 /* add OV7670 here
1546 * it appears to be wrongly detected as a 7610 by default */
1547 if (rc < 0) {
1548 PDEBUG(D_ERR, "Error detecting sensor type");
1549 return -1;
1550 }
1551 if ((rc & 3) == 3) {
1552 /* quick hack to make OV7670s work */
1553 high = i2c_r(sd, 0x0a);
1554 low = i2c_r(sd, 0x0b);
1555 /* info("%x, %x", high, low); */
1556 if (high == 0x76 && low == 0x73) {
1557 PDEBUG(D_PROBE, "Sensor is an OV7670");
1558 sd->sensor = SEN_OV7670;
1559 } else {
1560 PDEBUG(D_PROBE, "Sensor is an OV7610");
1561 sd->sensor = SEN_OV7610;
1562 }
1563 } else if ((rc & 3) == 1) {
1564 /* I don't know what's different about the 76BE yet. */
1565 if (i2c_r(sd, 0x15) & 1)
1566 PDEBUG(D_PROBE, "Sensor is an OV7620AE");
1567 else
1568 PDEBUG(D_PROBE, "Sensor is an OV76BE");
1569
1570 /* OV511+ will return all zero isoc data unless we
1571 * configure the sensor as a 7620. Someone needs to
1572 * find the exact reg. setting that causes this. */
1573 sd->sensor = SEN_OV76BE;
1574 } else if ((rc & 3) == 0) {
1575 /* try to read product id registers */
1576 high = i2c_r(sd, 0x0a);
1577 if (high < 0) {
1578 PDEBUG(D_ERR, "Error detecting camera chip PID");
1579 return high;
1580 }
1581 low = i2c_r(sd, 0x0b);
1582 if (low < 0) {
1583 PDEBUG(D_ERR, "Error detecting camera chip VER");
1584 return low;
1585 }
1586 if (high == 0x76) {
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001587 switch (low) {
1588 case 0x30:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001589 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
Jean-Francois Moine4202f712008-09-03 17:12:15 -03001590 PDEBUG(D_ERR,
1591 "7630 is not supported by this driver");
1592 return -1;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001593 case 0x40:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001594 PDEBUG(D_PROBE, "Sensor is an OV7645");
1595 sd->sensor = SEN_OV7640; /* FIXME */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001596 break;
1597 case 0x45:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001598 PDEBUG(D_PROBE, "Sensor is an OV7645B");
1599 sd->sensor = SEN_OV7640; /* FIXME */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001600 break;
1601 case 0x48:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001602 PDEBUG(D_PROBE, "Sensor is an OV7648");
1603 sd->sensor = SEN_OV7640; /* FIXME */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001604 break;
1605 default:
1606 PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001607 return -1;
1608 }
1609 } else {
1610 PDEBUG(D_PROBE, "Sensor is an OV7620");
1611 sd->sensor = SEN_OV7620;
1612 }
1613 } else {
1614 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
1615 return -1;
1616 }
1617
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001618 /* Set sensor-specific vars */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001619/* sd->sif = 0; already done */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001620 return 0;
1621}
1622
1623/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
1624static int ov6xx0_configure(struct sd *sd)
1625{
1626 int rc;
Jean-Francois Moine4202f712008-09-03 17:12:15 -03001627 PDEBUG(D_PROBE, "starting OV6xx0 configuration");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001628
1629 /* Detect sensor (sub)type */
1630 rc = i2c_r(sd, OV7610_REG_COM_I);
1631 if (rc < 0) {
1632 PDEBUG(D_ERR, "Error detecting sensor type");
1633 return -1;
1634 }
1635
1636 /* Ugh. The first two bits are the version bits, but
1637 * the entire register value must be used. I guess OVT
1638 * underestimated how many variants they would make. */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001639 switch (rc) {
1640 case 0x00:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001641 sd->sensor = SEN_OV6630;
1642 PDEBUG(D_ERR,
1643 "WARNING: Sensor is an OV66308. Your camera may have");
1644 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001645 break;
1646 case 0x01:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001647 sd->sensor = SEN_OV6620;
Hans de Goede7d971372009-06-14 05:28:17 -03001648 PDEBUG(D_PROBE, "Sensor is an OV6620");
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001649 break;
1650 case 0x02:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001651 sd->sensor = SEN_OV6630;
1652 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001653 break;
1654 case 0x03:
Hans de Goede7d971372009-06-14 05:28:17 -03001655 sd->sensor = SEN_OV66308AF;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001656 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001657 break;
1658 case 0x90:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001659 sd->sensor = SEN_OV6630;
1660 PDEBUG(D_ERR,
1661 "WARNING: Sensor is an OV66307. Your camera may have");
1662 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001663 break;
1664 default:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001665 PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc);
1666 return -1;
1667 }
1668
1669 /* Set sensor-specific vars */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03001670 sd->sif = 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001671
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001672 return 0;
1673}
1674
1675/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
1676static void ov51x_led_control(struct sd *sd, int on)
1677{
Hans de Goede9e4d8252009-06-14 06:25:06 -03001678 if (sd->invert_led)
1679 on = !on;
1680
Hans de Goede49809d62009-06-07 12:10:39 -03001681 switch (sd->bridge) {
1682 /* OV511 has no LED control */
1683 case BRIDGE_OV511PLUS:
1684 reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
1685 break;
1686 case BRIDGE_OV518:
1687 case BRIDGE_OV518PLUS:
1688 reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
1689 break;
1690 case BRIDGE_OV519:
1691 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
1692 break;
1693 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001694}
1695
Hans de Goede1876bb92009-06-14 06:45:50 -03001696static int ov51x_upload_quan_tables(struct sd *sd)
Hans de Goede49809d62009-06-07 12:10:39 -03001697{
Hans de Goede1876bb92009-06-14 06:45:50 -03001698 const unsigned char yQuanTable511[] = {
1699 0, 1, 1, 2, 2, 3, 3, 4,
1700 1, 1, 1, 2, 2, 3, 4, 4,
1701 1, 1, 2, 2, 3, 4, 4, 4,
1702 2, 2, 2, 3, 4, 4, 4, 4,
1703 2, 2, 3, 4, 4, 5, 5, 5,
1704 3, 3, 4, 4, 5, 5, 5, 5,
1705 3, 4, 4, 4, 5, 5, 5, 5,
1706 4, 4, 4, 4, 5, 5, 5, 5
1707 };
1708
1709 const unsigned char uvQuanTable511[] = {
1710 0, 2, 2, 3, 4, 4, 4, 4,
1711 2, 2, 2, 4, 4, 4, 4, 4,
1712 2, 2, 3, 4, 4, 4, 4, 4,
1713 3, 4, 4, 4, 4, 4, 4, 4,
1714 4, 4, 4, 4, 4, 4, 4, 4,
1715 4, 4, 4, 4, 4, 4, 4, 4,
1716 4, 4, 4, 4, 4, 4, 4, 4,
1717 4, 4, 4, 4, 4, 4, 4, 4
1718 };
1719
1720 /* OV518 quantization tables are 8x4 (instead of 8x8) */
Hans de Goede49809d62009-06-07 12:10:39 -03001721 const unsigned char yQuanTable518[] = {
1722 5, 4, 5, 6, 6, 7, 7, 7,
1723 5, 5, 5, 5, 6, 7, 7, 7,
1724 6, 6, 6, 6, 7, 7, 7, 8,
1725 7, 7, 6, 7, 7, 7, 8, 8
1726 };
1727
1728 const unsigned char uvQuanTable518[] = {
1729 6, 6, 6, 7, 7, 7, 7, 7,
1730 6, 6, 6, 7, 7, 7, 7, 7,
1731 6, 6, 6, 7, 7, 7, 7, 8,
1732 7, 7, 7, 7, 7, 7, 8, 8
1733 };
1734
Hans de Goede1876bb92009-06-14 06:45:50 -03001735 const unsigned char *pYTable, *pUVTable;
Hans de Goede49809d62009-06-07 12:10:39 -03001736 unsigned char val0, val1;
Hans de Goede1876bb92009-06-14 06:45:50 -03001737 int i, size, rc, reg = R51x_COMP_LUT_BEGIN;
Hans de Goede49809d62009-06-07 12:10:39 -03001738
1739 PDEBUG(D_PROBE, "Uploading quantization tables");
1740
Hans de Goede1876bb92009-06-14 06:45:50 -03001741 if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
1742 pYTable = yQuanTable511;
1743 pUVTable = uvQuanTable511;
1744 size = 32;
1745 } else {
1746 pYTable = yQuanTable518;
1747 pUVTable = uvQuanTable518;
1748 size = 16;
1749 }
1750
1751 for (i = 0; i < size; i++) {
Hans de Goede49809d62009-06-07 12:10:39 -03001752 val0 = *pYTable++;
1753 val1 = *pYTable++;
1754 val0 &= 0x0f;
1755 val1 &= 0x0f;
1756 val0 |= val1 << 4;
1757 rc = reg_w(sd, reg, val0);
1758 if (rc < 0)
1759 return rc;
1760
1761 val0 = *pUVTable++;
1762 val1 = *pUVTable++;
1763 val0 &= 0x0f;
1764 val1 &= 0x0f;
1765 val0 |= val1 << 4;
Hans de Goede1876bb92009-06-14 06:45:50 -03001766 rc = reg_w(sd, reg + size, val0);
Hans de Goede49809d62009-06-07 12:10:39 -03001767 if (rc < 0)
1768 return rc;
1769
1770 reg++;
1771 }
1772
1773 return 0;
1774}
1775
Hans de Goede1876bb92009-06-14 06:45:50 -03001776/* This initializes the OV511/OV511+ and the sensor */
1777static int ov511_configure(struct gspca_dev *gspca_dev)
1778{
1779 struct sd *sd = (struct sd *) gspca_dev;
1780 int rc;
1781
1782 /* For 511 and 511+ */
1783 const struct ov_regvals init_511[] = {
1784 { R51x_SYS_RESET, 0x7f },
1785 { R51x_SYS_INIT, 0x01 },
1786 { R51x_SYS_RESET, 0x7f },
1787 { R51x_SYS_INIT, 0x01 },
1788 { R51x_SYS_RESET, 0x3f },
1789 { R51x_SYS_INIT, 0x01 },
1790 { R51x_SYS_RESET, 0x3d },
1791 };
1792
1793 const struct ov_regvals norm_511[] = {
1794 { R511_DRAM_FLOW_CTL, 0x01 },
1795 { R51x_SYS_SNAP, 0x00 },
1796 { R51x_SYS_SNAP, 0x02 },
1797 { R51x_SYS_SNAP, 0x00 },
1798 { R511_FIFO_OPTS, 0x1f },
1799 { R511_COMP_EN, 0x00 },
1800 { R511_COMP_LUT_EN, 0x03 },
1801 };
1802
1803 const struct ov_regvals norm_511_p[] = {
1804 { R511_DRAM_FLOW_CTL, 0xff },
1805 { R51x_SYS_SNAP, 0x00 },
1806 { R51x_SYS_SNAP, 0x02 },
1807 { R51x_SYS_SNAP, 0x00 },
1808 { R511_FIFO_OPTS, 0xff },
1809 { R511_COMP_EN, 0x00 },
1810 { R511_COMP_LUT_EN, 0x03 },
1811 };
1812
1813 const struct ov_regvals compress_511[] = {
1814 { 0x70, 0x1f },
1815 { 0x71, 0x05 },
1816 { 0x72, 0x06 },
1817 { 0x73, 0x06 },
1818 { 0x74, 0x14 },
1819 { 0x75, 0x03 },
1820 { 0x76, 0x04 },
1821 { 0x77, 0x04 },
1822 };
1823
1824 PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
1825
1826 rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511));
1827 if (rc < 0)
1828 return rc;
1829
1830 switch (sd->bridge) {
1831 case BRIDGE_OV511:
1832 rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
1833 if (rc < 0)
1834 return rc;
1835 break;
1836 case BRIDGE_OV511PLUS:
1837 rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
1838 if (rc < 0)
1839 return rc;
1840 break;
1841 }
1842
1843 /* Init compression */
1844 rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
1845 if (rc < 0)
1846 return rc;
1847
1848 rc = ov51x_upload_quan_tables(sd);
1849 if (rc < 0) {
1850 PDEBUG(D_ERR, "Error uploading quantization tables");
1851 return rc;
1852 }
1853
1854 return 0;
1855}
1856
Hans de Goede49809d62009-06-07 12:10:39 -03001857/* This initializes the OV518/OV518+ and the sensor */
1858static int ov518_configure(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001859{
1860 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede49809d62009-06-07 12:10:39 -03001861 int rc;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001862
Hans de Goede49809d62009-06-07 12:10:39 -03001863 /* For 518 and 518+ */
1864 static struct ov_regvals init_518[] = {
1865 { R51x_SYS_RESET, 0x40 },
1866 { R51x_SYS_INIT, 0xe1 },
1867 { R51x_SYS_RESET, 0x3e },
1868 { R51x_SYS_INIT, 0xe1 },
1869 { R51x_SYS_RESET, 0x00 },
1870 { R51x_SYS_INIT, 0xe1 },
1871 { 0x46, 0x00 },
1872 { 0x5d, 0x03 },
1873 };
1874
1875 static struct ov_regvals norm_518[] = {
1876 { R51x_SYS_SNAP, 0x02 }, /* Reset */
1877 { R51x_SYS_SNAP, 0x01 }, /* Enable */
1878 { 0x31, 0x0f },
1879 { 0x5d, 0x03 },
1880 { 0x24, 0x9f },
1881 { 0x25, 0x90 },
1882 { 0x20, 0x00 },
1883 { 0x51, 0x04 },
1884 { 0x71, 0x19 },
1885 { 0x2f, 0x80 },
1886 };
1887
1888 static struct ov_regvals norm_518_p[] = {
1889 { R51x_SYS_SNAP, 0x02 }, /* Reset */
1890 { R51x_SYS_SNAP, 0x01 }, /* Enable */
1891 { 0x31, 0x0f },
1892 { 0x5d, 0x03 },
1893 { 0x24, 0x9f },
1894 { 0x25, 0x90 },
1895 { 0x20, 0x60 },
1896 { 0x51, 0x02 },
1897 { 0x71, 0x19 },
1898 { 0x40, 0xff },
1899 { 0x41, 0x42 },
1900 { 0x46, 0x00 },
1901 { 0x33, 0x04 },
1902 { 0x21, 0x19 },
1903 { 0x3f, 0x10 },
1904 { 0x2f, 0x80 },
1905 };
1906
1907 /* First 5 bits of custom ID reg are a revision ID on OV518 */
1908 PDEBUG(D_PROBE, "Device revision %d",
1909 0x1F & reg_r(sd, R51x_SYS_CUST_ID));
1910
1911 rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
1912 if (rc < 0)
1913 return rc;
1914
1915 /* Set LED GPIO pin to output mode */
1916 rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
1917 if (rc < 0)
1918 return rc;
1919
1920 switch (sd->bridge) {
1921 case BRIDGE_OV518:
1922 rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
1923 if (rc < 0)
1924 return rc;
1925 break;
1926 case BRIDGE_OV518PLUS:
1927 rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
1928 if (rc < 0)
1929 return rc;
1930 break;
1931 }
1932
Hans de Goede1876bb92009-06-14 06:45:50 -03001933 rc = ov51x_upload_quan_tables(sd);
Hans de Goede49809d62009-06-07 12:10:39 -03001934 if (rc < 0) {
1935 PDEBUG(D_ERR, "Error uploading quantization tables");
1936 return rc;
1937 }
1938
1939 rc = reg_w(sd, 0x2f, 0x80);
1940 if (rc < 0)
1941 return rc;
1942
1943 return 0;
1944}
1945
1946static int ov519_configure(struct sd *sd)
1947{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001948 static const struct ov_regvals init_519[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001949 { 0x5a, 0x6d }, /* EnableSystem */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001950 { 0x53, 0x9b },
1951 { 0x54, 0xff }, /* set bit2 to enable jpeg */
1952 { 0x5d, 0x03 },
1953 { 0x49, 0x01 },
1954 { 0x48, 0x00 },
1955 /* Set LED pin to output mode. Bit 4 must be cleared or sensor
1956 * detection will fail. This deserves further investigation. */
1957 { OV519_GPIO_IO_CTRL0, 0xee },
1958 { 0x51, 0x0f }, /* SetUsbInit */
1959 { 0x51, 0x00 },
1960 { 0x22, 0x00 },
1961 /* windows reads 0x55 at this point*/
1962 };
1963
Hans de Goede49809d62009-06-07 12:10:39 -03001964 return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
1965}
1966
1967/* this function is called at probe time */
1968static int sd_config(struct gspca_dev *gspca_dev,
1969 const struct usb_device_id *id)
1970{
1971 struct sd *sd = (struct sd *) gspca_dev;
1972 struct cam *cam;
1973 int ret = 0;
1974
Hans de Goede9e4d8252009-06-14 06:25:06 -03001975 sd->bridge = id->driver_info & BRIDGE_MASK;
1976 sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
Hans de Goede49809d62009-06-07 12:10:39 -03001977
1978 switch (sd->bridge) {
Hans de Goede1876bb92009-06-14 06:45:50 -03001979 case BRIDGE_OV511:
1980 case BRIDGE_OV511PLUS:
1981 ret = ov511_configure(gspca_dev);
1982 break;
Hans de Goede49809d62009-06-07 12:10:39 -03001983 case BRIDGE_OV518:
1984 case BRIDGE_OV518PLUS:
1985 ret = ov518_configure(gspca_dev);
1986 break;
1987 case BRIDGE_OV519:
1988 ret = ov519_configure(sd);
1989 break;
1990 }
1991
1992 if (ret)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001993 goto error;
Hans de Goede49809d62009-06-07 12:10:39 -03001994
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001995 ov51x_led_control(sd, 0); /* turn LED off */
1996
1997 /* Test for 76xx */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001998 if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
1999 goto error;
2000
2001 /* The OV519 must be more aggressive about sensor detection since
2002 * I2C write will never fail if the sensor is not present. We have
2003 * to try to initialize the sensor to detect its presence */
Jean-Francois Moine4202f712008-09-03 17:12:15 -03002004 if (init_ov_sensor(sd) >= 0) {
2005 if (ov7xx0_configure(sd) < 0) {
2006 PDEBUG(D_ERR, "Failed to configure OV7xx0");
2007 goto error;
2008 }
2009 } else {
2010
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002011 /* Test for 6xx0 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002012 if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
2013 goto error;
2014
Jean-Francois Moine4202f712008-09-03 17:12:15 -03002015 if (init_ov_sensor(sd) >= 0) {
2016 if (ov6xx0_configure(sd) < 0) {
2017 PDEBUG(D_ERR, "Failed to configure OV6xx0");
2018 goto error;
2019 }
2020 } else {
2021
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002022 /* Test for 8xx0 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002023 if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
2024 goto error;
2025
2026 if (init_ov_sensor(sd) < 0) {
2027 PDEBUG(D_ERR,
2028 "Can't determine sensor slave IDs");
2029 goto error;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002030 }
Jean-Francois Moine4202f712008-09-03 17:12:15 -03002031 if (ov8xx0_configure(sd) < 0) {
2032 PDEBUG(D_ERR,
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002033 "Failed to configure OV8xx0 sensor");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002034 goto error;
2035 }
2036 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002037 }
2038
2039 cam = &gspca_dev->cam;
Hans de Goede49809d62009-06-07 12:10:39 -03002040 switch (sd->bridge) {
Hans de Goede1876bb92009-06-14 06:45:50 -03002041 case BRIDGE_OV511:
2042 case BRIDGE_OV511PLUS:
2043 if (!sd->sif) {
2044 cam->cam_mode = ov511_vga_mode;
2045 cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
2046 } else {
2047 cam->cam_mode = ov511_sif_mode;
2048 cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
2049 }
2050 break;
Hans de Goede49809d62009-06-07 12:10:39 -03002051 case BRIDGE_OV518:
2052 case BRIDGE_OV518PLUS:
2053 if (!sd->sif) {
2054 cam->cam_mode = ov518_vga_mode;
2055 cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
2056 } else {
2057 cam->cam_mode = ov518_sif_mode;
2058 cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
2059 }
2060 break;
2061 case BRIDGE_OV519:
2062 if (!sd->sif) {
2063 cam->cam_mode = ov519_vga_mode;
2064 cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
2065 } else {
2066 cam->cam_mode = ov519_sif_mode;
2067 cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
2068 }
2069 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002070 }
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002071 sd->brightness = BRIGHTNESS_DEF;
Hans de Goedef5cee952009-06-14 06:32:52 -03002072 if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF)
2073 sd->contrast = 200; /* The default is too low for the ov6630 */
2074 else
2075 sd->contrast = CONTRAST_DEF;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002076 sd->colors = COLOR_DEF;
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03002077 sd->hflip = HFLIP_DEF;
2078 sd->vflip = VFLIP_DEF;
Hans de Goede02ab18b2009-06-14 04:32:04 -03002079 sd->autobrightness = AUTOBRIGHT_DEF;
2080 if (sd->sensor == SEN_OV7670) {
2081 sd->freq = OV7670_FREQ_DEF;
2082 gspca_dev->ctrl_dis = 1 << FREQ_IDX;
2083 } else {
2084 sd->freq = FREQ_DEF;
2085 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
2086 (1 << OV7670_FREQ_IDX);
2087 }
2088 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
2089 gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
2090 /* OV8610 Frequency filter control should work but needs testing */
2091 if (sd->sensor == SEN_OV8610)
2092 gspca_dev->ctrl_dis |= 1 << FREQ_IDX;
2093
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002094 return 0;
2095error:
2096 PDEBUG(D_ERR, "OV519 Config failed");
2097 return -EBUSY;
2098}
2099
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002100/* this function is called at probe and resume time */
2101static int sd_init(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002102{
Jean-Francois Moine4202f712008-09-03 17:12:15 -03002103 struct sd *sd = (struct sd *) gspca_dev;
2104
2105 /* initialize the sensor */
2106 switch (sd->sensor) {
2107 case SEN_OV6620:
2108 if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
2109 return -EIO;
2110 break;
2111 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03002112 case SEN_OV66308AF:
Jean-Francois Moine4202f712008-09-03 17:12:15 -03002113 if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
2114 return -EIO;
2115 break;
2116 default:
2117/* case SEN_OV7610: */
2118/* case SEN_OV76BE: */
2119 if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
2120 return -EIO;
2121 break;
2122 case SEN_OV7620:
2123 if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
2124 return -EIO;
2125 break;
2126 case SEN_OV7640:
2127 if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
2128 return -EIO;
2129 break;
2130 case SEN_OV7670:
2131 if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
2132 return -EIO;
2133 break;
2134 case SEN_OV8610:
2135 if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
2136 return -EIO;
2137 break;
2138 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002139 return 0;
2140}
2141
Hans de Goede1876bb92009-06-14 06:45:50 -03002142/* Set up the OV511/OV511+ with the given image parameters.
2143 *
2144 * Do not put any sensor-specific code in here (including I2C I/O functions)
2145 */
2146static int ov511_mode_init_regs(struct sd *sd)
2147{
2148 int hsegs, vsegs, packet_size, fps, needed;
2149 int interlaced = 0;
2150 struct usb_host_interface *alt;
2151 struct usb_interface *intf;
2152
2153 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
2154 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
2155 if (!alt) {
2156 PDEBUG(D_ERR, "Couldn't get altsetting");
2157 return -EIO;
2158 }
2159
2160 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
2161 reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
2162
2163 reg_w(sd, R511_CAM_UV_EN, 0x01);
2164 reg_w(sd, R511_SNAP_UV_EN, 0x01);
2165 reg_w(sd, R511_SNAP_OPTS, 0x03);
2166
2167 /* Here I'm assuming that snapshot size == image size.
2168 * I hope that's always true. --claudio
2169 */
2170 hsegs = (sd->gspca_dev.width >> 3) - 1;
2171 vsegs = (sd->gspca_dev.height >> 3) - 1;
2172
2173 reg_w(sd, R511_CAM_PXCNT, hsegs);
2174 reg_w(sd, R511_CAM_LNCNT, vsegs);
2175 reg_w(sd, R511_CAM_PXDIV, 0x00);
2176 reg_w(sd, R511_CAM_LNDIV, 0x00);
2177
2178 /* YUV420, low pass filter on */
2179 reg_w(sd, R511_CAM_OPTS, 0x03);
2180
2181 /* Snapshot additions */
2182 reg_w(sd, R511_SNAP_PXCNT, hsegs);
2183 reg_w(sd, R511_SNAP_LNCNT, vsegs);
2184 reg_w(sd, R511_SNAP_PXDIV, 0x00);
2185 reg_w(sd, R511_SNAP_LNDIV, 0x00);
2186
2187 /******** Set the framerate ********/
2188 if (frame_rate > 0)
2189 sd->frame_rate = frame_rate;
2190
2191 switch (sd->sensor) {
2192 case SEN_OV6620:
2193 /* No framerate control, doesn't like higher rates yet */
2194 sd->clockdiv = 3;
2195 break;
2196
2197 /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
2198 for more sensors we need to do this for them too */
2199 case SEN_OV7620:
2200 case SEN_OV7640:
2201 if (sd->gspca_dev.width == 320)
2202 interlaced = 1;
2203 /* Fall through */
2204 case SEN_OV6630:
2205 case SEN_OV76BE:
2206 case SEN_OV7610:
2207 case SEN_OV7670:
2208 switch (sd->frame_rate) {
2209 case 30:
2210 case 25:
2211 /* Not enough bandwidth to do 640x480 @ 30 fps */
2212 if (sd->gspca_dev.width != 640) {
2213 sd->clockdiv = 0;
2214 break;
2215 }
2216 /* Fall through for 640x480 case */
2217 default:
2218/* case 20: */
2219/* case 15: */
2220 sd->clockdiv = 1;
2221 break;
2222 case 10:
2223 sd->clockdiv = 2;
2224 break;
2225 case 5:
2226 sd->clockdiv = 5;
2227 break;
2228 }
2229 if (interlaced) {
2230 sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
2231 /* Higher then 10 does not work */
2232 if (sd->clockdiv > 10)
2233 sd->clockdiv = 10;
2234 }
2235 break;
2236
2237 case SEN_OV8610:
2238 /* No framerate control ?? */
2239 sd->clockdiv = 0;
2240 break;
2241 }
2242
2243 /* Check if we have enough bandwidth to disable compression */
2244 fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
2245 needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
2246 /* 1400 is a conservative estimate of the max nr of isoc packets/sec */
2247 if (needed > 1400 * packet_size) {
2248 /* Enable Y and UV quantization and compression */
2249 reg_w(sd, R511_COMP_EN, 0x07);
2250 reg_w(sd, R511_COMP_LUT_EN, 0x03);
2251 } else {
2252 reg_w(sd, R511_COMP_EN, 0x06);
2253 reg_w(sd, R511_COMP_LUT_EN, 0x00);
2254 }
2255
2256 reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
2257 reg_w(sd, R51x_SYS_RESET, 0);
2258
2259 return 0;
2260}
2261
Hans de Goede49809d62009-06-07 12:10:39 -03002262/* Sets up the OV518/OV518+ with the given image parameters
2263 *
2264 * OV518 needs a completely different approach, until we can figure out what
2265 * the individual registers do. Also, only 15 FPS is supported now.
2266 *
2267 * Do not put any sensor-specific code in here (including I2C I/O functions)
2268 */
2269static int ov518_mode_init_regs(struct sd *sd)
2270{
2271 int hsegs, vsegs;
2272
2273 /******** Set the mode ********/
2274
2275 reg_w(sd, 0x2b, 0);
2276 reg_w(sd, 0x2c, 0);
2277 reg_w(sd, 0x2d, 0);
2278 reg_w(sd, 0x2e, 0);
2279 reg_w(sd, 0x3b, 0);
2280 reg_w(sd, 0x3c, 0);
2281 reg_w(sd, 0x3d, 0);
2282 reg_w(sd, 0x3e, 0);
2283
2284 if (sd->bridge == BRIDGE_OV518) {
2285 /* Set 8-bit (YVYU) input format */
2286 reg_w_mask(sd, 0x20, 0x08, 0x08);
2287
2288 /* Set 12-bit (4:2:0) output format */
2289 reg_w_mask(sd, 0x28, 0x80, 0xf0);
2290 reg_w_mask(sd, 0x38, 0x80, 0xf0);
2291 } else {
2292 reg_w(sd, 0x28, 0x80);
2293 reg_w(sd, 0x38, 0x80);
2294 }
2295
2296 hsegs = sd->gspca_dev.width / 16;
2297 vsegs = sd->gspca_dev.height / 4;
2298
2299 reg_w(sd, 0x29, hsegs);
2300 reg_w(sd, 0x2a, vsegs);
2301
2302 reg_w(sd, 0x39, hsegs);
2303 reg_w(sd, 0x3a, vsegs);
2304
2305 /* Windows driver does this here; who knows why */
2306 reg_w(sd, 0x2f, 0x80);
2307
2308 /******** Set the framerate (to 30 FPS) ********/
2309 if (sd->bridge == BRIDGE_OV518PLUS)
2310 sd->clockdiv = 1;
2311 else
2312 sd->clockdiv = 0;
2313
2314 /* Mode independent, but framerate dependent, regs */
2315 reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */
2316 reg_w(sd, 0x22, 0x18);
2317 reg_w(sd, 0x23, 0xff);
2318
2319 if (sd->bridge == BRIDGE_OV518PLUS)
2320 reg_w(sd, 0x21, 0x19);
2321 else
2322 reg_w(sd, 0x71, 0x17); /* Compression-related? */
2323
2324 /* FIXME: Sensor-specific */
2325 /* Bit 5 is what matters here. Of course, it is "reserved" */
2326 i2c_w(sd, 0x54, 0x23);
2327
2328 reg_w(sd, 0x2f, 0x80);
2329
2330 if (sd->bridge == BRIDGE_OV518PLUS) {
2331 reg_w(sd, 0x24, 0x94);
2332 reg_w(sd, 0x25, 0x90);
2333 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
2334 ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */
2335 ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */
2336 ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */
2337 ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */
2338 ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */
2339 ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */
2340 ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */
2341 ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */
2342 } else {
2343 reg_w(sd, 0x24, 0x9f);
2344 reg_w(sd, 0x25, 0x90);
2345 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
2346 ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */
2347 ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */
2348 ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */
2349 ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */
2350 ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */
2351 ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */
2352 ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */
2353 ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */
2354 }
2355
2356 reg_w(sd, 0x2f, 0x80);
2357
2358 return 0;
2359}
2360
2361
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002362/* Sets up the OV519 with the given image parameters
2363 *
2364 * OV519 needs a completely different approach, until we can figure out what
2365 * the individual registers do.
2366 *
2367 * Do not put any sensor-specific code in here (including I2C I/O functions)
2368 */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002369static int ov519_mode_init_regs(struct sd *sd)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002370{
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03002371 static const struct ov_regvals mode_init_519_ov7670[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002372 { 0x5d, 0x03 }, /* Turn off suspend mode */
2373 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
2374 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
2375 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
2376 { 0xa3, 0x18 },
2377 { 0xa4, 0x04 },
2378 { 0xa5, 0x28 },
2379 { 0x37, 0x00 }, /* SetUsbInit */
2380 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
2381 /* Enable both fields, YUV Input, disable defect comp (why?) */
2382 { 0x20, 0x0c },
2383 { 0x21, 0x38 },
2384 { 0x22, 0x1d },
2385 { 0x17, 0x50 }, /* undocumented */
2386 { 0x37, 0x00 }, /* undocumented */
2387 { 0x40, 0xff }, /* I2C timeout counter */
2388 { 0x46, 0x00 }, /* I2C clock prescaler */
2389 { 0x59, 0x04 }, /* new from windrv 090403 */
2390 { 0xff, 0x00 }, /* undocumented */
2391 /* windows reads 0x55 at this point, why? */
2392 };
2393
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03002394 static const struct ov_regvals mode_init_519[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002395 { 0x5d, 0x03 }, /* Turn off suspend mode */
2396 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
2397 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
2398 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
2399 { 0xa3, 0x18 },
2400 { 0xa4, 0x04 },
2401 { 0xa5, 0x28 },
2402 { 0x37, 0x00 }, /* SetUsbInit */
2403 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
2404 /* Enable both fields, YUV Input, disable defect comp (why?) */
2405 { 0x22, 0x1d },
2406 { 0x17, 0x50 }, /* undocumented */
2407 { 0x37, 0x00 }, /* undocumented */
2408 { 0x40, 0xff }, /* I2C timeout counter */
2409 { 0x46, 0x00 }, /* I2C clock prescaler */
2410 { 0x59, 0x04 }, /* new from windrv 090403 */
2411 { 0xff, 0x00 }, /* undocumented */
2412 /* windows reads 0x55 at this point, why? */
2413 };
2414
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002415 /******** Set the mode ********/
2416 if (sd->sensor != SEN_OV7670) {
2417 if (write_regvals(sd, mode_init_519,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03002418 ARRAY_SIZE(mode_init_519)))
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002419 return -EIO;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002420 if (sd->sensor == SEN_OV7640) {
2421 /* Select 8-bit input mode */
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002422 reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002423 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002424 } else {
2425 if (write_regvals(sd, mode_init_519_ov7670,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03002426 ARRAY_SIZE(mode_init_519_ov7670)))
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002427 return -EIO;
2428 }
2429
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002430 reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
2431 reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
Hans de Goede80142ef2009-06-14 06:26:49 -03002432 if (sd->sensor == SEN_OV7670 &&
2433 sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
2434 reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
2435 else
2436 reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002437 reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
2438 reg_w(sd, OV519_R14_Y_OFFSETL, 0x00);
2439 reg_w(sd, OV519_R15_Y_OFFSETH, 0x00);
2440 reg_w(sd, OV519_R16_DIVIDER, 0x00);
2441 reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002442 reg_w(sd, 0x26, 0x00); /* Undocumented */
2443
2444 /******** Set the framerate ********/
2445 if (frame_rate > 0)
2446 sd->frame_rate = frame_rate;
2447
2448/* FIXME: These are only valid at the max resolution. */
2449 sd->clockdiv = 0;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002450 switch (sd->sensor) {
2451 case SEN_OV7640:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002452 switch (sd->frame_rate) {
Jean-Francois Moine53e74512008-11-08 06:10:19 -03002453 default:
2454/* case 30: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002455 reg_w(sd, 0xa4, 0x0c);
2456 reg_w(sd, 0x23, 0xff);
2457 break;
2458 case 25:
2459 reg_w(sd, 0xa4, 0x0c);
2460 reg_w(sd, 0x23, 0x1f);
2461 break;
2462 case 20:
2463 reg_w(sd, 0xa4, 0x0c);
2464 reg_w(sd, 0x23, 0x1b);
2465 break;
Jean-Francois Moine53e74512008-11-08 06:10:19 -03002466 case 15:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002467 reg_w(sd, 0xa4, 0x04);
2468 reg_w(sd, 0x23, 0xff);
2469 sd->clockdiv = 1;
2470 break;
2471 case 10:
2472 reg_w(sd, 0xa4, 0x04);
2473 reg_w(sd, 0x23, 0x1f);
2474 sd->clockdiv = 1;
2475 break;
2476 case 5:
2477 reg_w(sd, 0xa4, 0x04);
2478 reg_w(sd, 0x23, 0x1b);
2479 sd->clockdiv = 1;
2480 break;
2481 }
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002482 break;
2483 case SEN_OV8610:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002484 switch (sd->frame_rate) {
2485 default: /* 15 fps */
2486/* case 15: */
2487 reg_w(sd, 0xa4, 0x06);
2488 reg_w(sd, 0x23, 0xff);
2489 break;
2490 case 10:
2491 reg_w(sd, 0xa4, 0x06);
2492 reg_w(sd, 0x23, 0x1f);
2493 break;
2494 case 5:
2495 reg_w(sd, 0xa4, 0x06);
2496 reg_w(sd, 0x23, 0x1b);
2497 break;
2498 }
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002499 break;
2500 case SEN_OV7670: /* guesses, based on 7640 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002501 PDEBUG(D_STREAM, "Setting framerate to %d fps",
2502 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002503 reg_w(sd, 0xa4, 0x10);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002504 switch (sd->frame_rate) {
2505 case 30:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002506 reg_w(sd, 0x23, 0xff);
2507 break;
2508 case 20:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002509 reg_w(sd, 0x23, 0x1b);
2510 break;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002511 default:
2512/* case 15: */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002513 reg_w(sd, 0x23, 0xff);
2514 sd->clockdiv = 1;
2515 break;
2516 }
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002517 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002518 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002519 return 0;
2520}
2521
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002522static int mode_init_ov_sensor_regs(struct sd *sd)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002523{
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002524 struct gspca_dev *gspca_dev;
2525 int qvga;
2526
2527 gspca_dev = &sd->gspca_dev;
Hans de Goede124cc9c2009-06-14 05:48:00 -03002528 qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002529
2530 /******** Mode (VGA/QVGA) and sensor specific regs ********/
2531 switch (sd->sensor) {
2532 case SEN_OV8610:
2533 /* For OV8610 qvga means qsvga */
2534 i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
2535 break;
2536 case SEN_OV7610:
2537 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
2538 break;
2539 case SEN_OV7620:
2540/* i2c_w(sd, 0x2b, 0x00); */
2541 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
2542 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
2543 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
2544 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
2545 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
2546 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
2547 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
2548 break;
2549 case SEN_OV76BE:
2550/* i2c_w(sd, 0x2b, 0x00); */
2551 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
2552 break;
2553 case SEN_OV7640:
2554/* i2c_w(sd, 0x2b, 0x00); */
2555 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
2556 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
2557/* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
2558/* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */
2559/* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */
2560/* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */
2561/* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */
2562 break;
2563 case SEN_OV7670:
2564 /* set COM7_FMT_VGA or COM7_FMT_QVGA
2565 * do we need to set anything else?
2566 * HSTART etc are set in set_ov_sensor_window itself */
2567 i2c_w_mask(sd, OV7670_REG_COM7,
2568 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
2569 OV7670_COM7_FMT_MASK);
2570 break;
2571 case SEN_OV6620:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002572 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03002573 case SEN_OV66308AF:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002574 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
2575 break;
2576 default:
2577 return -EINVAL;
2578 }
2579
2580 /******** Palette-specific regs ********/
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002581 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
2582 /* not valid on the OV6620/OV7620/6630? */
2583 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
2584 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002585
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002586 /* The OV518 needs special treatment. Although both the OV518
2587 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
2588 * bus is actually used. The UV bus is tied to ground.
2589 * Therefore, the OV6630 needs to be in 8-bit multiplexed
2590 * output mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002591
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002592 /* OV7640 is 8-bit only */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002593
Hans de Goede7d971372009-06-14 05:28:17 -03002594 if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF &&
2595 sd->sensor != SEN_OV7640)
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002596 i2c_w_mask(sd, 0x13, 0x00, 0x20);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002597
2598 /******** Clock programming ********/
2599 /* The OV6620 needs special handling. This prevents the
2600 * severe banding that normally occurs */
2601 if (sd->sensor == SEN_OV6620) {
2602
2603 /* Clock down */
2604 i2c_w(sd, 0x2a, 0x04);
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002605 i2c_w(sd, 0x11, sd->clockdiv);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002606 i2c_w(sd, 0x2a, 0x84);
2607 /* This next setting is critical. It seems to improve
2608 * the gain or the contrast. The "reserved" bits seem
2609 * to have some effect in this case. */
2610 i2c_w(sd, 0x2d, 0x85);
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002611 } else {
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002612 i2c_w(sd, 0x11, sd->clockdiv);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002613 }
2614
2615 /******** Special Features ********/
2616/* no evidence this is possible with OV7670, either */
2617 /* Test Pattern */
2618 if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670)
2619 i2c_w_mask(sd, 0x12, 0x00, 0x02);
2620
2621 /* Enable auto white balance */
2622 if (sd->sensor == SEN_OV7670)
2623 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,
2624 OV7670_COM8_AWB);
2625 else
2626 i2c_w_mask(sd, 0x12, 0x04, 0x04);
2627
2628 /* This will go away as soon as ov51x_mode_init_sensor_regs() */
2629 /* is fully tested. */
2630 /* 7620/6620/6630? don't have register 0x35, so play it safe */
2631 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002632 if (!qvga)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002633 i2c_w(sd, 0x35, 0x9e);
2634 else
2635 i2c_w(sd, 0x35, 0x1e);
2636 }
2637 return 0;
2638}
2639
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002640static void sethvflip(struct sd *sd)
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03002641{
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002642 if (sd->sensor != SEN_OV7670)
2643 return;
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03002644 if (sd->gspca_dev.streaming)
2645 ov51x_stop(sd);
2646 i2c_w_mask(sd, OV7670_REG_MVFP,
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002647 OV7670_MVFP_MIRROR * sd->hflip
2648 | OV7670_MVFP_VFLIP * sd->vflip,
2649 OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03002650 if (sd->gspca_dev.streaming)
2651 ov51x_restart(sd);
2652}
2653
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002654static int set_ov_sensor_window(struct sd *sd)
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03002655{
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002656 struct gspca_dev *gspca_dev;
Hans de Goede124cc9c2009-06-14 05:48:00 -03002657 int qvga, crop;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002658 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
2659 int ret, hstart, hstop, vstop, vstart;
2660 __u8 v;
2661
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002662 gspca_dev = &sd->gspca_dev;
Hans de Goede124cc9c2009-06-14 05:48:00 -03002663 qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
2664 crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2;
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002665
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002666 /* The different sensor ICs handle setting up of window differently.
2667 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
2668 switch (sd->sensor) {
2669 case SEN_OV8610:
2670 hwsbase = 0x1e;
2671 hwebase = 0x1e;
2672 vwsbase = 0x02;
2673 vwebase = 0x02;
2674 break;
2675 case SEN_OV7610:
2676 case SEN_OV76BE:
2677 hwsbase = 0x38;
2678 hwebase = 0x3a;
2679 vwsbase = vwebase = 0x05;
2680 break;
2681 case SEN_OV6620:
2682 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03002683 case SEN_OV66308AF:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002684 hwsbase = 0x38;
2685 hwebase = 0x3a;
2686 vwsbase = 0x05;
2687 vwebase = 0x06;
Hans de Goede7d971372009-06-14 05:28:17 -03002688 if (sd->sensor == SEN_OV66308AF && qvga)
Hans de Goede49809d62009-06-07 12:10:39 -03002689 /* HDG: this fixes U and V getting swapped */
Hans de Goede7d971372009-06-14 05:28:17 -03002690 hwsbase++;
Hans de Goede124cc9c2009-06-14 05:48:00 -03002691 if (crop) {
2692 hwsbase += 8;
2693 hwebase += 8;
2694 vwsbase += 11;
2695 vwebase += 11;
2696 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002697 break;
2698 case SEN_OV7620:
2699 hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
2700 hwebase = 0x2f;
2701 vwsbase = vwebase = 0x05;
2702 break;
2703 case SEN_OV7640:
2704 hwsbase = 0x1a;
2705 hwebase = 0x1a;
2706 vwsbase = vwebase = 0x03;
2707 break;
2708 case SEN_OV7670:
2709 /*handling of OV7670 hardware sensor start and stop values
2710 * is very odd, compared to the other OV sensors */
2711 vwsbase = vwebase = hwebase = hwsbase = 0x00;
2712 break;
2713 default:
2714 return -EINVAL;
2715 }
2716
2717 switch (sd->sensor) {
2718 case SEN_OV6620:
2719 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03002720 case SEN_OV66308AF:
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002721 if (qvga) { /* QCIF */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002722 hwscale = 0;
2723 vwscale = 0;
2724 } else { /* CIF */
2725 hwscale = 1;
2726 vwscale = 1; /* The datasheet says 0;
2727 * it's wrong */
2728 }
2729 break;
2730 case SEN_OV8610:
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002731 if (qvga) { /* QSVGA */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002732 hwscale = 1;
2733 vwscale = 1;
2734 } else { /* SVGA */
2735 hwscale = 2;
2736 vwscale = 2;
2737 }
2738 break;
2739 default: /* SEN_OV7xx0 */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002740 if (qvga) { /* QVGA */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002741 hwscale = 1;
2742 vwscale = 0;
2743 } else { /* VGA */
2744 hwscale = 2;
2745 vwscale = 1;
2746 }
2747 }
2748
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002749 ret = mode_init_ov_sensor_regs(sd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002750 if (ret < 0)
2751 return ret;
2752
2753 if (sd->sensor == SEN_OV8610) {
2754 i2c_w_mask(sd, 0x2d, 0x05, 0x40);
2755 /* old 0x95, new 0x05 from windrv 090403 */
2756 /* bits 5-7: reserved */
2757 i2c_w_mask(sd, 0x28, 0x20, 0x20);
2758 /* bit 5: progressive mode on */
2759 }
2760
2761 /* The below is wrong for OV7670s because their window registers
2762 * only store the high bits in 0x17 to 0x1a */
2763
2764 /* SRH Use sd->max values instead of requested win values */
2765 /* SCS Since we're sticking with only the max hardware widths
2766 * for a given mode */
2767 /* I can hard code this for OV7670s */
2768 /* Yes, these numbers do look odd, but they're tested and work! */
2769 if (sd->sensor == SEN_OV7670) {
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002770 if (qvga) { /* QVGA from ov7670.c by
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002771 * Jonathan Corbet */
2772 hstart = 164;
Hans de Goede80142ef2009-06-14 06:26:49 -03002773 hstop = 28;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002774 vstart = 14;
2775 vstop = 494;
2776 } else { /* VGA */
2777 hstart = 158;
2778 hstop = 14;
2779 vstart = 10;
2780 vstop = 490;
2781 }
2782 /* OV7670 hardware window registers are split across
2783 * multiple locations */
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002784 i2c_w(sd, OV7670_REG_HSTART, hstart >> 3);
2785 i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002786 v = i2c_r(sd, OV7670_REG_HREF);
2787 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);
2788 msleep(10); /* need to sleep between read and write to
2789 * same reg! */
2790 i2c_w(sd, OV7670_REG_HREF, v);
2791
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002792 i2c_w(sd, OV7670_REG_VSTART, vstart >> 2);
2793 i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002794 v = i2c_r(sd, OV7670_REG_VREF);
2795 v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);
2796 msleep(10); /* need to sleep between read and write to
2797 * same reg! */
2798 i2c_w(sd, OV7670_REG_VREF, v);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002799 } else {
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002800 i2c_w(sd, 0x17, hwsbase);
2801 i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
2802 i2c_w(sd, 0x19, vwsbase);
2803 i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002804 }
2805 return 0;
2806}
2807
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002808/* -- start the camera -- */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03002809static int sd_start(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002810{
2811 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede49809d62009-06-07 12:10:39 -03002812 int ret = 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002813
Hans de Goede49809d62009-06-07 12:10:39 -03002814 switch (sd->bridge) {
Hans de Goede1876bb92009-06-14 06:45:50 -03002815 case BRIDGE_OV511:
2816 case BRIDGE_OV511PLUS:
2817 ret = ov511_mode_init_regs(sd);
2818 break;
Hans de Goede49809d62009-06-07 12:10:39 -03002819 case BRIDGE_OV518:
2820 case BRIDGE_OV518PLUS:
2821 ret = ov518_mode_init_regs(sd);
2822 break;
2823 case BRIDGE_OV519:
2824 ret = ov519_mode_init_regs(sd);
2825 break;
2826 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002827 if (ret < 0)
2828 goto out;
Hans de Goede49809d62009-06-07 12:10:39 -03002829
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002830 ret = set_ov_sensor_window(sd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002831 if (ret < 0)
2832 goto out;
2833
Hans de Goede49809d62009-06-07 12:10:39 -03002834 setcontrast(gspca_dev);
2835 setbrightness(gspca_dev);
2836 setcolors(gspca_dev);
Hans de Goede02ab18b2009-06-14 04:32:04 -03002837 sethvflip(sd);
2838 setautobrightness(sd);
2839 setfreq(sd);
Hans de Goede49809d62009-06-07 12:10:39 -03002840
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03002841 ret = ov51x_restart(sd);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002842 if (ret < 0)
2843 goto out;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002844 ov51x_led_control(sd, 1);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03002845 return 0;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002846out:
2847 PDEBUG(D_ERR, "camera start error:%d", ret);
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -03002848 return ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002849}
2850
2851static void sd_stopN(struct gspca_dev *gspca_dev)
2852{
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03002853 struct sd *sd = (struct sd *) gspca_dev;
2854
2855 ov51x_stop(sd);
2856 ov51x_led_control(sd, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002857}
2858
Hans de Goede1876bb92009-06-14 06:45:50 -03002859static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
2860 struct gspca_frame *frame, /* target */
2861 __u8 *in, /* isoc packet */
2862 int len) /* iso packet length */
2863{
2864 struct sd *sd = (struct sd *) gspca_dev;
2865
2866 /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
2867 * byte non-zero. The EOF packet has image width/height in the
2868 * 10th and 11th bytes. The 9th byte is given as follows:
2869 *
2870 * bit 7: EOF
2871 * 6: compression enabled
2872 * 5: 422/420/400 modes
2873 * 4: 422/420/400 modes
2874 * 3: 1
2875 * 2: snapshot button on
2876 * 1: snapshot frame
2877 * 0: even/odd field
2878 */
2879 if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
2880 (in[8] & 0x08)) {
2881 if (in[8] & 0x80) {
2882 /* Frame end */
2883 if ((in[9] + 1) * 8 != gspca_dev->width ||
2884 (in[10] + 1) * 8 != gspca_dev->height) {
2885 PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
2886 " requested: %dx%d\n",
2887 (in[9] + 1) * 8, (in[10] + 1) * 8,
2888 gspca_dev->width, gspca_dev->height);
2889 gspca_dev->last_packet_type = DISCARD_PACKET;
2890 return;
2891 }
2892 /* Add 11 byte footer to frame, might be usefull */
2893 gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11);
2894 return;
2895 } else {
2896 /* Frame start */
2897 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0);
2898 sd->packet_nr = 0;
2899 }
2900 }
2901
2902 /* Ignore the packet number */
2903 len--;
2904
2905 /* intermediate packet */
2906 gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len);
2907}
2908
Hans de Goede49809d62009-06-07 12:10:39 -03002909static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
2910 struct gspca_frame *frame, /* target */
2911 __u8 *data, /* isoc packet */
2912 int len) /* iso packet length */
2913{
Hans de Goede92918a52009-06-14 06:21:35 -03002914 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede49809d62009-06-07 12:10:39 -03002915
2916 /* A false positive here is likely, until OVT gives me
2917 * the definitive SOF/EOF format */
2918 if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
2919 gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0);
2920 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0);
Hans de Goede92918a52009-06-14 06:21:35 -03002921 sd->packet_nr = 0;
2922 }
2923
2924 if (gspca_dev->last_packet_type == DISCARD_PACKET)
2925 return;
2926
2927 /* Does this device use packet numbers ? */
2928 if (len & 7) {
2929 len--;
2930 if (sd->packet_nr == data[len])
2931 sd->packet_nr++;
2932 /* The last few packets of the frame (which are all 0's
2933 except that they may contain part of the footer), are
2934 numbered 0 */
2935 else if (sd->packet_nr == 0 || data[len]) {
2936 PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
2937 (int)data[len], (int)sd->packet_nr);
2938 gspca_dev->last_packet_type = DISCARD_PACKET;
2939 return;
2940 }
Hans de Goede49809d62009-06-07 12:10:39 -03002941 }
2942
2943 /* intermediate packet */
2944 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
2945}
2946
2947static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002948 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03002949 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002950 int len) /* iso packet length */
2951{
2952 /* Header of ov519 is 16 bytes:
2953 * Byte Value Description
2954 * 0 0xff magic
2955 * 1 0xff magic
2956 * 2 0xff magic
2957 * 3 0xXX 0x50 = SOF, 0x51 = EOF
2958 * 9 0xXX 0x01 initial frame without data,
2959 * 0x00 standard frame with image
2960 * 14 Lo in EOF: length of image data / 8
2961 * 15 Hi
2962 */
2963
2964 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
2965 switch (data[3]) {
2966 case 0x50: /* start of frame */
2967#define HDRSZ 16
2968 data += HDRSZ;
2969 len -= HDRSZ;
2970#undef HDRSZ
2971 if (data[0] == 0xff || data[1] == 0xd8)
2972 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2973 data, len);
2974 else
2975 gspca_dev->last_packet_type = DISCARD_PACKET;
2976 return;
2977 case 0x51: /* end of frame */
2978 if (data[9] != 0)
2979 gspca_dev->last_packet_type = DISCARD_PACKET;
2980 gspca_frame_add(gspca_dev, LAST_PACKET, frame,
2981 data, 0);
2982 return;
2983 }
2984 }
2985
2986 /* intermediate packet */
2987 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
2988 data, len);
2989}
2990
Hans de Goede49809d62009-06-07 12:10:39 -03002991static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2992 struct gspca_frame *frame, /* target */
2993 __u8 *data, /* isoc packet */
2994 int len) /* iso packet length */
2995{
2996 struct sd *sd = (struct sd *) gspca_dev;
2997
2998 switch (sd->bridge) {
2999 case BRIDGE_OV511:
3000 case BRIDGE_OV511PLUS:
Hans de Goede1876bb92009-06-14 06:45:50 -03003001 ov511_pkt_scan(gspca_dev, frame, data, len);
Hans de Goede49809d62009-06-07 12:10:39 -03003002 break;
3003 case BRIDGE_OV518:
3004 case BRIDGE_OV518PLUS:
3005 ov518_pkt_scan(gspca_dev, frame, data, len);
3006 break;
3007 case BRIDGE_OV519:
3008 ov519_pkt_scan(gspca_dev, frame, data, len);
3009 break;
3010 }
3011}
3012
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003013/* -- management routines -- */
3014
3015static void setbrightness(struct gspca_dev *gspca_dev)
3016{
3017 struct sd *sd = (struct sd *) gspca_dev;
3018 int val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003019
3020 val = sd->brightness;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003021 switch (sd->sensor) {
3022 case SEN_OV8610:
3023 case SEN_OV7610:
3024 case SEN_OV76BE:
3025 case SEN_OV6620:
3026 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03003027 case SEN_OV66308AF:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003028 case SEN_OV7640:
3029 i2c_w(sd, OV7610_REG_BRT, val);
3030 break;
3031 case SEN_OV7620:
3032 /* 7620 doesn't like manual changes when in auto mode */
Hans de Goede02ab18b2009-06-14 04:32:04 -03003033 if (!sd->autobrightness)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003034 i2c_w(sd, OV7610_REG_BRT, val);
3035 break;
3036 case SEN_OV7670:
Jean-Francois Moine594f5b82008-08-01 06:37:51 -03003037/*win trace
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003038 * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
3039 i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
3040 break;
3041 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003042}
3043
3044static void setcontrast(struct gspca_dev *gspca_dev)
3045{
3046 struct sd *sd = (struct sd *) gspca_dev;
3047 int val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003048
3049 val = sd->contrast;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003050 switch (sd->sensor) {
3051 case SEN_OV7610:
3052 case SEN_OV6620:
3053 i2c_w(sd, OV7610_REG_CNT, val);
3054 break;
3055 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03003056 case SEN_OV66308AF:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003057 i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
Hans de Goede49809d62009-06-07 12:10:39 -03003058 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003059 case SEN_OV8610: {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03003060 static const __u8 ctab[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003061 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
3062 };
3063
3064 /* Use Y gamma control instead. Bit 0 enables it. */
3065 i2c_w(sd, 0x64, ctab[val >> 5]);
3066 break;
3067 }
3068 case SEN_OV7620: {
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03003069 static const __u8 ctab[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003070 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
3071 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
3072 };
3073
3074 /* Use Y gamma control instead. Bit 0 enables it. */
3075 i2c_w(sd, 0x64, ctab[val >> 4]);
3076 break;
3077 }
3078 case SEN_OV7640:
3079 /* Use gain control instead. */
3080 i2c_w(sd, OV7610_REG_GAIN, val >> 2);
3081 break;
3082 case SEN_OV7670:
3083 /* check that this isn't just the same as ov7610 */
3084 i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
3085 break;
3086 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003087}
3088
3089static void setcolors(struct gspca_dev *gspca_dev)
3090{
3091 struct sd *sd = (struct sd *) gspca_dev;
3092 int val;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003093
3094 val = sd->colors;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003095 switch (sd->sensor) {
3096 case SEN_OV8610:
3097 case SEN_OV7610:
3098 case SEN_OV76BE:
3099 case SEN_OV6620:
3100 case SEN_OV6630:
Hans de Goede7d971372009-06-14 05:28:17 -03003101 case SEN_OV66308AF:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003102 i2c_w(sd, OV7610_REG_SAT, val);
3103 break;
3104 case SEN_OV7620:
3105 /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
3106/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
3107 if (rc < 0)
3108 goto out; */
3109 i2c_w(sd, OV7610_REG_SAT, val);
3110 break;
3111 case SEN_OV7640:
3112 i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
3113 break;
3114 case SEN_OV7670:
3115 /* supported later once I work out how to do it
3116 * transparently fail now! */
3117 /* set REG_COM13 values for UV sat auto mode */
3118 break;
3119 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003120}
3121
Hans de Goede02ab18b2009-06-14 04:32:04 -03003122static void setautobrightness(struct sd *sd)
3123{
3124 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
3125 return;
3126
3127 i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10);
3128}
3129
3130static void setfreq(struct sd *sd)
3131{
3132 if (sd->sensor == SEN_OV7670) {
3133 switch (sd->freq) {
3134 case 0: /* Banding filter disabled */
3135 i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
3136 break;
3137 case 1: /* 50 hz */
3138 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
3139 OV7670_COM8_BFILT);
3140 i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
3141 break;
3142 case 2: /* 60 hz */
3143 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
3144 OV7670_COM8_BFILT);
3145 i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
3146 break;
3147 case 3: /* Auto hz */
3148 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
3149 OV7670_COM8_BFILT);
3150 i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
3151 0x18);
3152 break;
3153 }
3154 } else {
3155 switch (sd->freq) {
3156 case 0: /* Banding filter disabled */
3157 i2c_w_mask(sd, 0x2d, 0x00, 0x04);
3158 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
3159 break;
3160 case 1: /* 50 hz (filter on and framerate adj) */
3161 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
3162 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
3163 /* 20 fps -> 16.667 fps */
3164 if (sd->sensor == SEN_OV6620 ||
Hans de Goede7d971372009-06-14 05:28:17 -03003165 sd->sensor == SEN_OV6630 ||
3166 sd->sensor == SEN_OV66308AF)
Hans de Goede02ab18b2009-06-14 04:32:04 -03003167 i2c_w(sd, 0x2b, 0x5e);
3168 else
3169 i2c_w(sd, 0x2b, 0xac);
3170 break;
3171 case 2: /* 60 hz (filter on, ...) */
3172 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
3173 if (sd->sensor == SEN_OV6620 ||
Hans de Goede7d971372009-06-14 05:28:17 -03003174 sd->sensor == SEN_OV6630 ||
3175 sd->sensor == SEN_OV66308AF) {
Hans de Goede02ab18b2009-06-14 04:32:04 -03003176 /* 20 fps -> 15 fps */
3177 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
3178 i2c_w(sd, 0x2b, 0xa8);
3179 } else {
3180 /* no framerate adj. */
3181 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
3182 }
3183 break;
3184 }
3185 }
3186}
3187
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003188static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
3189{
3190 struct sd *sd = (struct sd *) gspca_dev;
3191
3192 sd->brightness = val;
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003193 if (gspca_dev->streaming)
3194 setbrightness(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003195 return 0;
3196}
3197
3198static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
3199{
3200 struct sd *sd = (struct sd *) gspca_dev;
3201
3202 *val = sd->brightness;
3203 return 0;
3204}
3205
3206static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
3207{
3208 struct sd *sd = (struct sd *) gspca_dev;
3209
3210 sd->contrast = val;
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003211 if (gspca_dev->streaming)
3212 setcontrast(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003213 return 0;
3214}
3215
3216static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
3217{
3218 struct sd *sd = (struct sd *) gspca_dev;
3219
3220 *val = sd->contrast;
3221 return 0;
3222}
3223
3224static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
3225{
3226 struct sd *sd = (struct sd *) gspca_dev;
3227
3228 sd->colors = val;
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003229 if (gspca_dev->streaming)
3230 setcolors(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003231 return 0;
3232}
3233
3234static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
3235{
3236 struct sd *sd = (struct sd *) gspca_dev;
3237
3238 *val = sd->colors;
3239 return 0;
3240}
3241
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03003242static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
3243{
3244 struct sd *sd = (struct sd *) gspca_dev;
3245
3246 sd->hflip = val;
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003247 if (gspca_dev->streaming)
3248 sethvflip(sd);
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03003249 return 0;
3250}
3251
3252static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
3253{
3254 struct sd *sd = (struct sd *) gspca_dev;
3255
3256 *val = sd->hflip;
3257 return 0;
3258}
3259
3260static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
3261{
3262 struct sd *sd = (struct sd *) gspca_dev;
3263
3264 sd->vflip = val;
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003265 if (gspca_dev->streaming)
3266 sethvflip(sd);
Jean-Francois Moine0cd67592008-07-29 05:25:28 -03003267 return 0;
3268}
3269
3270static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
3271{
3272 struct sd *sd = (struct sd *) gspca_dev;
3273
3274 *val = sd->vflip;
3275 return 0;
3276}
3277
Hans de Goede02ab18b2009-06-14 04:32:04 -03003278static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val)
3279{
3280 struct sd *sd = (struct sd *) gspca_dev;
3281
3282 sd->autobrightness = val;
3283 if (gspca_dev->streaming)
3284 setautobrightness(sd);
3285 return 0;
3286}
3287
3288static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val)
3289{
3290 struct sd *sd = (struct sd *) gspca_dev;
3291
3292 *val = sd->autobrightness;
3293 return 0;
3294}
3295
3296static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
3297{
3298 struct sd *sd = (struct sd *) gspca_dev;
3299
3300 sd->freq = val;
3301 if (gspca_dev->streaming)
3302 setfreq(sd);
3303 return 0;
3304}
3305
3306static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
3307{
3308 struct sd *sd = (struct sd *) gspca_dev;
3309
3310 *val = sd->freq;
3311 return 0;
3312}
3313
3314static int sd_querymenu(struct gspca_dev *gspca_dev,
3315 struct v4l2_querymenu *menu)
3316{
3317 struct sd *sd = (struct sd *) gspca_dev;
3318
3319 switch (menu->id) {
3320 case V4L2_CID_POWER_LINE_FREQUENCY:
3321 switch (menu->index) {
3322 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
3323 strcpy((char *) menu->name, "NoFliker");
3324 return 0;
3325 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
3326 strcpy((char *) menu->name, "50 Hz");
3327 return 0;
3328 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
3329 strcpy((char *) menu->name, "60 Hz");
3330 return 0;
3331 case 3:
3332 if (sd->sensor != SEN_OV7670)
3333 return -EINVAL;
3334
3335 strcpy((char *) menu->name, "Automatic");
3336 return 0;
3337 }
3338 break;
3339 }
3340 return -EINVAL;
3341}
3342
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003343/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03003344static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003345 .name = MODULE_NAME,
3346 .ctrls = sd_ctrls,
3347 .nctrls = ARRAY_SIZE(sd_ctrls),
3348 .config = sd_config,
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03003349 .init = sd_init,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003350 .start = sd_start,
3351 .stopN = sd_stopN,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003352 .pkt_scan = sd_pkt_scan,
Hans de Goede02ab18b2009-06-14 04:32:04 -03003353 .querymenu = sd_querymenu,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003354};
3355
3356/* -- module initialisation -- */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03003357static const __devinitdata struct usb_device_id device_table[] = {
Hans de Goede49809d62009-06-07 12:10:39 -03003358 {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
3359 {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
3360 {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
3361 {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
Hans de Goede9e4d8252009-06-14 06:25:06 -03003362 {USB_DEVICE(0x041e, 0x4064),
3363 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
3364 {USB_DEVICE(0x041e, 0x4068),
3365 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
Hans de Goede49809d62009-06-07 12:10:39 -03003366 {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
3367 {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
3368 {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
Hans de Goede1876bb92009-06-14 06:45:50 -03003369 {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
Hans de Goede49809d62009-06-07 12:10:39 -03003370 {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
3371 {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
3372 {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
3373 {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
3374 {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
Hans de Goede1876bb92009-06-14 06:45:50 -03003375 {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
Hans de Goede49809d62009-06-07 12:10:39 -03003376 {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
Hans de Goede1876bb92009-06-14 06:45:50 -03003377 {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003378 {}
3379};
Jean-Francois Moineac40b1f2008-11-08 06:03:37 -03003380
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003381MODULE_DEVICE_TABLE(usb, device_table);
3382
3383/* -- device connect -- */
3384static int sd_probe(struct usb_interface *intf,
3385 const struct usb_device_id *id)
3386{
3387 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
3388 THIS_MODULE);
3389}
3390
3391static struct usb_driver sd_driver = {
3392 .name = MODULE_NAME,
3393 .id_table = device_table,
3394 .probe = sd_probe,
3395 .disconnect = gspca_disconnect,
Jean-Francois Moine6a709742008-09-03 16:48:10 -03003396#ifdef CONFIG_PM
3397 .suspend = gspca_suspend,
3398 .resume = gspca_resume,
3399#endif
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003400};
3401
3402/* -- module insert / remove -- */
3403static int __init sd_mod_init(void)
3404{
Alexey Klimovf69e9522009-01-01 13:02:07 -03003405 int ret;
3406 ret = usb_register(&sd_driver);
3407 if (ret < 0)
Alexey Klimove6b14842009-01-01 13:04:58 -03003408 return ret;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03003409 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03003410 return 0;
3411}
3412static void __exit sd_mod_exit(void)
3413{
3414 usb_deregister(&sd_driver);
3415 PDEBUG(D_PROBE, "deregistered");
3416}
3417
3418module_init(sd_mod_init);
3419module_exit(sd_mod_exit);
3420
3421module_param(frame_rate, int, 0644);
3422MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");