blob: c431900cd292a11f690808e2718c953dff6324e2 [file] [log] [blame]
Brian Johnson26e744b2009-07-19 05:52:58 -03001/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Brian Johnson26e744b2009-07-19 05:52:58 -030021#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030022
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030023#include "gspca.h"
24#include "jpeg.h"
25
26#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030027#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030028
Brian Johnson26e744b2009-07-19 05:52:58 -030029MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
30 "microdia project <microdia@googlegroups.com>");
31MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34#define MODULE_NAME "sn9c20x"
35
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -030036/*
37 * Pixel format private data
38 */
39#define SCALE_MASK 0x0f
40#define SCALE_160x120 0
41#define SCALE_320x240 1
42#define SCALE_640x480 2
43#define SCALE_1280x1024 3
Brian Johnson26e744b2009-07-19 05:52:58 -030044#define MODE_RAW 0x10
45#define MODE_JPEG 0x20
46#define MODE_SXGA 0x80
47
48#define SENSOR_OV9650 0
49#define SENSOR_OV9655 1
50#define SENSOR_SOI968 2
51#define SENSOR_OV7660 3
52#define SENSOR_OV7670 4
53#define SENSOR_MT9V011 5
54#define SENSOR_MT9V111 6
55#define SENSOR_MT9V112 7
56#define SENSOR_MT9M001 8
57#define SENSOR_MT9M111 9
Brian Johnsone99ac542010-03-16 13:58:28 -030058#define SENSOR_MT9M112 10
59#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030060#define SENSOR_MT9VPRB 20
61
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030062/* camera flags */
Brian Johnson33ddc162010-04-18 21:42:40 -030063#define HAS_NO_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030064#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030065#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030066
Brian Johnson26e744b2009-07-19 05:52:58 -030067/* specific webcam descriptor */
68struct sd {
69 struct gspca_dev gspca_dev;
70
71#define MIN_AVG_LUM 80
72#define MAX_AVG_LUM 130
73 atomic_t avg_lum;
74 u8 old_step;
75 u8 older_step;
76 u8 exposure_step;
77
78 u8 brightness;
79 u8 contrast;
80 u8 saturation;
81 s16 hue;
82 u8 gamma;
83 u8 red;
84 u8 blue;
85
86 u8 hflip;
87 u8 vflip;
88 u8 gain;
89 u16 exposure;
90 u8 auto_exposure;
91
92 u8 i2c_addr;
93 u8 sensor;
94 u8 hstart;
95 u8 vstart;
96
Jean-François Moine9a731a32010-06-04 05:26:42 -030097 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -030098 u8 quality;
99
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300100 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300101};
102
Joe Perches58aa68c2009-09-02 01:12:13 -0300103struct i2c_reg_u8 {
104 u8 reg;
105 u8 val;
106};
107
108struct i2c_reg_u16 {
109 u8 reg;
110 u16 val;
111};
112
Brian Johnson26e744b2009-07-19 05:52:58 -0300113static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
114static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
115static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
116static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
117static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
118static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
119static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
120static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
121static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
122static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
123static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
124static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
125static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
126static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
127static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
128static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
129static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
130static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
131static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
132static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
133static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
134static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
135static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
136static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
137
Brian Johnson7ddaac72010-03-16 13:58:27 -0300138static const struct dmi_system_id flip_dmi_table[] = {
139 {
140 .ident = "MSI MS-1034",
141 .matches = {
142 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
143 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
144 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
145 }
146 },
147 {
148 .ident = "MSI MS-1632",
149 .matches = {
150 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
151 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
152 }
153 },
Brian Johnsone077f862010-04-05 20:52:52 -0300154 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300155 .ident = "MSI MS-1633X",
156 .matches = {
157 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
158 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
159 }
160 },
161 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300162 .ident = "MSI MS-1635X",
163 .matches = {
164 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
165 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
166 }
167 },
168 {
Brian Johnsone077f862010-04-05 20:52:52 -0300169 .ident = "ASUSTeK W7J",
170 .matches = {
171 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
172 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
173 }
174 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300175 {}
176};
177
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300178static const struct ctrl sd_ctrls[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300179 {
180#define BRIGHTNESS_IDX 0
181 {
182 .id = V4L2_CID_BRIGHTNESS,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "Brightness",
185 .minimum = 0,
186 .maximum = 0xff,
187 .step = 1,
188#define BRIGHTNESS_DEFAULT 0x7f
189 .default_value = BRIGHTNESS_DEFAULT,
190 },
191 .set = sd_setbrightness,
192 .get = sd_getbrightness,
193 },
194 {
195#define CONTRAST_IDX 1
196 {
197 .id = V4L2_CID_CONTRAST,
198 .type = V4L2_CTRL_TYPE_INTEGER,
199 .name = "Contrast",
200 .minimum = 0,
201 .maximum = 0xff,
202 .step = 1,
203#define CONTRAST_DEFAULT 0x7f
204 .default_value = CONTRAST_DEFAULT,
205 },
206 .set = sd_setcontrast,
207 .get = sd_getcontrast,
208 },
209 {
210#define SATURATION_IDX 2
211 {
212 .id = V4L2_CID_SATURATION,
213 .type = V4L2_CTRL_TYPE_INTEGER,
214 .name = "Saturation",
215 .minimum = 0,
216 .maximum = 0xff,
217 .step = 1,
218#define SATURATION_DEFAULT 0x7f
219 .default_value = SATURATION_DEFAULT,
220 },
221 .set = sd_setsaturation,
222 .get = sd_getsaturation,
223 },
224 {
225#define HUE_IDX 3
226 {
227 .id = V4L2_CID_HUE,
228 .type = V4L2_CTRL_TYPE_INTEGER,
229 .name = "Hue",
230 .minimum = -180,
231 .maximum = 180,
232 .step = 1,
233#define HUE_DEFAULT 0
234 .default_value = HUE_DEFAULT,
235 },
236 .set = sd_sethue,
237 .get = sd_gethue,
238 },
239 {
240#define GAMMA_IDX 4
241 {
242 .id = V4L2_CID_GAMMA,
243 .type = V4L2_CTRL_TYPE_INTEGER,
244 .name = "Gamma",
245 .minimum = 0,
246 .maximum = 0xff,
247 .step = 1,
248#define GAMMA_DEFAULT 0x10
249 .default_value = GAMMA_DEFAULT,
250 },
251 .set = sd_setgamma,
252 .get = sd_getgamma,
253 },
254 {
255#define BLUE_IDX 5
256 {
257 .id = V4L2_CID_BLUE_BALANCE,
258 .type = V4L2_CTRL_TYPE_INTEGER,
259 .name = "Blue Balance",
260 .minimum = 0,
261 .maximum = 0x7f,
262 .step = 1,
263#define BLUE_DEFAULT 0x28
264 .default_value = BLUE_DEFAULT,
265 },
266 .set = sd_setbluebalance,
267 .get = sd_getbluebalance,
268 },
269 {
270#define RED_IDX 6
271 {
272 .id = V4L2_CID_RED_BALANCE,
273 .type = V4L2_CTRL_TYPE_INTEGER,
274 .name = "Red Balance",
275 .minimum = 0,
276 .maximum = 0x7f,
277 .step = 1,
278#define RED_DEFAULT 0x28
279 .default_value = RED_DEFAULT,
280 },
281 .set = sd_setredbalance,
282 .get = sd_getredbalance,
283 },
284 {
285#define HFLIP_IDX 7
286 {
287 .id = V4L2_CID_HFLIP,
288 .type = V4L2_CTRL_TYPE_BOOLEAN,
289 .name = "Horizontal Flip",
290 .minimum = 0,
291 .maximum = 1,
292 .step = 1,
293#define HFLIP_DEFAULT 0
294 .default_value = HFLIP_DEFAULT,
295 },
296 .set = sd_sethflip,
297 .get = sd_gethflip,
298 },
299 {
300#define VFLIP_IDX 8
301 {
302 .id = V4L2_CID_VFLIP,
303 .type = V4L2_CTRL_TYPE_BOOLEAN,
304 .name = "Vertical Flip",
305 .minimum = 0,
306 .maximum = 1,
307 .step = 1,
308#define VFLIP_DEFAULT 0
309 .default_value = VFLIP_DEFAULT,
310 },
311 .set = sd_setvflip,
312 .get = sd_getvflip,
313 },
314 {
315#define EXPOSURE_IDX 9
316 {
317 .id = V4L2_CID_EXPOSURE,
318 .type = V4L2_CTRL_TYPE_INTEGER,
319 .name = "Exposure",
320 .minimum = 0,
321 .maximum = 0x1780,
322 .step = 1,
323#define EXPOSURE_DEFAULT 0x33
324 .default_value = EXPOSURE_DEFAULT,
325 },
326 .set = sd_setexposure,
327 .get = sd_getexposure,
328 },
329 {
330#define GAIN_IDX 10
331 {
332 .id = V4L2_CID_GAIN,
333 .type = V4L2_CTRL_TYPE_INTEGER,
334 .name = "Gain",
335 .minimum = 0,
336 .maximum = 28,
337 .step = 1,
338#define GAIN_DEFAULT 0x00
339 .default_value = GAIN_DEFAULT,
340 },
341 .set = sd_setgain,
342 .get = sd_getgain,
343 },
344 {
345#define AUTOGAIN_IDX 11
346 {
347 .id = V4L2_CID_AUTOGAIN,
348 .type = V4L2_CTRL_TYPE_BOOLEAN,
349 .name = "Auto Exposure",
350 .minimum = 0,
351 .maximum = 1,
352 .step = 1,
353#define AUTO_EXPOSURE_DEFAULT 1
354 .default_value = AUTO_EXPOSURE_DEFAULT,
355 },
356 .set = sd_setautoexposure,
357 .get = sd_getautoexposure,
358 },
359};
360
361static const struct v4l2_pix_format vga_mode[] = {
362 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300363 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300364 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300365 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300366 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300367 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
368 .bytesperline = 160,
369 .sizeimage = 160 * 120,
370 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300371 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300372 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300373 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300374 .sizeimage = 240 * 120,
375 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300376 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300377 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300378 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300379 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300380 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300381 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300382 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
383 .bytesperline = 320,
384 .sizeimage = 320 * 240 ,
385 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300386 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300387 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300388 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300389 .sizeimage = 480 * 240 ,
390 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300391 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300392 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300393 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300394 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300395 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300396 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300397 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
398 .bytesperline = 640,
399 .sizeimage = 640 * 480,
400 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300401 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300402 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300403 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300404 .sizeimage = 960 * 480,
405 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300406 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300407};
408
409static const struct v4l2_pix_format sxga_mode[] = {
410 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300411 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300412 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300413 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300414 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300415 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
416 .bytesperline = 160,
417 .sizeimage = 160 * 120,
418 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300419 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300420 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300421 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300422 .sizeimage = 240 * 120,
423 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300424 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300425 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300426 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300427 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300428 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300429 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300430 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
431 .bytesperline = 320,
432 .sizeimage = 320 * 240 ,
433 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300434 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300435 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300436 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300437 .sizeimage = 480 * 240 ,
438 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300439 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300440 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300441 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300442 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300443 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300444 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300445 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
446 .bytesperline = 640,
447 .sizeimage = 640 * 480,
448 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300449 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300450 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300451 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300452 .sizeimage = 960 * 480,
453 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300454 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300455 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
456 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300457 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300458 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300459 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300460};
461
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300462static const struct v4l2_pix_format mono_mode[] = {
463 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
464 .bytesperline = 160,
465 .sizeimage = 160 * 120,
466 .colorspace = V4L2_COLORSPACE_SRGB,
467 .priv = SCALE_160x120 | MODE_RAW},
468 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
469 .bytesperline = 320,
470 .sizeimage = 320 * 240 ,
471 .colorspace = V4L2_COLORSPACE_SRGB,
472 .priv = SCALE_320x240 | MODE_RAW},
473 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
474 .bytesperline = 640,
475 .sizeimage = 640 * 480,
476 .colorspace = V4L2_COLORSPACE_SRGB,
477 .priv = SCALE_640x480 | MODE_RAW},
478 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
479 .bytesperline = 1280,
480 .sizeimage = 1280 * 1024,
481 .colorspace = V4L2_COLORSPACE_SRGB,
482 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
483};
484
Joe Perches58aa68c2009-09-02 01:12:13 -0300485static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300486 41, 44, 46, 48, 50, 52, 54, 56,
487 58, 60, 62, 64, 66, 68, 70, 72,
488 74, 76, 78, 80, 81, 83, 85, 87,
489 88, 90, 92, 93, 95, 97, 98, 100,
490 101, 102, 104, 105, 107, 108, 109, 110,
491 112, 113, 114, 115, 116, 117, 118, 119,
492 120, 121, 122, 123, 123, 124, 125, 125,
493 126, 127, 127, 128, 128, 129, 129, 129,
494 130, 130, 130, 130, 131, 131, 131, 131,
495 131, 131, 131, 131, 130, 130, 130, 130,
496 129, 129, 129, 128, 128, 127, 127, 126,
497 125, 125, 124, 123, 122, 122, 121, 120,
498 119, 118, 117, 116, 115, 114, 112, 111,
499 110, 109, 107, 106, 105, 103, 102, 101,
500 99, 98, 96, 94, 93, 91, 90, 88,
501 86, 84, 83, 81, 79, 77, 75, 74,
502 72, 70, 68, 66, 64, 62, 60, 58,
503 56, 54, 52, 49, 47, 45, 43, 41,
504 39, 36, 34, 32, 30, 28, 25, 23,
505 21, 19, 16, 14, 12, 9, 7, 5,
506 3, 0, -1, -3, -6, -8, -10, -12,
507 -15, -17, -19, -22, -24, -26, -28, -30,
508 -33, -35, -37, -39, -41, -44, -46, -48,
509 -50, -52, -54, -56, -58, -60, -62, -64,
510 -66, -68, -70, -72, -74, -76, -78, -80,
511 -81, -83, -85, -87, -88, -90, -92, -93,
512 -95, -97, -98, -100, -101, -102, -104, -105,
513 -107, -108, -109, -110, -112, -113, -114, -115,
514 -116, -117, -118, -119, -120, -121, -122, -123,
515 -123, -124, -125, -125, -126, -127, -127, -128,
516 -128, -128, -128, -128, -128, -128, -128, -128,
517 -128, -128, -128, -128, -128, -128, -128, -128,
518 -128, -128, -128, -128, -128, -128, -128, -128,
519 -128, -127, -127, -126, -125, -125, -124, -123,
520 -122, -122, -121, -120, -119, -118, -117, -116,
521 -115, -114, -112, -111, -110, -109, -107, -106,
522 -105, -103, -102, -101, -99, -98, -96, -94,
523 -93, -91, -90, -88, -86, -84, -83, -81,
524 -79, -77, -75, -74, -72, -70, -68, -66,
525 -64, -62, -60, -58, -56, -54, -52, -49,
526 -47, -45, -43, -41, -39, -36, -34, -32,
527 -30, -28, -25, -23, -21, -19, -16, -14,
528 -12, -9, -7, -5, -3, 0, 1, 3,
529 6, 8, 10, 12, 15, 17, 19, 22,
530 24, 26, 28, 30, 33, 35, 37, 39, 41
531};
532
Joe Perches58aa68c2009-09-02 01:12:13 -0300533static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300534 82, 80, 78, 76, 74, 73, 71, 69,
535 67, 65, 63, 61, 58, 56, 54, 52,
536 50, 48, 46, 44, 41, 39, 37, 35,
537 32, 30, 28, 26, 23, 21, 19, 16,
538 14, 12, 10, 7, 5, 3, 0, -1,
539 -3, -6, -8, -10, -13, -15, -17, -19,
540 -22, -24, -26, -29, -31, -33, -35, -38,
541 -40, -42, -44, -46, -48, -51, -53, -55,
542 -57, -59, -61, -63, -65, -67, -69, -71,
543 -73, -75, -77, -79, -81, -82, -84, -86,
544 -88, -89, -91, -93, -94, -96, -98, -99,
545 -101, -102, -104, -105, -106, -108, -109, -110,
546 -112, -113, -114, -115, -116, -117, -119, -120,
547 -120, -121, -122, -123, -124, -125, -126, -126,
548 -127, -128, -128, -128, -128, -128, -128, -128,
549 -128, -128, -128, -128, -128, -128, -128, -128,
550 -128, -128, -128, -128, -128, -128, -128, -128,
551 -128, -128, -128, -128, -128, -128, -128, -128,
552 -127, -127, -126, -125, -125, -124, -123, -122,
553 -121, -120, -119, -118, -117, -116, -115, -114,
554 -113, -111, -110, -109, -107, -106, -105, -103,
555 -102, -100, -99, -97, -96, -94, -92, -91,
556 -89, -87, -85, -84, -82, -80, -78, -76,
557 -74, -73, -71, -69, -67, -65, -63, -61,
558 -58, -56, -54, -52, -50, -48, -46, -44,
559 -41, -39, -37, -35, -32, -30, -28, -26,
560 -23, -21, -19, -16, -14, -12, -10, -7,
561 -5, -3, 0, 1, 3, 6, 8, 10,
562 13, 15, 17, 19, 22, 24, 26, 29,
563 31, 33, 35, 38, 40, 42, 44, 46,
564 48, 51, 53, 55, 57, 59, 61, 63,
565 65, 67, 69, 71, 73, 75, 77, 79,
566 81, 82, 84, 86, 88, 89, 91, 93,
567 94, 96, 98, 99, 101, 102, 104, 105,
568 106, 108, 109, 110, 112, 113, 114, 115,
569 116, 117, 119, 120, 120, 121, 122, 123,
570 124, 125, 126, 126, 127, 128, 128, 129,
571 129, 130, 130, 131, 131, 131, 131, 132,
572 132, 132, 132, 132, 132, 132, 132, 132,
573 132, 132, 132, 131, 131, 131, 130, 130,
574 130, 129, 129, 128, 127, 127, 126, 125,
575 125, 124, 123, 122, 121, 120, 119, 118,
576 117, 116, 115, 114, 113, 111, 110, 109,
577 107, 106, 105, 103, 102, 100, 99, 97,
578 96, 94, 92, 91, 89, 87, 85, 84, 82
579};
580
Joe Perches58aa68c2009-09-02 01:12:13 -0300581static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300582 -124, -124, -125, -125, -125, -125, -125, -125,
583 -125, -126, -126, -125, -125, -125, -125, -125,
584 -125, -124, -124, -124, -123, -123, -122, -122,
585 -121, -121, -120, -120, -119, -118, -117, -117,
586 -116, -115, -114, -113, -112, -111, -110, -109,
587 -108, -107, -105, -104, -103, -102, -100, -99,
588 -98, -96, -95, -93, -92, -91, -89, -87,
589 -86, -84, -83, -81, -79, -77, -76, -74,
590 -72, -70, -69, -67, -65, -63, -61, -59,
591 -57, -55, -53, -51, -49, -47, -45, -43,
592 -41, -39, -37, -35, -33, -30, -28, -26,
593 -24, -22, -20, -18, -15, -13, -11, -9,
594 -7, -4, -2, 0, 1, 3, 6, 8,
595 10, 12, 14, 17, 19, 21, 23, 25,
596 27, 29, 32, 34, 36, 38, 40, 42,
597 44, 46, 48, 50, 52, 54, 56, 58,
598 60, 62, 64, 66, 68, 70, 71, 73,
599 75, 77, 78, 80, 82, 83, 85, 87,
600 88, 90, 91, 93, 94, 96, 97, 98,
601 100, 101, 102, 104, 105, 106, 107, 108,
602 109, 111, 112, 113, 113, 114, 115, 116,
603 117, 118, 118, 119, 120, 120, 121, 122,
604 122, 123, 123, 124, 124, 124, 125, 125,
605 125, 125, 125, 125, 125, 126, 126, 125,
606 125, 125, 125, 125, 125, 124, 124, 124,
607 123, 123, 122, 122, 121, 121, 120, 120,
608 119, 118, 117, 117, 116, 115, 114, 113,
609 112, 111, 110, 109, 108, 107, 105, 104,
610 103, 102, 100, 99, 98, 96, 95, 93,
611 92, 91, 89, 87, 86, 84, 83, 81,
612 79, 77, 76, 74, 72, 70, 69, 67,
613 65, 63, 61, 59, 57, 55, 53, 51,
614 49, 47, 45, 43, 41, 39, 37, 35,
615 33, 30, 28, 26, 24, 22, 20, 18,
616 15, 13, 11, 9, 7, 4, 2, 0,
617 -1, -3, -6, -8, -10, -12, -14, -17,
618 -19, -21, -23, -25, -27, -29, -32, -34,
619 -36, -38, -40, -42, -44, -46, -48, -50,
620 -52, -54, -56, -58, -60, -62, -64, -66,
621 -68, -70, -71, -73, -75, -77, -78, -80,
622 -82, -83, -85, -87, -88, -90, -91, -93,
623 -94, -96, -97, -98, -100, -101, -102, -104,
624 -105, -106, -107, -108, -109, -111, -112, -113,
625 -113, -114, -115, -116, -117, -118, -118, -119,
626 -120, -120, -121, -122, -122, -123, -123, -124, -124
627};
628
Joe Perches58aa68c2009-09-02 01:12:13 -0300629static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300630 -100, -99, -98, -97, -95, -94, -93, -91,
631 -90, -89, -87, -86, -84, -83, -81, -80,
632 -78, -76, -75, -73, -71, -70, -68, -66,
633 -64, -63, -61, -59, -57, -55, -53, -51,
634 -49, -48, -46, -44, -42, -40, -38, -36,
635 -34, -32, -30, -27, -25, -23, -21, -19,
636 -17, -15, -13, -11, -9, -7, -4, -2,
637 0, 1, 3, 5, 7, 9, 11, 14,
638 16, 18, 20, 22, 24, 26, 28, 30,
639 32, 34, 36, 38, 40, 42, 44, 46,
640 48, 50, 52, 54, 56, 58, 59, 61,
641 63, 65, 67, 68, 70, 72, 74, 75,
642 77, 78, 80, 82, 83, 85, 86, 88,
643 89, 90, 92, 93, 95, 96, 97, 98,
644 100, 101, 102, 103, 104, 105, 106, 107,
645 108, 109, 110, 111, 112, 112, 113, 114,
646 115, 115, 116, 116, 117, 117, 118, 118,
647 119, 119, 119, 120, 120, 120, 120, 120,
648 121, 121, 121, 121, 121, 121, 120, 120,
649 120, 120, 120, 119, 119, 119, 118, 118,
650 117, 117, 116, 116, 115, 114, 114, 113,
651 112, 111, 111, 110, 109, 108, 107, 106,
652 105, 104, 103, 102, 100, 99, 98, 97,
653 95, 94, 93, 91, 90, 89, 87, 86,
654 84, 83, 81, 80, 78, 76, 75, 73,
655 71, 70, 68, 66, 64, 63, 61, 59,
656 57, 55, 53, 51, 49, 48, 46, 44,
657 42, 40, 38, 36, 34, 32, 30, 27,
658 25, 23, 21, 19, 17, 15, 13, 11,
659 9, 7, 4, 2, 0, -1, -3, -5,
660 -7, -9, -11, -14, -16, -18, -20, -22,
661 -24, -26, -28, -30, -32, -34, -36, -38,
662 -40, -42, -44, -46, -48, -50, -52, -54,
663 -56, -58, -59, -61, -63, -65, -67, -68,
664 -70, -72, -74, -75, -77, -78, -80, -82,
665 -83, -85, -86, -88, -89, -90, -92, -93,
666 -95, -96, -97, -98, -100, -101, -102, -103,
667 -104, -105, -106, -107, -108, -109, -110, -111,
668 -112, -112, -113, -114, -115, -115, -116, -116,
669 -117, -117, -118, -118, -119, -119, -119, -120,
670 -120, -120, -120, -120, -121, -121, -121, -121,
671 -121, -121, -120, -120, -120, -120, -120, -119,
672 -119, -119, -118, -118, -117, -117, -116, -116,
673 -115, -114, -114, -113, -112, -111, -111, -110,
674 -109, -108, -107, -106, -105, -104, -103, -102, -100
675};
676
Joe Perches58aa68c2009-09-02 01:12:13 -0300677static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300678 112, 113, 114, 114, 115, 116, 117, 117,
679 118, 118, 119, 119, 120, 120, 120, 121,
680 121, 121, 122, 122, 122, 122, 122, 122,
681 122, 122, 122, 122, 122, 122, 121, 121,
682 121, 120, 120, 120, 119, 119, 118, 118,
683 117, 116, 116, 115, 114, 113, 113, 112,
684 111, 110, 109, 108, 107, 106, 105, 104,
685 103, 102, 100, 99, 98, 97, 95, 94,
686 93, 91, 90, 88, 87, 85, 84, 82,
687 80, 79, 77, 76, 74, 72, 70, 69,
688 67, 65, 63, 61, 60, 58, 56, 54,
689 52, 50, 48, 46, 44, 42, 40, 38,
690 36, 34, 32, 30, 28, 26, 24, 22,
691 19, 17, 15, 13, 11, 9, 7, 5,
692 2, 0, -1, -3, -5, -7, -9, -12,
693 -14, -16, -18, -20, -22, -24, -26, -28,
694 -31, -33, -35, -37, -39, -41, -43, -45,
695 -47, -49, -51, -53, -54, -56, -58, -60,
696 -62, -64, -66, -67, -69, -71, -73, -74,
697 -76, -78, -79, -81, -83, -84, -86, -87,
698 -89, -90, -92, -93, -94, -96, -97, -98,
699 -99, -101, -102, -103, -104, -105, -106, -107,
700 -108, -109, -110, -111, -112, -113, -114, -114,
701 -115, -116, -117, -117, -118, -118, -119, -119,
702 -120, -120, -120, -121, -121, -121, -122, -122,
703 -122, -122, -122, -122, -122, -122, -122, -122,
704 -122, -122, -121, -121, -121, -120, -120, -120,
705 -119, -119, -118, -118, -117, -116, -116, -115,
706 -114, -113, -113, -112, -111, -110, -109, -108,
707 -107, -106, -105, -104, -103, -102, -100, -99,
708 -98, -97, -95, -94, -93, -91, -90, -88,
709 -87, -85, -84, -82, -80, -79, -77, -76,
710 -74, -72, -70, -69, -67, -65, -63, -61,
711 -60, -58, -56, -54, -52, -50, -48, -46,
712 -44, -42, -40, -38, -36, -34, -32, -30,
713 -28, -26, -24, -22, -19, -17, -15, -13,
714 -11, -9, -7, -5, -2, 0, 1, 3,
715 5, 7, 9, 12, 14, 16, 18, 20,
716 22, 24, 26, 28, 31, 33, 35, 37,
717 39, 41, 43, 45, 47, 49, 51, 53,
718 54, 56, 58, 60, 62, 64, 66, 67,
719 69, 71, 73, 74, 76, 78, 79, 81,
720 83, 84, 86, 87, 89, 90, 92, 93,
721 94, 96, 97, 98, 99, 101, 102, 103,
722 104, 105, 106, 107, 108, 109, 110, 111, 112
723};
724
Joe Perches58aa68c2009-09-02 01:12:13 -0300725static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300726 -11, -13, -15, -17, -19, -21, -23, -25,
727 -27, -29, -31, -33, -35, -37, -39, -41,
728 -43, -45, -46, -48, -50, -52, -54, -55,
729 -57, -59, -61, -62, -64, -66, -67, -69,
730 -71, -72, -74, -75, -77, -78, -80, -81,
731 -83, -84, -86, -87, -88, -90, -91, -92,
732 -93, -95, -96, -97, -98, -99, -100, -101,
733 -102, -103, -104, -105, -106, -106, -107, -108,
734 -109, -109, -110, -111, -111, -112, -112, -113,
735 -113, -114, -114, -114, -115, -115, -115, -115,
736 -116, -116, -116, -116, -116, -116, -116, -116,
737 -116, -115, -115, -115, -115, -114, -114, -114,
738 -113, -113, -112, -112, -111, -111, -110, -110,
739 -109, -108, -108, -107, -106, -105, -104, -103,
740 -102, -101, -100, -99, -98, -97, -96, -95,
741 -94, -93, -91, -90, -89, -88, -86, -85,
742 -84, -82, -81, -79, -78, -76, -75, -73,
743 -71, -70, -68, -67, -65, -63, -62, -60,
744 -58, -56, -55, -53, -51, -49, -47, -45,
745 -44, -42, -40, -38, -36, -34, -32, -30,
746 -28, -26, -24, -22, -20, -18, -16, -14,
747 -12, -10, -8, -6, -4, -2, 0, 1,
748 3, 5, 7, 9, 11, 13, 15, 17,
749 19, 21, 23, 25, 27, 29, 31, 33,
750 35, 37, 39, 41, 43, 45, 46, 48,
751 50, 52, 54, 55, 57, 59, 61, 62,
752 64, 66, 67, 69, 71, 72, 74, 75,
753 77, 78, 80, 81, 83, 84, 86, 87,
754 88, 90, 91, 92, 93, 95, 96, 97,
755 98, 99, 100, 101, 102, 103, 104, 105,
756 106, 106, 107, 108, 109, 109, 110, 111,
757 111, 112, 112, 113, 113, 114, 114, 114,
758 115, 115, 115, 115, 116, 116, 116, 116,
759 116, 116, 116, 116, 116, 115, 115, 115,
760 115, 114, 114, 114, 113, 113, 112, 112,
761 111, 111, 110, 110, 109, 108, 108, 107,
762 106, 105, 104, 103, 102, 101, 100, 99,
763 98, 97, 96, 95, 94, 93, 91, 90,
764 89, 88, 86, 85, 84, 82, 81, 79,
765 78, 76, 75, 73, 71, 70, 68, 67,
766 65, 63, 62, 60, 58, 56, 55, 53,
767 51, 49, 47, 45, 44, 42, 40, 38,
768 36, 34, 32, 30, 28, 26, 24, 22,
769 20, 18, 16, 14, 12, 10, 8, 6,
770 4, 2, 0, -1, -3, -5, -7, -9, -11
771};
772
773static u16 i2c_ident[] = {
774 V4L2_IDENT_OV9650,
775 V4L2_IDENT_OV9655,
776 V4L2_IDENT_SOI968,
777 V4L2_IDENT_OV7660,
778 V4L2_IDENT_OV7670,
779 V4L2_IDENT_MT9V011,
780 V4L2_IDENT_MT9V111,
781 V4L2_IDENT_MT9V112,
782 V4L2_IDENT_MT9M001C12ST,
783 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300784 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300785 V4L2_IDENT_HV7131R,
786};
787
788static u16 bridge_init[][2] = {
789 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
790 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
791 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
792 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
793 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
794 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
795 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
796 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
797 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
798 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
799 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
800 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
801 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
802 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
803 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
804 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
805 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
806 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300807 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
808 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300809};
810
811/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
812static u8 ov_gain[] = {
813 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
814 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
815 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
816 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
817 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
818 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
819 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
820 0x70 /* 8x */
821};
822
823/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
824static u16 micron1_gain[] = {
825 /* 1x 1.25x 1.5x 1.75x */
826 0x0020, 0x0028, 0x0030, 0x0038,
827 /* 2x 2.25x 2.5x 2.75x */
828 0x00a0, 0x00a4, 0x00a8, 0x00ac,
829 /* 3x 3.25x 3.5x 3.75x */
830 0x00b0, 0x00b4, 0x00b8, 0x00bc,
831 /* 4x 4.25x 4.5x 4.75x */
832 0x00c0, 0x00c4, 0x00c8, 0x00cc,
833 /* 5x 5.25x 5.5x 5.75x */
834 0x00d0, 0x00d4, 0x00d8, 0x00dc,
835 /* 6x 6.25x 6.5x 6.75x */
836 0x00e0, 0x00e4, 0x00e8, 0x00ec,
837 /* 7x 7.25x 7.5x 7.75x */
838 0x00f0, 0x00f4, 0x00f8, 0x00fc,
839 /* 8x */
840 0x01c0
841};
842
843/* mt9m001 sensor uses a different gain formula then other micron sensors */
844/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
845static u16 micron2_gain[] = {
846 /* 1x 1.25x 1.5x 1.75x */
847 0x0008, 0x000a, 0x000c, 0x000e,
848 /* 2x 2.25x 2.5x 2.75x */
849 0x0010, 0x0012, 0x0014, 0x0016,
850 /* 3x 3.25x 3.5x 3.75x */
851 0x0018, 0x001a, 0x001c, 0x001e,
852 /* 4x 4.25x 4.5x 4.75x */
853 0x0020, 0x0051, 0x0052, 0x0053,
854 /* 5x 5.25x 5.5x 5.75x */
855 0x0054, 0x0055, 0x0056, 0x0057,
856 /* 6x 6.25x 6.5x 6.75x */
857 0x0058, 0x0059, 0x005a, 0x005b,
858 /* 7x 7.25x 7.5x 7.75x */
859 0x005c, 0x005d, 0x005e, 0x005f,
860 /* 8x */
861 0x0060
862};
863
864/* Gain = .5 + bit[7:0] / 16 */
865static u8 hv7131r_gain[] = {
866 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
867 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
868 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
869 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
870 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
871 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
872 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
873 0x78 /* 8x */
874};
875
Joe Perches58aa68c2009-09-02 01:12:13 -0300876static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300877 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
878 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
879 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
880 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
881 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
882 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300883 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300884 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
885 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
886 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
887 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
888};
889
Joe Perches58aa68c2009-09-02 01:12:13 -0300890static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300891 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
892 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
893 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300894 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
895 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
896 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300897 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
898 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
899 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
900};
901
Joe Perches58aa68c2009-09-02 01:12:13 -0300902static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300903 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
904 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
905 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
906 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
907 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
908 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
909 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
910 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
911 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
912 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
913 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
914 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
915 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
916 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
917 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
918 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
919 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
920 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
921 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
922 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
923 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
924 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
925 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
926 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
927 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
928 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
929 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
930 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
931 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
932 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
933 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
934 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
935 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
936 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
937 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
938 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
939 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
940 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
941 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
942 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
943 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
944 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
945 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
946 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
947 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
948 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
949 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
950 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
951 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
952 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
953 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
954 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
955 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
956 {0x93, 0x00},
957};
958
Joe Perches58aa68c2009-09-02 01:12:13 -0300959static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300960 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
961 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
962 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
963 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
964 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
965 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
966 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
967 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
968 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
969 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
970 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
971 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
972 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
973 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
974 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
975 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
976 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
977 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
978 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
979 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
980 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
981 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
982 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
983 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
984 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
985 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
986 {0xaa, 0x92}, {0xab, 0x0a},
987};
988
Joe Perches58aa68c2009-09-02 01:12:13 -0300989static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300990 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
991 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
992 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
993 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
994 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
995 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
996 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
997 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
998 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
999 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
1000 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
1001 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
1002 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
1003 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
1004 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
1005 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -03001006 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001007 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
1008 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -03001009 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001010 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
1011 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
1012 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
1013 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -03001014};
1015
Joe Perches58aa68c2009-09-02 01:12:13 -03001016static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001017 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
1018 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
1019 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
1020 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1021 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1022 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1023 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1024 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1025 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1026 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1027 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1028 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1029 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1030 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1031 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1032 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1033};
1034
Joe Perches58aa68c2009-09-02 01:12:13 -03001035static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001036 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001037 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1038 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1039 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1040 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1041 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1042 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001043};
1044
Joe Perches58aa68c2009-09-02 01:12:13 -03001045static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001046 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1047 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1048 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1049 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1050 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1051 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1052 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1053 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1054 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1055 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1056 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1057 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1058 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1059 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1060 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1061 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1062 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1063 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1064 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1065 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1066 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1067 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1068 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1069 {0x06, 0x0029}, {0x05, 0x0009},
1070};
1071
Joe Perches58aa68c2009-09-02 01:12:13 -03001072static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001073 {0x0d, 0x0001},
1074 {0x0d, 0x0000},
1075 {0x04, 0x0500}, /* hres = 1280 */
1076 {0x03, 0x0400}, /* vres = 1024 */
1077 {0x20, 0x1100},
1078 {0x06, 0x0010},
1079 {0x2b, 0x0024},
1080 {0x2e, 0x0024},
1081 {0x35, 0x0024},
1082 {0x2d, 0x0020},
1083 {0x2c, 0x0020},
1084 {0x09, 0x0ad4},
1085 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001086};
1087
Joe Perches58aa68c2009-09-02 01:12:13 -03001088static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001089 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1090 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001091 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1092 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001093};
1094
Brian Johnsone99ac542010-03-16 13:58:28 -03001095static struct i2c_reg_u16 mt9m112_init[] = {
1096 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1097 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1098 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1099 {0xf0, 0x0000},
1100};
1101
Joe Perches58aa68c2009-09-02 01:12:13 -03001102static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001103 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1104 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1105 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1106 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1107 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1108 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1109 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1110 {0x23, 0x09}, {0x01, 0x08},
1111};
1112
Joe Perches58aa68c2009-09-02 01:12:13 -03001113static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001114{
1115 struct usb_device *dev = gspca_dev->dev;
1116 int result;
1117 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1118 0x00,
1119 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1120 reg,
1121 0x00,
1122 gspca_dev->usb_buf,
1123 length,
1124 500);
1125 if (unlikely(result < 0 || result != length)) {
1126 err("Read register failed 0x%02X", reg);
1127 return -EIO;
1128 }
1129 return 0;
1130}
1131
Joe Perches58aa68c2009-09-02 01:12:13 -03001132static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1133 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001134{
1135 struct usb_device *dev = gspca_dev->dev;
1136 int result;
1137 memcpy(gspca_dev->usb_buf, buffer, length);
1138 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1139 0x08,
1140 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1141 reg,
1142 0x00,
1143 gspca_dev->usb_buf,
1144 length,
1145 500);
1146 if (unlikely(result < 0 || result != length)) {
1147 err("Write register failed index 0x%02X", reg);
1148 return -EIO;
1149 }
1150 return 0;
1151}
1152
Joe Perches58aa68c2009-09-02 01:12:13 -03001153static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001154{
1155 u8 data[1] = {value};
1156 return reg_w(gspca_dev, reg, data, 1);
1157}
1158
Joe Perches58aa68c2009-09-02 01:12:13 -03001159static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001160{
1161 int i;
1162 reg_w(gspca_dev, 0x10c0, buffer, 8);
1163 for (i = 0; i < 5; i++) {
1164 reg_r(gspca_dev, 0x10c0, 1);
1165 if (gspca_dev->usb_buf[0] & 0x04) {
1166 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001167 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001168 return 0;
1169 }
1170 msleep(1);
1171 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001172 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001173}
1174
Joe Perches58aa68c2009-09-02 01:12:13 -03001175static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001176{
1177 struct sd *sd = (struct sd *) gspca_dev;
1178
1179 u8 row[8];
1180
1181 /*
1182 * from the point of view of the bridge, the length
1183 * includes the address
1184 */
1185 row[0] = 0x81 | (2 << 4);
1186 row[1] = sd->i2c_addr;
1187 row[2] = reg;
1188 row[3] = val;
1189 row[4] = 0x00;
1190 row[5] = 0x00;
1191 row[6] = 0x00;
1192 row[7] = 0x10;
1193
1194 return i2c_w(gspca_dev, row);
1195}
1196
Joe Perches58aa68c2009-09-02 01:12:13 -03001197static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001198{
1199 struct sd *sd = (struct sd *) gspca_dev;
1200 u8 row[8];
1201
1202 /*
1203 * from the point of view of the bridge, the length
1204 * includes the address
1205 */
1206 row[0] = 0x81 | (3 << 4);
1207 row[1] = sd->i2c_addr;
1208 row[2] = reg;
1209 row[3] = (val >> 8) & 0xff;
1210 row[4] = val & 0xff;
1211 row[5] = 0x00;
1212 row[6] = 0x00;
1213 row[7] = 0x10;
1214
1215 return i2c_w(gspca_dev, row);
1216}
1217
Jean-Francois Moine83955552009-12-12 06:58:01 -03001218static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001219{
1220 struct sd *sd = (struct sd *) gspca_dev;
1221 u8 row[8];
1222
Brian Johnson00b581e2009-07-23 05:55:43 -03001223 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001224 row[1] = sd->i2c_addr;
1225 row[2] = reg;
1226 row[3] = 0;
1227 row[4] = 0;
1228 row[5] = 0;
1229 row[6] = 0;
1230 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001231 if (i2c_w(gspca_dev, row) < 0)
1232 return -EIO;
1233 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001234 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001235 if (i2c_w(gspca_dev, row) < 0)
1236 return -EIO;
1237 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1238 return -EIO;
1239 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001240 return 0;
1241}
1242
Jean-Francois Moine83955552009-12-12 06:58:01 -03001243static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001244{
1245 struct sd *sd = (struct sd *) gspca_dev;
1246 u8 row[8];
1247
Brian Johnson00b581e2009-07-23 05:55:43 -03001248 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001249 row[1] = sd->i2c_addr;
1250 row[2] = reg;
1251 row[3] = 0;
1252 row[4] = 0;
1253 row[5] = 0;
1254 row[6] = 0;
1255 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001256 if (i2c_w(gspca_dev, row) < 0)
1257 return -EIO;
1258 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001259 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001260 if (i2c_w(gspca_dev, row) < 0)
1261 return -EIO;
1262 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1263 return -EIO;
1264 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001265 return 0;
1266}
1267
1268static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1269{
1270 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001271 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001272 struct sd *sd = (struct sd *) gspca_dev;
1273
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001274 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1275 return -EINVAL;
1276
1277 if (id != 0x7fa2) {
1278 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1279 return -ENODEV;
1280 }
1281
Brian Johnson26e744b2009-07-19 05:52:58 -03001282 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001283 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1284 ov9650_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001285 err("OV9650 sensor initialization failed");
1286 return -ENODEV;
1287 }
1288 }
1289 sd->hstart = 1;
1290 sd->vstart = 7;
1291 return 0;
1292}
1293
1294static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1295{
1296 int i;
1297 struct sd *sd = (struct sd *) gspca_dev;
1298
1299 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001300 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1301 ov9655_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001302 err("OV9655 sensor initialization failed");
1303 return -ENODEV;
1304 }
1305 }
1306 /* disable hflip and vflip */
1307 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001308 sd->hstart = 1;
1309 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001310 return 0;
1311}
1312
1313static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1314{
1315 int i;
1316 struct sd *sd = (struct sd *) gspca_dev;
1317
1318 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001319 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1320 soi968_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001321 err("SOI968 sensor initialization failed");
1322 return -ENODEV;
1323 }
1324 }
1325 /* disable hflip and vflip */
Jean-François Moine780e3122010-10-19 04:29:10 -03001326 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1327 | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001328 sd->hstart = 60;
1329 sd->vstart = 11;
1330 return 0;
1331}
1332
1333static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1334{
1335 int i;
1336 struct sd *sd = (struct sd *) gspca_dev;
1337
1338 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001339 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1340 ov7660_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001341 err("OV7660 sensor initialization failed");
1342 return -ENODEV;
1343 }
1344 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001345 sd->hstart = 3;
1346 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001347 return 0;
1348}
1349
1350static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1351{
1352 int i;
1353 struct sd *sd = (struct sd *) gspca_dev;
1354
1355 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001356 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1357 ov7670_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001358 err("OV7670 sensor initialization failed");
1359 return -ENODEV;
1360 }
1361 }
1362 /* disable hflip and vflip */
1363 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1364 sd->hstart = 0;
1365 sd->vstart = 1;
1366 return 0;
1367}
1368
1369static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1370{
1371 struct sd *sd = (struct sd *) gspca_dev;
1372 int i;
1373 u16 value;
1374 int ret;
1375
1376 sd->i2c_addr = 0x5d;
1377 ret = i2c_r2(gspca_dev, 0xff, &value);
1378 if ((ret == 0) && (value == 0x8243)) {
1379 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001380 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1381 mt9v011_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001382 err("MT9V011 sensor initialization failed");
1383 return -ENODEV;
1384 }
1385 }
1386 sd->hstart = 2;
1387 sd->vstart = 2;
1388 sd->sensor = SENSOR_MT9V011;
1389 info("MT9V011 sensor detected");
1390 return 0;
1391 }
1392
1393 sd->i2c_addr = 0x5c;
1394 i2c_w2(gspca_dev, 0x01, 0x0004);
1395 ret = i2c_r2(gspca_dev, 0xff, &value);
1396 if ((ret == 0) && (value == 0x823a)) {
1397 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001398 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1399 mt9v111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001400 err("MT9V111 sensor initialization failed");
1401 return -ENODEV;
1402 }
1403 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001404 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1405 | (1 << AUTOGAIN_IDX)
1406 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001407 sd->hstart = 2;
1408 sd->vstart = 2;
1409 sd->sensor = SENSOR_MT9V111;
1410 info("MT9V111 sensor detected");
1411 return 0;
1412 }
1413
1414 sd->i2c_addr = 0x5d;
1415 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1416 if (ret < 0) {
1417 sd->i2c_addr = 0x48;
1418 i2c_w2(gspca_dev, 0xf0, 0x0000);
1419 }
1420 ret = i2c_r2(gspca_dev, 0x00, &value);
1421 if ((ret == 0) && (value == 0x1229)) {
1422 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001423 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1424 mt9v112_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001425 err("MT9V112 sensor initialization failed");
1426 return -ENODEV;
1427 }
1428 }
1429 sd->hstart = 6;
1430 sd->vstart = 2;
1431 sd->sensor = SENSOR_MT9V112;
1432 info("MT9V112 sensor detected");
1433 return 0;
1434 }
1435
1436 return -ENODEV;
1437}
1438
Brian Johnsone99ac542010-03-16 13:58:28 -03001439static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1440{
1441 struct sd *sd = (struct sd *) gspca_dev;
1442 int i;
1443 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1444 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1445 mt9m112_init[i].val) < 0) {
1446 err("MT9M112 sensor initialization failed");
1447 return -ENODEV;
1448 }
1449 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001450 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1451 | (1 << GAIN_IDX);
Brian Johnsone99ac542010-03-16 13:58:28 -03001452 sd->hstart = 0;
1453 sd->vstart = 2;
1454 return 0;
1455}
1456
Brian Johnson26e744b2009-07-19 05:52:58 -03001457static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1458{
1459 struct sd *sd = (struct sd *) gspca_dev;
1460 int i;
1461 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001462 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1463 mt9m111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001464 err("MT9M111 sensor initialization failed");
1465 return -ENODEV;
1466 }
1467 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001468 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1469 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001470 sd->hstart = 0;
1471 sd->vstart = 2;
1472 return 0;
1473}
1474
1475static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
1478 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001479 u16 id;
1480
1481 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1482 return -EINVAL;
1483
1484 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1485 switch (id) {
1486 case 0x8411:
1487 case 0x8421:
1488 info("MT9M001 color sensor detected");
1489 break;
1490 case 0x8431:
1491 info("MT9M001 mono sensor detected");
1492 break;
1493 default:
1494 err("No MT9M001 chip detected, ID = %x\n", id);
1495 return -ENODEV;
1496 }
1497
Brian Johnson26e744b2009-07-19 05:52:58 -03001498 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001499 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1500 mt9m001_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001501 err("MT9M001 sensor initialization failed");
1502 return -ENODEV;
1503 }
1504 }
1505 /* disable hflip and vflip */
1506 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001507 sd->hstart = 1;
1508 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001509 return 0;
1510}
1511
1512static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1513{
1514 int i;
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001518 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1519 hv7131r_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001520 err("HV7131R Sensor initialization failed");
1521 return -ENODEV;
1522 }
1523 }
1524 sd->hstart = 0;
1525 sd->vstart = 1;
1526 return 0;
1527}
1528
Brian Johnson26e744b2009-07-19 05:52:58 -03001529static int set_cmatrix(struct gspca_dev *gspca_dev)
1530{
1531 struct sd *sd = (struct sd *) gspca_dev;
1532 s32 hue_coord, hue_index = 180 + sd->hue;
1533 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001534
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001535 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001536 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1537 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1538 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1539 cmatrix[18] = sd->brightness - 0x80;
1540
1541 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001542 cmatrix[6] = hue_coord;
1543 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001544
1545 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001546 cmatrix[8] = hue_coord;
1547 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001548
1549 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001550 cmatrix[10] = hue_coord;
1551 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001552
1553 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001554 cmatrix[12] = hue_coord;
1555 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001556
1557 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001558 cmatrix[14] = hue_coord;
1559 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001560
1561 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001562 cmatrix[16] = hue_coord;
1563 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001564
1565 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1566}
1567
1568static int set_gamma(struct gspca_dev *gspca_dev)
1569{
1570 struct sd *sd = (struct sd *) gspca_dev;
1571 u8 gamma[17];
1572 u8 gval = sd->gamma * 0xb8 / 0x100;
1573
1574
1575 gamma[0] = 0x0a;
1576 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1577 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1578 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1579 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1580 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1581 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1582 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1583 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1584 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1585 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1586 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1587 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1588 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1589 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1590 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1591 gamma[16] = 0xf5;
1592
1593 return reg_w(gspca_dev, 0x1190, gamma, 17);
1594}
1595
1596static int set_redblue(struct gspca_dev *gspca_dev)
1597{
1598 struct sd *sd = (struct sd *) gspca_dev;
1599 reg_w1(gspca_dev, 0x118c, sd->red);
1600 reg_w1(gspca_dev, 0x118f, sd->blue);
1601 return 0;
1602}
1603
1604static int set_hvflip(struct gspca_dev *gspca_dev)
1605{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001606 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001607 u16 value2;
1608 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001609
1610 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1611 hflip = !sd->hflip;
1612 vflip = !sd->vflip;
1613 } else {
1614 hflip = sd->hflip;
1615 vflip = sd->vflip;
1616 }
1617
Brian Johnson26e744b2009-07-19 05:52:58 -03001618 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001619 case SENSOR_OV7660:
1620 value = 0x01;
1621 if (hflip)
1622 value |= 0x20;
1623 if (vflip) {
1624 value |= 0x10;
1625 sd->vstart = 2;
1626 } else
1627 sd->vstart = 3;
1628 reg_w1(gspca_dev, 0x1182, sd->vstart);
1629 i2c_w1(gspca_dev, 0x1e, value);
1630 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001631 case SENSOR_OV9650:
1632 i2c_r1(gspca_dev, 0x1e, &value);
1633 value &= ~0x30;
1634 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001635 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001636 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001637 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001638 value |= 0x10;
1639 tslb = 0x49;
1640 }
1641 i2c_w1(gspca_dev, 0x1e, value);
1642 i2c_w1(gspca_dev, 0x3a, tslb);
1643 break;
1644 case SENSOR_MT9V111:
1645 case SENSOR_MT9V011:
1646 i2c_r2(gspca_dev, 0x20, &value2);
1647 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001648 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001649 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001650 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001651 value2 |= 0x4020;
1652 i2c_w2(gspca_dev, 0x20, value2);
1653 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001654 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001655 case SENSOR_MT9M111:
1656 case SENSOR_MT9V112:
1657 i2c_r2(gspca_dev, 0x20, &value2);
1658 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001659 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001660 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001661 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001662 value2 |= 0x0001;
1663 i2c_w2(gspca_dev, 0x20, value2);
1664 break;
1665 case SENSOR_HV7131R:
1666 i2c_r1(gspca_dev, 0x01, &value);
1667 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001668 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001669 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001670 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001671 value |= 0x02;
1672 i2c_w1(gspca_dev, 0x01, value);
1673 break;
1674 }
1675 return 0;
1676}
1677
1678static int set_exposure(struct gspca_dev *gspca_dev)
1679{
1680 struct sd *sd = (struct sd *) gspca_dev;
1681 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1682 switch (sd->sensor) {
1683 case SENSOR_OV7660:
1684 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001685 case SENSOR_OV9655:
1686 case SENSOR_OV9650:
1687 exp[0] |= (3 << 4);
1688 exp[2] = 0x2d;
1689 exp[3] = sd->exposure & 0xff;
1690 exp[4] = sd->exposure >> 8;
1691 break;
1692 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001693 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001694 case SENSOR_MT9V011:
1695 exp[0] |= (3 << 4);
1696 exp[2] = 0x09;
1697 exp[3] = sd->exposure >> 8;
1698 exp[4] = sd->exposure & 0xff;
1699 break;
1700 case SENSOR_HV7131R:
1701 exp[0] |= (4 << 4);
1702 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001703 exp[3] = (sd->exposure >> 5) & 0xff;
1704 exp[4] = (sd->exposure << 3) & 0xff;
1705 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001706 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001707 default:
1708 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001709 }
1710 i2c_w(gspca_dev, exp);
1711 return 0;
1712}
1713
1714static int set_gain(struct gspca_dev *gspca_dev)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1718 switch (sd->sensor) {
1719 case SENSOR_OV7660:
1720 case SENSOR_OV7670:
1721 case SENSOR_SOI968:
1722 case SENSOR_OV9655:
1723 case SENSOR_OV9650:
1724 gain[0] |= (2 << 4);
1725 gain[3] = ov_gain[sd->gain];
1726 break;
1727 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001728 gain[0] |= (3 << 4);
1729 gain[2] = 0x35;
1730 gain[3] = micron1_gain[sd->gain] >> 8;
1731 gain[4] = micron1_gain[sd->gain] & 0xff;
1732 break;
1733 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001734 gain[0] |= (3 << 4);
1735 gain[2] = 0x2f;
1736 gain[3] = micron1_gain[sd->gain] >> 8;
1737 gain[4] = micron1_gain[sd->gain] & 0xff;
1738 break;
1739 case SENSOR_MT9M001:
1740 gain[0] |= (3 << 4);
1741 gain[2] = 0x2f;
1742 gain[3] = micron2_gain[sd->gain] >> 8;
1743 gain[4] = micron2_gain[sd->gain] & 0xff;
1744 break;
1745 case SENSOR_HV7131R:
1746 gain[0] |= (2 << 4);
1747 gain[2] = 0x30;
1748 gain[3] = hv7131r_gain[sd->gain];
1749 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001750 default:
1751 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001752 }
1753 i2c_w(gspca_dev, gain);
1754 return 0;
1755}
1756
1757static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1758{
1759 struct sd *sd = (struct sd *) gspca_dev;
1760
1761 sd->brightness = val;
1762 if (gspca_dev->streaming)
1763 return set_cmatrix(gspca_dev);
1764 return 0;
1765}
1766
1767static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1768{
1769 struct sd *sd = (struct sd *) gspca_dev;
1770 *val = sd->brightness;
1771 return 0;
1772}
1773
1774
1775static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1776{
1777 struct sd *sd = (struct sd *) gspca_dev;
1778
1779 sd->contrast = val;
1780 if (gspca_dev->streaming)
1781 return set_cmatrix(gspca_dev);
1782 return 0;
1783}
1784
1785static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1786{
1787 struct sd *sd = (struct sd *) gspca_dev;
1788 *val = sd->contrast;
1789 return 0;
1790}
1791
1792static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1793{
1794 struct sd *sd = (struct sd *) gspca_dev;
1795
1796 sd->saturation = val;
1797 if (gspca_dev->streaming)
1798 return set_cmatrix(gspca_dev);
1799 return 0;
1800}
1801
1802static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1803{
1804 struct sd *sd = (struct sd *) gspca_dev;
1805 *val = sd->saturation;
1806 return 0;
1807}
1808
1809static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1810{
1811 struct sd *sd = (struct sd *) gspca_dev;
1812
1813 sd->hue = val;
1814 if (gspca_dev->streaming)
1815 return set_cmatrix(gspca_dev);
1816 return 0;
1817}
1818
1819static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1820{
1821 struct sd *sd = (struct sd *) gspca_dev;
1822 *val = sd->hue;
1823 return 0;
1824}
1825
1826static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1827{
1828 struct sd *sd = (struct sd *) gspca_dev;
1829
1830 sd->gamma = val;
1831 if (gspca_dev->streaming)
1832 return set_gamma(gspca_dev);
1833 return 0;
1834}
1835
1836static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1837{
1838 struct sd *sd = (struct sd *) gspca_dev;
1839 *val = sd->gamma;
1840 return 0;
1841}
1842
1843static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1844{
1845 struct sd *sd = (struct sd *) gspca_dev;
1846
1847 sd->red = val;
1848 if (gspca_dev->streaming)
1849 return set_redblue(gspca_dev);
1850 return 0;
1851}
1852
1853static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1854{
1855 struct sd *sd = (struct sd *) gspca_dev;
1856 *val = sd->red;
1857 return 0;
1858}
1859
1860static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1861{
1862 struct sd *sd = (struct sd *) gspca_dev;
1863
1864 sd->blue = val;
1865 if (gspca_dev->streaming)
1866 return set_redblue(gspca_dev);
1867 return 0;
1868}
1869
1870static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1871{
1872 struct sd *sd = (struct sd *) gspca_dev;
1873 *val = sd->blue;
1874 return 0;
1875}
1876
1877static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1878{
1879 struct sd *sd = (struct sd *) gspca_dev;
1880
1881 sd->hflip = val;
1882 if (gspca_dev->streaming)
1883 return set_hvflip(gspca_dev);
1884 return 0;
1885}
1886
1887static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1888{
1889 struct sd *sd = (struct sd *) gspca_dev;
1890 *val = sd->hflip;
1891 return 0;
1892}
1893
1894static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1895{
1896 struct sd *sd = (struct sd *) gspca_dev;
1897
1898 sd->vflip = val;
1899 if (gspca_dev->streaming)
1900 return set_hvflip(gspca_dev);
1901 return 0;
1902}
1903
1904static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1905{
1906 struct sd *sd = (struct sd *) gspca_dev;
1907 *val = sd->vflip;
1908 return 0;
1909}
1910
1911static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1912{
1913 struct sd *sd = (struct sd *) gspca_dev;
1914
1915 sd->exposure = val;
1916 if (gspca_dev->streaming)
1917 return set_exposure(gspca_dev);
1918 return 0;
1919}
1920
1921static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1922{
1923 struct sd *sd = (struct sd *) gspca_dev;
1924 *val = sd->exposure;
1925 return 0;
1926}
1927
1928static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1929{
1930 struct sd *sd = (struct sd *) gspca_dev;
1931
1932 sd->gain = val;
1933 if (gspca_dev->streaming)
1934 return set_gain(gspca_dev);
1935 return 0;
1936}
1937
1938static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1939{
1940 struct sd *sd = (struct sd *) gspca_dev;
1941 *val = sd->gain;
1942 return 0;
1943}
1944
1945static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1946{
1947 struct sd *sd = (struct sd *) gspca_dev;
1948 sd->auto_exposure = val;
1949 return 0;
1950}
1951
1952static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1953{
1954 struct sd *sd = (struct sd *) gspca_dev;
1955 *val = sd->auto_exposure;
1956 return 0;
1957}
1958
1959#ifdef CONFIG_VIDEO_ADV_DEBUG
1960static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1961 struct v4l2_dbg_register *reg)
1962{
1963 struct sd *sd = (struct sd *) gspca_dev;
1964 switch (reg->match.type) {
1965 case V4L2_CHIP_MATCH_HOST:
1966 if (reg->match.addr != 0)
1967 return -EINVAL;
1968 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1969 return -EINVAL;
1970 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1971 return -EINVAL;
1972 reg->val = gspca_dev->usb_buf[0];
1973 return 0;
1974 case V4L2_CHIP_MATCH_I2C_ADDR:
1975 if (reg->match.addr != sd->i2c_addr)
1976 return -EINVAL;
1977 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001978 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001979 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1980 return -EINVAL;
1981 } else {
1982 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1983 return -EINVAL;
1984 }
1985 return 0;
1986 }
1987 return -EINVAL;
1988}
1989
1990static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1991 struct v4l2_dbg_register *reg)
1992{
1993 struct sd *sd = (struct sd *) gspca_dev;
1994 switch (reg->match.type) {
1995 case V4L2_CHIP_MATCH_HOST:
1996 if (reg->match.addr != 0)
1997 return -EINVAL;
1998 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1999 return -EINVAL;
2000 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
2001 return -EINVAL;
2002 return 0;
2003 case V4L2_CHIP_MATCH_I2C_ADDR:
2004 if (reg->match.addr != sd->i2c_addr)
2005 return -EINVAL;
2006 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03002007 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002008 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
2009 return -EINVAL;
2010 } else {
2011 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
2012 return -EINVAL;
2013 }
2014 return 0;
2015 }
2016 return -EINVAL;
2017}
2018#endif
2019
2020static int sd_chip_ident(struct gspca_dev *gspca_dev,
2021 struct v4l2_dbg_chip_ident *chip)
2022{
2023 struct sd *sd = (struct sd *) gspca_dev;
2024
2025 switch (chip->match.type) {
2026 case V4L2_CHIP_MATCH_HOST:
2027 if (chip->match.addr != 0)
2028 return -EINVAL;
2029 chip->revision = 0;
2030 chip->ident = V4L2_IDENT_SN9C20X;
2031 return 0;
2032 case V4L2_CHIP_MATCH_I2C_ADDR:
2033 if (chip->match.addr != sd->i2c_addr)
2034 return -EINVAL;
2035 chip->revision = 0;
2036 chip->ident = i2c_ident[sd->sensor];
2037 return 0;
2038 }
2039 return -EINVAL;
2040}
2041
2042static int sd_config(struct gspca_dev *gspca_dev,
2043 const struct usb_device_id *id)
2044{
2045 struct sd *sd = (struct sd *) gspca_dev;
2046 struct cam *cam;
2047
2048 cam = &gspca_dev->cam;
2049
2050 sd->sensor = (id->driver_info >> 8) & 0xff;
2051 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002052 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03002053
2054 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03002055 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002056 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03002057 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002058 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03002059 cam->cam_mode = sxga_mode;
2060 cam->nmodes = ARRAY_SIZE(sxga_mode);
2061 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03002062 case SENSOR_MT9M001:
2063 cam->cam_mode = mono_mode;
2064 cam->nmodes = ARRAY_SIZE(mono_mode);
2065 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002066 default:
2067 cam->cam_mode = vga_mode;
2068 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002069 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002070 }
2071
2072 sd->old_step = 0;
2073 sd->older_step = 0;
2074 sd->exposure_step = 16;
2075
2076 sd->brightness = BRIGHTNESS_DEFAULT;
2077 sd->contrast = CONTRAST_DEFAULT;
2078 sd->saturation = SATURATION_DEFAULT;
2079 sd->hue = HUE_DEFAULT;
2080 sd->gamma = GAMMA_DEFAULT;
2081 sd->red = RED_DEFAULT;
2082 sd->blue = BLUE_DEFAULT;
2083
2084 sd->hflip = HFLIP_DEFAULT;
2085 sd->vflip = VFLIP_DEFAULT;
2086 sd->exposure = EXPOSURE_DEFAULT;
2087 sd->gain = GAIN_DEFAULT;
2088 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2089
2090 sd->quality = 95;
2091
Brian Johnson26e744b2009-07-19 05:52:58 -03002092 return 0;
2093}
2094
2095static int sd_init(struct gspca_dev *gspca_dev)
2096{
2097 struct sd *sd = (struct sd *) gspca_dev;
2098 int i;
2099 u8 value;
2100 u8 i2c_init[9] =
2101 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2102
2103 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2104 value = bridge_init[i][1];
2105 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2106 err("Device initialization failed");
2107 return -ENODEV;
2108 }
2109 }
2110
Brian Johnson0c045eb2010-03-16 13:58:27 -03002111 if (sd->flags & LED_REVERSE)
2112 reg_w1(gspca_dev, 0x1006, 0x00);
2113 else
2114 reg_w1(gspca_dev, 0x1006, 0x20);
2115
Brian Johnson26e744b2009-07-19 05:52:58 -03002116 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2117 err("Device initialization failed");
2118 return -ENODEV;
2119 }
2120
2121 switch (sd->sensor) {
2122 case SENSOR_OV9650:
2123 if (ov9650_init_sensor(gspca_dev) < 0)
2124 return -ENODEV;
2125 info("OV9650 sensor detected");
2126 break;
2127 case SENSOR_OV9655:
2128 if (ov9655_init_sensor(gspca_dev) < 0)
2129 return -ENODEV;
2130 info("OV9655 sensor detected");
2131 break;
2132 case SENSOR_SOI968:
2133 if (soi968_init_sensor(gspca_dev) < 0)
2134 return -ENODEV;
2135 info("SOI968 sensor detected");
2136 break;
2137 case SENSOR_OV7660:
2138 if (ov7660_init_sensor(gspca_dev) < 0)
2139 return -ENODEV;
2140 info("OV7660 sensor detected");
2141 break;
2142 case SENSOR_OV7670:
2143 if (ov7670_init_sensor(gspca_dev) < 0)
2144 return -ENODEV;
2145 info("OV7670 sensor detected");
2146 break;
2147 case SENSOR_MT9VPRB:
2148 if (mt9v_init_sensor(gspca_dev) < 0)
2149 return -ENODEV;
2150 break;
2151 case SENSOR_MT9M111:
2152 if (mt9m111_init_sensor(gspca_dev) < 0)
2153 return -ENODEV;
2154 info("MT9M111 sensor detected");
2155 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002156 case SENSOR_MT9M112:
2157 if (mt9m112_init_sensor(gspca_dev) < 0)
2158 return -ENODEV;
2159 info("MT9M112 sensor detected");
2160 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002161 case SENSOR_MT9M001:
2162 if (mt9m001_init_sensor(gspca_dev) < 0)
2163 return -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03002164 break;
2165 case SENSOR_HV7131R:
2166 if (hv7131r_init_sensor(gspca_dev) < 0)
2167 return -ENODEV;
2168 info("HV7131R sensor detected");
2169 break;
2170 default:
2171 info("Unsupported Sensor");
2172 return -ENODEV;
2173 }
2174
2175 return 0;
2176}
2177
2178static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2179{
2180 struct sd *sd = (struct sd *) gspca_dev;
2181 u8 value;
2182 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002183 case SENSOR_SOI968:
2184 if (mode & MODE_SXGA) {
2185 i2c_w1(gspca_dev, 0x17, 0x1d);
2186 i2c_w1(gspca_dev, 0x18, 0xbd);
2187 i2c_w1(gspca_dev, 0x19, 0x01);
2188 i2c_w1(gspca_dev, 0x1a, 0x81);
2189 i2c_w1(gspca_dev, 0x12, 0x00);
2190 sd->hstart = 140;
2191 sd->vstart = 19;
2192 } else {
2193 i2c_w1(gspca_dev, 0x17, 0x13);
2194 i2c_w1(gspca_dev, 0x18, 0x63);
2195 i2c_w1(gspca_dev, 0x19, 0x01);
2196 i2c_w1(gspca_dev, 0x1a, 0x79);
2197 i2c_w1(gspca_dev, 0x12, 0x40);
2198 sd->hstart = 60;
2199 sd->vstart = 11;
2200 }
2201 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002202 case SENSOR_OV9650:
2203 if (mode & MODE_SXGA) {
2204 i2c_w1(gspca_dev, 0x17, 0x1b);
2205 i2c_w1(gspca_dev, 0x18, 0xbc);
2206 i2c_w1(gspca_dev, 0x19, 0x01);
2207 i2c_w1(gspca_dev, 0x1a, 0x82);
2208 i2c_r1(gspca_dev, 0x12, &value);
2209 i2c_w1(gspca_dev, 0x12, value & 0x07);
2210 } else {
2211 i2c_w1(gspca_dev, 0x17, 0x24);
2212 i2c_w1(gspca_dev, 0x18, 0xc5);
2213 i2c_w1(gspca_dev, 0x19, 0x00);
2214 i2c_w1(gspca_dev, 0x1a, 0x3c);
2215 i2c_r1(gspca_dev, 0x12, &value);
2216 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2217 }
2218 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002219 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002220 case SENSOR_MT9M111:
2221 if (mode & MODE_SXGA) {
2222 i2c_w2(gspca_dev, 0xf0, 0x0002);
2223 i2c_w2(gspca_dev, 0xc8, 0x970b);
2224 i2c_w2(gspca_dev, 0xf0, 0x0000);
2225 } else {
2226 i2c_w2(gspca_dev, 0xf0, 0x0002);
2227 i2c_w2(gspca_dev, 0xc8, 0x8000);
2228 i2c_w2(gspca_dev, 0xf0, 0x0000);
2229 }
2230 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002231 }
2232}
2233
2234#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002235((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002236(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2237(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2238
2239#define CLR_WIN(width, height) \
2240((const u8 [])\
2241{0, width >> 2, 0, height >> 1,\
2242((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2243
2244static int sd_start(struct gspca_dev *gspca_dev)
2245{
2246 struct sd *sd = (struct sd *) gspca_dev;
2247 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2248 int width = gspca_dev->width;
2249 int height = gspca_dev->height;
2250 u8 fmt, scale = 0;
2251
Brian Johnson26e744b2009-07-19 05:52:58 -03002252 jpeg_define(sd->jpeg_hdr, height, width,
2253 0x21);
2254 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2255
2256 if (mode & MODE_RAW)
2257 fmt = 0x2d;
2258 else if (mode & MODE_JPEG)
2259 fmt = 0x2c;
2260 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002261 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002262
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002263 switch (mode & SCALE_MASK) {
2264 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002265 scale = 0xc0;
2266 info("Set 1280x1024");
2267 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002268 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002269 scale = 0x80;
2270 info("Set 640x480");
2271 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002272 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002273 scale = 0x90;
2274 info("Set 320x240");
2275 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002276 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002277 scale = 0xa0;
2278 info("Set 160x120");
2279 break;
2280 }
2281
2282 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002283 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2284 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002285 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2286 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2287 reg_w1(gspca_dev, 0x1189, scale);
2288 reg_w1(gspca_dev, 0x10e0, fmt);
2289
2290 set_cmatrix(gspca_dev);
2291 set_gamma(gspca_dev);
2292 set_redblue(gspca_dev);
2293 set_gain(gspca_dev);
2294 set_exposure(gspca_dev);
2295 set_hvflip(gspca_dev);
2296
Brian Johnson0c045eb2010-03-16 13:58:27 -03002297 reg_w1(gspca_dev, 0x1007, 0x20);
2298
Brian Johnson26e744b2009-07-19 05:52:58 -03002299 reg_r(gspca_dev, 0x1061, 1);
2300 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2301 return 0;
2302}
2303
2304static void sd_stopN(struct gspca_dev *gspca_dev)
2305{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002306 reg_w1(gspca_dev, 0x1007, 0x00);
2307
Brian Johnson26e744b2009-07-19 05:52:58 -03002308 reg_r(gspca_dev, 0x1061, 1);
2309 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2310}
2311
Brian Johnsone1430472009-09-02 12:39:41 -03002312static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002313{
2314 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002315 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002316
2317 /*
2318 * some hardcoded values are present
2319 * like those for maximal/minimal exposure
2320 * and exposure steps
2321 */
2322 if (avg_lum < MIN_AVG_LUM) {
2323 if (sd->exposure > 0x1770)
2324 return;
2325
2326 new_exp = sd->exposure + sd->exposure_step;
2327 if (new_exp > 0x1770)
2328 new_exp = 0x1770;
2329 if (new_exp < 0x10)
2330 new_exp = 0x10;
2331 sd->exposure = new_exp;
2332 set_exposure(gspca_dev);
2333
2334 sd->older_step = sd->old_step;
2335 sd->old_step = 1;
2336
2337 if (sd->old_step ^ sd->older_step)
2338 sd->exposure_step /= 2;
2339 else
2340 sd->exposure_step += 2;
2341 }
2342 if (avg_lum > MAX_AVG_LUM) {
2343 if (sd->exposure < 0x10)
2344 return;
2345 new_exp = sd->exposure - sd->exposure_step;
2346 if (new_exp > 0x1700)
2347 new_exp = 0x1770;
2348 if (new_exp < 0x10)
2349 new_exp = 0x10;
2350 sd->exposure = new_exp;
2351 set_exposure(gspca_dev);
2352 sd->older_step = sd->old_step;
2353 sd->old_step = 0;
2354
2355 if (sd->old_step ^ sd->older_step)
2356 sd->exposure_step /= 2;
2357 else
2358 sd->exposure_step += 2;
2359 }
2360}
2361
Brian Johnsone1430472009-09-02 12:39:41 -03002362static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2363{
2364 struct sd *sd = (struct sd *) gspca_dev;
2365
2366 if (avg_lum < MIN_AVG_LUM) {
2367 if (sd->gain + 1 <= 28) {
2368 sd->gain++;
2369 set_gain(gspca_dev);
2370 }
2371 }
2372 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002373 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002374 sd->gain--;
2375 set_gain(gspca_dev);
2376 }
2377 }
2378}
2379
2380static void sd_dqcallback(struct gspca_dev *gspca_dev)
2381{
2382 struct sd *sd = (struct sd *) gspca_dev;
2383 int avg_lum;
2384
2385 if (!sd->auto_exposure)
2386 return;
2387
2388 avg_lum = atomic_read(&sd->avg_lum);
2389 if (sd->sensor == SENSOR_SOI968)
2390 do_autogain(gspca_dev, avg_lum);
2391 else
2392 do_autoexposure(gspca_dev, avg_lum);
2393}
2394
Jean-François Moine28566432010-10-01 07:33:26 -03002395#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002396static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2397 u8 *data, /* interrupt packet */
2398 int len) /* interrupt packet length */
2399{
2400 struct sd *sd = (struct sd *) gspca_dev;
2401 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002402 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002403 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2404 input_sync(gspca_dev->input_dev);
2405 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2406 input_sync(gspca_dev->input_dev);
2407 ret = 0;
2408 }
2409 return ret;
2410}
2411#endif
2412
Brian Johnson26e744b2009-07-19 05:52:58 -03002413static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002414 u8 *data, /* isoc packet */
2415 int len) /* iso packet length */
2416{
2417 struct sd *sd = (struct sd *) gspca_dev;
2418 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002419 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002420 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2421 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2422 avg_lum = ((data[35] >> 2) & 3) |
2423 (data[20] << 2) |
2424 (data[19] << 10);
2425 avg_lum += ((data[35] >> 4) & 3) |
2426 (data[22] << 2) |
2427 (data[21] << 10);
2428 avg_lum += ((data[35] >> 6) & 3) |
2429 (data[24] << 2) |
2430 (data[23] << 10);
2431 avg_lum += (data[36] & 3) |
2432 (data[26] << 2) |
2433 (data[25] << 10);
2434 avg_lum += ((data[36] >> 2) & 3) |
2435 (data[28] << 2) |
2436 (data[27] << 10);
2437 avg_lum += ((data[36] >> 4) & 3) |
2438 (data[30] << 2) |
2439 (data[29] << 10);
2440 avg_lum += ((data[36] >> 6) & 3) |
2441 (data[32] << 2) |
2442 (data[31] << 10);
2443 avg_lum += ((data[44] >> 4) & 3) |
2444 (data[34] << 2) |
2445 (data[33] << 10);
2446 avg_lum >>= 9;
2447 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002448 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Brian Johnson26e744b2009-07-19 05:52:58 -03002449 return;
2450 }
2451 if (gspca_dev->last_packet_type == LAST_PACKET) {
2452 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2453 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002454 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002455 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002456 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002457 data, len);
2458 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002459 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002460 data, len);
2461 }
2462 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002463 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002464 }
2465}
2466
2467/* sub-driver description */
2468static const struct sd_desc sd_desc = {
2469 .name = MODULE_NAME,
2470 .ctrls = sd_ctrls,
2471 .nctrls = ARRAY_SIZE(sd_ctrls),
2472 .config = sd_config,
2473 .init = sd_init,
2474 .start = sd_start,
2475 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002476 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002477#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002478 .int_pkt_scan = sd_int_pkt_scan,
2479#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002480 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002481#ifdef CONFIG_VIDEO_ADV_DEBUG
2482 .set_register = sd_dbg_s_register,
2483 .get_register = sd_dbg_g_register,
2484#endif
2485 .get_chip_ident = sd_chip_ident,
2486};
2487
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002488#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002489 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002490 | (SENSOR_ ## sensor << 8) \
2491 | (i2c_addr)
2492
Jean-François Moine95c967c2011-01-13 05:20:29 -03002493static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002494 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2495 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2496 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002497 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002498 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2499 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2500 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002501 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2502 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2503 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2504 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002505 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002506 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2507 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2508 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2509 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002510 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002511 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002512 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2513 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2514 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2515 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2516 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002517 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002518 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2519 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2520 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2521 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002522 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2523 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002524 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2525 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2526 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2527 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002528 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002529 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2530 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2531 {}
2532};
2533MODULE_DEVICE_TABLE(usb, device_table);
2534
2535/* -- device connect -- */
2536static int sd_probe(struct usb_interface *intf,
2537 const struct usb_device_id *id)
2538{
2539 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2540 THIS_MODULE);
2541}
2542
Brian Johnson26e744b2009-07-19 05:52:58 -03002543static struct usb_driver sd_driver = {
2544 .name = MODULE_NAME,
2545 .id_table = device_table,
2546 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002547 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002548#ifdef CONFIG_PM
2549 .suspend = gspca_suspend,
2550 .resume = gspca_resume,
2551 .reset_resume = gspca_resume,
2552#endif
2553};
2554
2555/* -- module insert / remove -- */
2556static int __init sd_mod_init(void)
2557{
Jean-François Moine54826432010-09-13 04:53:03 -03002558 return usb_register(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002559}
2560static void __exit sd_mod_exit(void)
2561{
2562 usb_deregister(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002563}
2564
2565module_init(sd_mod_init);
2566module_exit(sd_mod_exit);