blob: 9b3a052999827f00a73b5989ce4ce43b8e229880 [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
Joe Perches91f58422011-08-21 19:56:55 -030021#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
Brian Johnson26e744b2009-07-19 05:52:58 -030023#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030024
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030025#include "gspca.h"
26#include "jpeg.h"
27
28#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030029#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030030
Brian Johnson26e744b2009-07-19 05:52:58 -030031MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
32 "microdia project <microdia@googlegroups.com>");
33MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
34MODULE_LICENSE("GPL");
35
36#define MODULE_NAME "sn9c20x"
37
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -030038/*
39 * Pixel format private data
40 */
41#define SCALE_MASK 0x0f
42#define SCALE_160x120 0
43#define SCALE_320x240 1
44#define SCALE_640x480 2
45#define SCALE_1280x1024 3
Brian Johnson26e744b2009-07-19 05:52:58 -030046#define MODE_RAW 0x10
47#define MODE_JPEG 0x20
48#define MODE_SXGA 0x80
49
50#define SENSOR_OV9650 0
51#define SENSOR_OV9655 1
52#define SENSOR_SOI968 2
53#define SENSOR_OV7660 3
54#define SENSOR_OV7670 4
55#define SENSOR_MT9V011 5
56#define SENSOR_MT9V111 6
57#define SENSOR_MT9V112 7
58#define SENSOR_MT9M001 8
59#define SENSOR_MT9M111 9
Brian Johnsone99ac542010-03-16 13:58:28 -030060#define SENSOR_MT9M112 10
61#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030062#define SENSOR_MT9VPRB 20
63
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030064/* camera flags */
Brian Johnson33ddc162010-04-18 21:42:40 -030065#define HAS_NO_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030066#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030067#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030068
Brian Johnson26e744b2009-07-19 05:52:58 -030069/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev;
72
73#define MIN_AVG_LUM 80
74#define MAX_AVG_LUM 130
75 atomic_t avg_lum;
76 u8 old_step;
77 u8 older_step;
78 u8 exposure_step;
79
80 u8 brightness;
81 u8 contrast;
82 u8 saturation;
83 s16 hue;
84 u8 gamma;
85 u8 red;
86 u8 blue;
87
88 u8 hflip;
89 u8 vflip;
90 u8 gain;
91 u16 exposure;
92 u8 auto_exposure;
93
94 u8 i2c_addr;
95 u8 sensor;
96 u8 hstart;
97 u8 vstart;
98
Jean-François Moine9a731a32010-06-04 05:26:42 -030099 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300100 u8 quality;
101
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300102 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300103};
104
Joe Perches58aa68c2009-09-02 01:12:13 -0300105struct i2c_reg_u8 {
106 u8 reg;
107 u8 val;
108};
109
110struct i2c_reg_u16 {
111 u8 reg;
112 u16 val;
113};
114
Brian Johnson26e744b2009-07-19 05:52:58 -0300115static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
116static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
117static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
118static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
119static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
120static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
121static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
122static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
123static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
124static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
125static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
126static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
127static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
128static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
129static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
130static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
131static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
132static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
133static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
134static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
135static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
136static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
137static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
138static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
139
Brian Johnson7ddaac72010-03-16 13:58:27 -0300140static const struct dmi_system_id flip_dmi_table[] = {
141 {
142 .ident = "MSI MS-1034",
143 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
145 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
146 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
147 }
148 },
149 {
150 .ident = "MSI MS-1632",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
153 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
154 }
155 },
Brian Johnsone077f862010-04-05 20:52:52 -0300156 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300157 .ident = "MSI MS-1633X",
158 .matches = {
159 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
160 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
161 }
162 },
163 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300164 .ident = "MSI MS-1635X",
165 .matches = {
166 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
167 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
168 }
169 },
170 {
Brian Johnsone077f862010-04-05 20:52:52 -0300171 .ident = "ASUSTeK W7J",
172 .matches = {
173 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
174 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
175 }
176 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300177 {}
178};
179
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300180static const struct ctrl sd_ctrls[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300181 {
182#define BRIGHTNESS_IDX 0
183 {
184 .id = V4L2_CID_BRIGHTNESS,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "Brightness",
187 .minimum = 0,
188 .maximum = 0xff,
189 .step = 1,
190#define BRIGHTNESS_DEFAULT 0x7f
191 .default_value = BRIGHTNESS_DEFAULT,
192 },
193 .set = sd_setbrightness,
194 .get = sd_getbrightness,
195 },
196 {
197#define CONTRAST_IDX 1
198 {
199 .id = V4L2_CID_CONTRAST,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Contrast",
202 .minimum = 0,
203 .maximum = 0xff,
204 .step = 1,
205#define CONTRAST_DEFAULT 0x7f
206 .default_value = CONTRAST_DEFAULT,
207 },
208 .set = sd_setcontrast,
209 .get = sd_getcontrast,
210 },
211 {
212#define SATURATION_IDX 2
213 {
214 .id = V4L2_CID_SATURATION,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "Saturation",
217 .minimum = 0,
218 .maximum = 0xff,
219 .step = 1,
220#define SATURATION_DEFAULT 0x7f
221 .default_value = SATURATION_DEFAULT,
222 },
223 .set = sd_setsaturation,
224 .get = sd_getsaturation,
225 },
226 {
227#define HUE_IDX 3
228 {
229 .id = V4L2_CID_HUE,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Hue",
232 .minimum = -180,
233 .maximum = 180,
234 .step = 1,
235#define HUE_DEFAULT 0
236 .default_value = HUE_DEFAULT,
237 },
238 .set = sd_sethue,
239 .get = sd_gethue,
240 },
241 {
242#define GAMMA_IDX 4
243 {
244 .id = V4L2_CID_GAMMA,
245 .type = V4L2_CTRL_TYPE_INTEGER,
246 .name = "Gamma",
247 .minimum = 0,
248 .maximum = 0xff,
249 .step = 1,
250#define GAMMA_DEFAULT 0x10
251 .default_value = GAMMA_DEFAULT,
252 },
253 .set = sd_setgamma,
254 .get = sd_getgamma,
255 },
256 {
257#define BLUE_IDX 5
258 {
259 .id = V4L2_CID_BLUE_BALANCE,
260 .type = V4L2_CTRL_TYPE_INTEGER,
261 .name = "Blue Balance",
262 .minimum = 0,
263 .maximum = 0x7f,
264 .step = 1,
265#define BLUE_DEFAULT 0x28
266 .default_value = BLUE_DEFAULT,
267 },
268 .set = sd_setbluebalance,
269 .get = sd_getbluebalance,
270 },
271 {
272#define RED_IDX 6
273 {
274 .id = V4L2_CID_RED_BALANCE,
275 .type = V4L2_CTRL_TYPE_INTEGER,
276 .name = "Red Balance",
277 .minimum = 0,
278 .maximum = 0x7f,
279 .step = 1,
280#define RED_DEFAULT 0x28
281 .default_value = RED_DEFAULT,
282 },
283 .set = sd_setredbalance,
284 .get = sd_getredbalance,
285 },
286 {
287#define HFLIP_IDX 7
288 {
289 .id = V4L2_CID_HFLIP,
290 .type = V4L2_CTRL_TYPE_BOOLEAN,
291 .name = "Horizontal Flip",
292 .minimum = 0,
293 .maximum = 1,
294 .step = 1,
295#define HFLIP_DEFAULT 0
296 .default_value = HFLIP_DEFAULT,
297 },
298 .set = sd_sethflip,
299 .get = sd_gethflip,
300 },
301 {
302#define VFLIP_IDX 8
303 {
304 .id = V4L2_CID_VFLIP,
305 .type = V4L2_CTRL_TYPE_BOOLEAN,
306 .name = "Vertical Flip",
307 .minimum = 0,
308 .maximum = 1,
309 .step = 1,
310#define VFLIP_DEFAULT 0
311 .default_value = VFLIP_DEFAULT,
312 },
313 .set = sd_setvflip,
314 .get = sd_getvflip,
315 },
316 {
317#define EXPOSURE_IDX 9
318 {
319 .id = V4L2_CID_EXPOSURE,
320 .type = V4L2_CTRL_TYPE_INTEGER,
321 .name = "Exposure",
322 .minimum = 0,
323 .maximum = 0x1780,
324 .step = 1,
325#define EXPOSURE_DEFAULT 0x33
326 .default_value = EXPOSURE_DEFAULT,
327 },
328 .set = sd_setexposure,
329 .get = sd_getexposure,
330 },
331 {
332#define GAIN_IDX 10
333 {
334 .id = V4L2_CID_GAIN,
335 .type = V4L2_CTRL_TYPE_INTEGER,
336 .name = "Gain",
337 .minimum = 0,
338 .maximum = 28,
339 .step = 1,
340#define GAIN_DEFAULT 0x00
341 .default_value = GAIN_DEFAULT,
342 },
343 .set = sd_setgain,
344 .get = sd_getgain,
345 },
346 {
347#define AUTOGAIN_IDX 11
348 {
349 .id = V4L2_CID_AUTOGAIN,
350 .type = V4L2_CTRL_TYPE_BOOLEAN,
351 .name = "Auto Exposure",
352 .minimum = 0,
353 .maximum = 1,
354 .step = 1,
355#define AUTO_EXPOSURE_DEFAULT 1
356 .default_value = AUTO_EXPOSURE_DEFAULT,
357 },
358 .set = sd_setautoexposure,
359 .get = sd_getautoexposure,
360 },
361};
362
363static const struct v4l2_pix_format vga_mode[] = {
364 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300365 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300366 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300367 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300368 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300369 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
370 .bytesperline = 160,
371 .sizeimage = 160 * 120,
372 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300373 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300374 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300375 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300376 .sizeimage = 240 * 120,
377 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300378 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300379 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300380 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300381 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300382 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300383 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300384 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
385 .bytesperline = 320,
386 .sizeimage = 320 * 240 ,
387 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300388 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300389 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300390 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300391 .sizeimage = 480 * 240 ,
392 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300393 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300394 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300395 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300396 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300397 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300398 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300399 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
400 .bytesperline = 640,
401 .sizeimage = 640 * 480,
402 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300403 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300404 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300405 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 .sizeimage = 960 * 480,
407 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300408 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300409};
410
411static const struct v4l2_pix_format sxga_mode[] = {
412 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300413 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300414 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300415 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300416 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300417 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
418 .bytesperline = 160,
419 .sizeimage = 160 * 120,
420 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300421 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300422 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300423 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300424 .sizeimage = 240 * 120,
425 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300426 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300427 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300428 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300429 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300430 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300431 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300432 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
433 .bytesperline = 320,
434 .sizeimage = 320 * 240 ,
435 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300436 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300437 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300438 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300439 .sizeimage = 480 * 240 ,
440 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300441 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300442 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300443 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300444 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300445 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300446 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300447 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
448 .bytesperline = 640,
449 .sizeimage = 640 * 480,
450 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300451 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300452 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300453 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300454 .sizeimage = 960 * 480,
455 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300456 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300457 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
458 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300459 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300460 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300461 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300462};
463
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300464static const struct v4l2_pix_format mono_mode[] = {
465 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
466 .bytesperline = 160,
467 .sizeimage = 160 * 120,
468 .colorspace = V4L2_COLORSPACE_SRGB,
469 .priv = SCALE_160x120 | MODE_RAW},
470 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
471 .bytesperline = 320,
472 .sizeimage = 320 * 240 ,
473 .colorspace = V4L2_COLORSPACE_SRGB,
474 .priv = SCALE_320x240 | MODE_RAW},
475 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
476 .bytesperline = 640,
477 .sizeimage = 640 * 480,
478 .colorspace = V4L2_COLORSPACE_SRGB,
479 .priv = SCALE_640x480 | MODE_RAW},
480 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
481 .bytesperline = 1280,
482 .sizeimage = 1280 * 1024,
483 .colorspace = V4L2_COLORSPACE_SRGB,
484 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
485};
486
Joe Perches58aa68c2009-09-02 01:12:13 -0300487static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300488 41, 44, 46, 48, 50, 52, 54, 56,
489 58, 60, 62, 64, 66, 68, 70, 72,
490 74, 76, 78, 80, 81, 83, 85, 87,
491 88, 90, 92, 93, 95, 97, 98, 100,
492 101, 102, 104, 105, 107, 108, 109, 110,
493 112, 113, 114, 115, 116, 117, 118, 119,
494 120, 121, 122, 123, 123, 124, 125, 125,
495 126, 127, 127, 128, 128, 129, 129, 129,
496 130, 130, 130, 130, 131, 131, 131, 131,
497 131, 131, 131, 131, 130, 130, 130, 130,
498 129, 129, 129, 128, 128, 127, 127, 126,
499 125, 125, 124, 123, 122, 122, 121, 120,
500 119, 118, 117, 116, 115, 114, 112, 111,
501 110, 109, 107, 106, 105, 103, 102, 101,
502 99, 98, 96, 94, 93, 91, 90, 88,
503 86, 84, 83, 81, 79, 77, 75, 74,
504 72, 70, 68, 66, 64, 62, 60, 58,
505 56, 54, 52, 49, 47, 45, 43, 41,
506 39, 36, 34, 32, 30, 28, 25, 23,
507 21, 19, 16, 14, 12, 9, 7, 5,
508 3, 0, -1, -3, -6, -8, -10, -12,
509 -15, -17, -19, -22, -24, -26, -28, -30,
510 -33, -35, -37, -39, -41, -44, -46, -48,
511 -50, -52, -54, -56, -58, -60, -62, -64,
512 -66, -68, -70, -72, -74, -76, -78, -80,
513 -81, -83, -85, -87, -88, -90, -92, -93,
514 -95, -97, -98, -100, -101, -102, -104, -105,
515 -107, -108, -109, -110, -112, -113, -114, -115,
516 -116, -117, -118, -119, -120, -121, -122, -123,
517 -123, -124, -125, -125, -126, -127, -127, -128,
518 -128, -128, -128, -128, -128, -128, -128, -128,
519 -128, -128, -128, -128, -128, -128, -128, -128,
520 -128, -128, -128, -128, -128, -128, -128, -128,
521 -128, -127, -127, -126, -125, -125, -124, -123,
522 -122, -122, -121, -120, -119, -118, -117, -116,
523 -115, -114, -112, -111, -110, -109, -107, -106,
524 -105, -103, -102, -101, -99, -98, -96, -94,
525 -93, -91, -90, -88, -86, -84, -83, -81,
526 -79, -77, -75, -74, -72, -70, -68, -66,
527 -64, -62, -60, -58, -56, -54, -52, -49,
528 -47, -45, -43, -41, -39, -36, -34, -32,
529 -30, -28, -25, -23, -21, -19, -16, -14,
530 -12, -9, -7, -5, -3, 0, 1, 3,
531 6, 8, 10, 12, 15, 17, 19, 22,
532 24, 26, 28, 30, 33, 35, 37, 39, 41
533};
534
Joe Perches58aa68c2009-09-02 01:12:13 -0300535static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300536 82, 80, 78, 76, 74, 73, 71, 69,
537 67, 65, 63, 61, 58, 56, 54, 52,
538 50, 48, 46, 44, 41, 39, 37, 35,
539 32, 30, 28, 26, 23, 21, 19, 16,
540 14, 12, 10, 7, 5, 3, 0, -1,
541 -3, -6, -8, -10, -13, -15, -17, -19,
542 -22, -24, -26, -29, -31, -33, -35, -38,
543 -40, -42, -44, -46, -48, -51, -53, -55,
544 -57, -59, -61, -63, -65, -67, -69, -71,
545 -73, -75, -77, -79, -81, -82, -84, -86,
546 -88, -89, -91, -93, -94, -96, -98, -99,
547 -101, -102, -104, -105, -106, -108, -109, -110,
548 -112, -113, -114, -115, -116, -117, -119, -120,
549 -120, -121, -122, -123, -124, -125, -126, -126,
550 -127, -128, -128, -128, -128, -128, -128, -128,
551 -128, -128, -128, -128, -128, -128, -128, -128,
552 -128, -128, -128, -128, -128, -128, -128, -128,
553 -128, -128, -128, -128, -128, -128, -128, -128,
554 -127, -127, -126, -125, -125, -124, -123, -122,
555 -121, -120, -119, -118, -117, -116, -115, -114,
556 -113, -111, -110, -109, -107, -106, -105, -103,
557 -102, -100, -99, -97, -96, -94, -92, -91,
558 -89, -87, -85, -84, -82, -80, -78, -76,
559 -74, -73, -71, -69, -67, -65, -63, -61,
560 -58, -56, -54, -52, -50, -48, -46, -44,
561 -41, -39, -37, -35, -32, -30, -28, -26,
562 -23, -21, -19, -16, -14, -12, -10, -7,
563 -5, -3, 0, 1, 3, 6, 8, 10,
564 13, 15, 17, 19, 22, 24, 26, 29,
565 31, 33, 35, 38, 40, 42, 44, 46,
566 48, 51, 53, 55, 57, 59, 61, 63,
567 65, 67, 69, 71, 73, 75, 77, 79,
568 81, 82, 84, 86, 88, 89, 91, 93,
569 94, 96, 98, 99, 101, 102, 104, 105,
570 106, 108, 109, 110, 112, 113, 114, 115,
571 116, 117, 119, 120, 120, 121, 122, 123,
572 124, 125, 126, 126, 127, 128, 128, 129,
573 129, 130, 130, 131, 131, 131, 131, 132,
574 132, 132, 132, 132, 132, 132, 132, 132,
575 132, 132, 132, 131, 131, 131, 130, 130,
576 130, 129, 129, 128, 127, 127, 126, 125,
577 125, 124, 123, 122, 121, 120, 119, 118,
578 117, 116, 115, 114, 113, 111, 110, 109,
579 107, 106, 105, 103, 102, 100, 99, 97,
580 96, 94, 92, 91, 89, 87, 85, 84, 82
581};
582
Joe Perches58aa68c2009-09-02 01:12:13 -0300583static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300584 -124, -124, -125, -125, -125, -125, -125, -125,
585 -125, -126, -126, -125, -125, -125, -125, -125,
586 -125, -124, -124, -124, -123, -123, -122, -122,
587 -121, -121, -120, -120, -119, -118, -117, -117,
588 -116, -115, -114, -113, -112, -111, -110, -109,
589 -108, -107, -105, -104, -103, -102, -100, -99,
590 -98, -96, -95, -93, -92, -91, -89, -87,
591 -86, -84, -83, -81, -79, -77, -76, -74,
592 -72, -70, -69, -67, -65, -63, -61, -59,
593 -57, -55, -53, -51, -49, -47, -45, -43,
594 -41, -39, -37, -35, -33, -30, -28, -26,
595 -24, -22, -20, -18, -15, -13, -11, -9,
596 -7, -4, -2, 0, 1, 3, 6, 8,
597 10, 12, 14, 17, 19, 21, 23, 25,
598 27, 29, 32, 34, 36, 38, 40, 42,
599 44, 46, 48, 50, 52, 54, 56, 58,
600 60, 62, 64, 66, 68, 70, 71, 73,
601 75, 77, 78, 80, 82, 83, 85, 87,
602 88, 90, 91, 93, 94, 96, 97, 98,
603 100, 101, 102, 104, 105, 106, 107, 108,
604 109, 111, 112, 113, 113, 114, 115, 116,
605 117, 118, 118, 119, 120, 120, 121, 122,
606 122, 123, 123, 124, 124, 124, 125, 125,
607 125, 125, 125, 125, 125, 126, 126, 125,
608 125, 125, 125, 125, 125, 124, 124, 124,
609 123, 123, 122, 122, 121, 121, 120, 120,
610 119, 118, 117, 117, 116, 115, 114, 113,
611 112, 111, 110, 109, 108, 107, 105, 104,
612 103, 102, 100, 99, 98, 96, 95, 93,
613 92, 91, 89, 87, 86, 84, 83, 81,
614 79, 77, 76, 74, 72, 70, 69, 67,
615 65, 63, 61, 59, 57, 55, 53, 51,
616 49, 47, 45, 43, 41, 39, 37, 35,
617 33, 30, 28, 26, 24, 22, 20, 18,
618 15, 13, 11, 9, 7, 4, 2, 0,
619 -1, -3, -6, -8, -10, -12, -14, -17,
620 -19, -21, -23, -25, -27, -29, -32, -34,
621 -36, -38, -40, -42, -44, -46, -48, -50,
622 -52, -54, -56, -58, -60, -62, -64, -66,
623 -68, -70, -71, -73, -75, -77, -78, -80,
624 -82, -83, -85, -87, -88, -90, -91, -93,
625 -94, -96, -97, -98, -100, -101, -102, -104,
626 -105, -106, -107, -108, -109, -111, -112, -113,
627 -113, -114, -115, -116, -117, -118, -118, -119,
628 -120, -120, -121, -122, -122, -123, -123, -124, -124
629};
630
Joe Perches58aa68c2009-09-02 01:12:13 -0300631static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300632 -100, -99, -98, -97, -95, -94, -93, -91,
633 -90, -89, -87, -86, -84, -83, -81, -80,
634 -78, -76, -75, -73, -71, -70, -68, -66,
635 -64, -63, -61, -59, -57, -55, -53, -51,
636 -49, -48, -46, -44, -42, -40, -38, -36,
637 -34, -32, -30, -27, -25, -23, -21, -19,
638 -17, -15, -13, -11, -9, -7, -4, -2,
639 0, 1, 3, 5, 7, 9, 11, 14,
640 16, 18, 20, 22, 24, 26, 28, 30,
641 32, 34, 36, 38, 40, 42, 44, 46,
642 48, 50, 52, 54, 56, 58, 59, 61,
643 63, 65, 67, 68, 70, 72, 74, 75,
644 77, 78, 80, 82, 83, 85, 86, 88,
645 89, 90, 92, 93, 95, 96, 97, 98,
646 100, 101, 102, 103, 104, 105, 106, 107,
647 108, 109, 110, 111, 112, 112, 113, 114,
648 115, 115, 116, 116, 117, 117, 118, 118,
649 119, 119, 119, 120, 120, 120, 120, 120,
650 121, 121, 121, 121, 121, 121, 120, 120,
651 120, 120, 120, 119, 119, 119, 118, 118,
652 117, 117, 116, 116, 115, 114, 114, 113,
653 112, 111, 111, 110, 109, 108, 107, 106,
654 105, 104, 103, 102, 100, 99, 98, 97,
655 95, 94, 93, 91, 90, 89, 87, 86,
656 84, 83, 81, 80, 78, 76, 75, 73,
657 71, 70, 68, 66, 64, 63, 61, 59,
658 57, 55, 53, 51, 49, 48, 46, 44,
659 42, 40, 38, 36, 34, 32, 30, 27,
660 25, 23, 21, 19, 17, 15, 13, 11,
661 9, 7, 4, 2, 0, -1, -3, -5,
662 -7, -9, -11, -14, -16, -18, -20, -22,
663 -24, -26, -28, -30, -32, -34, -36, -38,
664 -40, -42, -44, -46, -48, -50, -52, -54,
665 -56, -58, -59, -61, -63, -65, -67, -68,
666 -70, -72, -74, -75, -77, -78, -80, -82,
667 -83, -85, -86, -88, -89, -90, -92, -93,
668 -95, -96, -97, -98, -100, -101, -102, -103,
669 -104, -105, -106, -107, -108, -109, -110, -111,
670 -112, -112, -113, -114, -115, -115, -116, -116,
671 -117, -117, -118, -118, -119, -119, -119, -120,
672 -120, -120, -120, -120, -121, -121, -121, -121,
673 -121, -121, -120, -120, -120, -120, -120, -119,
674 -119, -119, -118, -118, -117, -117, -116, -116,
675 -115, -114, -114, -113, -112, -111, -111, -110,
676 -109, -108, -107, -106, -105, -104, -103, -102, -100
677};
678
Joe Perches58aa68c2009-09-02 01:12:13 -0300679static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300680 112, 113, 114, 114, 115, 116, 117, 117,
681 118, 118, 119, 119, 120, 120, 120, 121,
682 121, 121, 122, 122, 122, 122, 122, 122,
683 122, 122, 122, 122, 122, 122, 121, 121,
684 121, 120, 120, 120, 119, 119, 118, 118,
685 117, 116, 116, 115, 114, 113, 113, 112,
686 111, 110, 109, 108, 107, 106, 105, 104,
687 103, 102, 100, 99, 98, 97, 95, 94,
688 93, 91, 90, 88, 87, 85, 84, 82,
689 80, 79, 77, 76, 74, 72, 70, 69,
690 67, 65, 63, 61, 60, 58, 56, 54,
691 52, 50, 48, 46, 44, 42, 40, 38,
692 36, 34, 32, 30, 28, 26, 24, 22,
693 19, 17, 15, 13, 11, 9, 7, 5,
694 2, 0, -1, -3, -5, -7, -9, -12,
695 -14, -16, -18, -20, -22, -24, -26, -28,
696 -31, -33, -35, -37, -39, -41, -43, -45,
697 -47, -49, -51, -53, -54, -56, -58, -60,
698 -62, -64, -66, -67, -69, -71, -73, -74,
699 -76, -78, -79, -81, -83, -84, -86, -87,
700 -89, -90, -92, -93, -94, -96, -97, -98,
701 -99, -101, -102, -103, -104, -105, -106, -107,
702 -108, -109, -110, -111, -112, -113, -114, -114,
703 -115, -116, -117, -117, -118, -118, -119, -119,
704 -120, -120, -120, -121, -121, -121, -122, -122,
705 -122, -122, -122, -122, -122, -122, -122, -122,
706 -122, -122, -121, -121, -121, -120, -120, -120,
707 -119, -119, -118, -118, -117, -116, -116, -115,
708 -114, -113, -113, -112, -111, -110, -109, -108,
709 -107, -106, -105, -104, -103, -102, -100, -99,
710 -98, -97, -95, -94, -93, -91, -90, -88,
711 -87, -85, -84, -82, -80, -79, -77, -76,
712 -74, -72, -70, -69, -67, -65, -63, -61,
713 -60, -58, -56, -54, -52, -50, -48, -46,
714 -44, -42, -40, -38, -36, -34, -32, -30,
715 -28, -26, -24, -22, -19, -17, -15, -13,
716 -11, -9, -7, -5, -2, 0, 1, 3,
717 5, 7, 9, 12, 14, 16, 18, 20,
718 22, 24, 26, 28, 31, 33, 35, 37,
719 39, 41, 43, 45, 47, 49, 51, 53,
720 54, 56, 58, 60, 62, 64, 66, 67,
721 69, 71, 73, 74, 76, 78, 79, 81,
722 83, 84, 86, 87, 89, 90, 92, 93,
723 94, 96, 97, 98, 99, 101, 102, 103,
724 104, 105, 106, 107, 108, 109, 110, 111, 112
725};
726
Joe Perches58aa68c2009-09-02 01:12:13 -0300727static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300728 -11, -13, -15, -17, -19, -21, -23, -25,
729 -27, -29, -31, -33, -35, -37, -39, -41,
730 -43, -45, -46, -48, -50, -52, -54, -55,
731 -57, -59, -61, -62, -64, -66, -67, -69,
732 -71, -72, -74, -75, -77, -78, -80, -81,
733 -83, -84, -86, -87, -88, -90, -91, -92,
734 -93, -95, -96, -97, -98, -99, -100, -101,
735 -102, -103, -104, -105, -106, -106, -107, -108,
736 -109, -109, -110, -111, -111, -112, -112, -113,
737 -113, -114, -114, -114, -115, -115, -115, -115,
738 -116, -116, -116, -116, -116, -116, -116, -116,
739 -116, -115, -115, -115, -115, -114, -114, -114,
740 -113, -113, -112, -112, -111, -111, -110, -110,
741 -109, -108, -108, -107, -106, -105, -104, -103,
742 -102, -101, -100, -99, -98, -97, -96, -95,
743 -94, -93, -91, -90, -89, -88, -86, -85,
744 -84, -82, -81, -79, -78, -76, -75, -73,
745 -71, -70, -68, -67, -65, -63, -62, -60,
746 -58, -56, -55, -53, -51, -49, -47, -45,
747 -44, -42, -40, -38, -36, -34, -32, -30,
748 -28, -26, -24, -22, -20, -18, -16, -14,
749 -12, -10, -8, -6, -4, -2, 0, 1,
750 3, 5, 7, 9, 11, 13, 15, 17,
751 19, 21, 23, 25, 27, 29, 31, 33,
752 35, 37, 39, 41, 43, 45, 46, 48,
753 50, 52, 54, 55, 57, 59, 61, 62,
754 64, 66, 67, 69, 71, 72, 74, 75,
755 77, 78, 80, 81, 83, 84, 86, 87,
756 88, 90, 91, 92, 93, 95, 96, 97,
757 98, 99, 100, 101, 102, 103, 104, 105,
758 106, 106, 107, 108, 109, 109, 110, 111,
759 111, 112, 112, 113, 113, 114, 114, 114,
760 115, 115, 115, 115, 116, 116, 116, 116,
761 116, 116, 116, 116, 116, 115, 115, 115,
762 115, 114, 114, 114, 113, 113, 112, 112,
763 111, 111, 110, 110, 109, 108, 108, 107,
764 106, 105, 104, 103, 102, 101, 100, 99,
765 98, 97, 96, 95, 94, 93, 91, 90,
766 89, 88, 86, 85, 84, 82, 81, 79,
767 78, 76, 75, 73, 71, 70, 68, 67,
768 65, 63, 62, 60, 58, 56, 55, 53,
769 51, 49, 47, 45, 44, 42, 40, 38,
770 36, 34, 32, 30, 28, 26, 24, 22,
771 20, 18, 16, 14, 12, 10, 8, 6,
772 4, 2, 0, -1, -3, -5, -7, -9, -11
773};
774
775static u16 i2c_ident[] = {
776 V4L2_IDENT_OV9650,
777 V4L2_IDENT_OV9655,
778 V4L2_IDENT_SOI968,
779 V4L2_IDENT_OV7660,
780 V4L2_IDENT_OV7670,
781 V4L2_IDENT_MT9V011,
782 V4L2_IDENT_MT9V111,
783 V4L2_IDENT_MT9V112,
784 V4L2_IDENT_MT9M001C12ST,
785 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300786 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300787 V4L2_IDENT_HV7131R,
788};
789
790static u16 bridge_init[][2] = {
791 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
792 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
793 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
794 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
795 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
796 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
797 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
798 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
799 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
800 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
801 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
802 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
803 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
804 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
805 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
806 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
807 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
808 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300809 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
810 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300811};
812
813/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
814static u8 ov_gain[] = {
815 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
816 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
817 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
818 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
819 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
820 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
821 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
822 0x70 /* 8x */
823};
824
825/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
826static u16 micron1_gain[] = {
827 /* 1x 1.25x 1.5x 1.75x */
828 0x0020, 0x0028, 0x0030, 0x0038,
829 /* 2x 2.25x 2.5x 2.75x */
830 0x00a0, 0x00a4, 0x00a8, 0x00ac,
831 /* 3x 3.25x 3.5x 3.75x */
832 0x00b0, 0x00b4, 0x00b8, 0x00bc,
833 /* 4x 4.25x 4.5x 4.75x */
834 0x00c0, 0x00c4, 0x00c8, 0x00cc,
835 /* 5x 5.25x 5.5x 5.75x */
836 0x00d0, 0x00d4, 0x00d8, 0x00dc,
837 /* 6x 6.25x 6.5x 6.75x */
838 0x00e0, 0x00e4, 0x00e8, 0x00ec,
839 /* 7x 7.25x 7.5x 7.75x */
840 0x00f0, 0x00f4, 0x00f8, 0x00fc,
841 /* 8x */
842 0x01c0
843};
844
845/* mt9m001 sensor uses a different gain formula then other micron sensors */
846/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
847static u16 micron2_gain[] = {
848 /* 1x 1.25x 1.5x 1.75x */
849 0x0008, 0x000a, 0x000c, 0x000e,
850 /* 2x 2.25x 2.5x 2.75x */
851 0x0010, 0x0012, 0x0014, 0x0016,
852 /* 3x 3.25x 3.5x 3.75x */
853 0x0018, 0x001a, 0x001c, 0x001e,
854 /* 4x 4.25x 4.5x 4.75x */
855 0x0020, 0x0051, 0x0052, 0x0053,
856 /* 5x 5.25x 5.5x 5.75x */
857 0x0054, 0x0055, 0x0056, 0x0057,
858 /* 6x 6.25x 6.5x 6.75x */
859 0x0058, 0x0059, 0x005a, 0x005b,
860 /* 7x 7.25x 7.5x 7.75x */
861 0x005c, 0x005d, 0x005e, 0x005f,
862 /* 8x */
863 0x0060
864};
865
866/* Gain = .5 + bit[7:0] / 16 */
867static u8 hv7131r_gain[] = {
868 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
869 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
870 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
871 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
872 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
873 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
874 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
875 0x78 /* 8x */
876};
877
Joe Perches58aa68c2009-09-02 01:12:13 -0300878static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300879 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
880 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
881 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
882 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
883 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
884 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300885 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300886 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
887 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
888 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
889 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
890};
891
Joe Perches58aa68c2009-09-02 01:12:13 -0300892static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300893 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
894 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
895 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300896 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
897 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
898 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300899 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
900 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
901 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
902};
903
Joe Perches58aa68c2009-09-02 01:12:13 -0300904static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300905 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
906 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
907 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
908 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
909 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
910 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
911 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
912 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
913 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
914 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
915 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
916 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
917 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
918 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
919 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
920 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
921 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
922 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
923 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
924 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
925 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
926 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
927 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
928 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
929 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
930 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
931 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
932 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
933 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
934 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
935 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
936 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
937 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
938 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
939 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
940 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
941 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
942 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
943 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
944 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
945 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
946 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
947 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
948 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
949 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
950 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
951 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
952 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
953 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
954 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
955 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
956 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
957 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
958 {0x93, 0x00},
959};
960
Joe Perches58aa68c2009-09-02 01:12:13 -0300961static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300962 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
963 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
964 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
965 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
966 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
967 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
968 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
969 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
970 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
971 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
972 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
973 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
974 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
975 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
976 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
977 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
978 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
979 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
980 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
981 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
982 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
983 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
984 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
985 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
986 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
987 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
988 {0xaa, 0x92}, {0xab, 0x0a},
989};
990
Joe Perches58aa68c2009-09-02 01:12:13 -0300991static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300992 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
993 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
994 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
995 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
996 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
997 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
998 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
999 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
1000 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
1001 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
1002 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
1003 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
1004 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
1005 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
1006 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
1007 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -03001008 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001009 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
1010 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -03001011 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001012 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
1013 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
1014 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
1015 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -03001016};
1017
Joe Perches58aa68c2009-09-02 01:12:13 -03001018static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001019 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
1020 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
1021 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
1022 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1023 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1024 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1025 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1026 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1027 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1028 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1029 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1030 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1031 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1032 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1033 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1034 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1035};
1036
Joe Perches58aa68c2009-09-02 01:12:13 -03001037static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001038 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001039 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1040 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1041 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1042 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1043 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1044 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001045};
1046
Joe Perches58aa68c2009-09-02 01:12:13 -03001047static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001048 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1049 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1050 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1051 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1052 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1053 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1054 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1055 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1056 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1057 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1058 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1059 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1060 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1061 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1062 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1063 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1064 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1065 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1066 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1067 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1068 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1069 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1070 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1071 {0x06, 0x0029}, {0x05, 0x0009},
1072};
1073
Joe Perches58aa68c2009-09-02 01:12:13 -03001074static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001075 {0x0d, 0x0001},
1076 {0x0d, 0x0000},
1077 {0x04, 0x0500}, /* hres = 1280 */
1078 {0x03, 0x0400}, /* vres = 1024 */
1079 {0x20, 0x1100},
1080 {0x06, 0x0010},
1081 {0x2b, 0x0024},
1082 {0x2e, 0x0024},
1083 {0x35, 0x0024},
1084 {0x2d, 0x0020},
1085 {0x2c, 0x0020},
1086 {0x09, 0x0ad4},
1087 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001088};
1089
Joe Perches58aa68c2009-09-02 01:12:13 -03001090static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001091 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1092 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001093 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1094 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001095};
1096
Brian Johnsone99ac542010-03-16 13:58:28 -03001097static struct i2c_reg_u16 mt9m112_init[] = {
1098 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1099 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1100 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1101 {0xf0, 0x0000},
1102};
1103
Joe Perches58aa68c2009-09-02 01:12:13 -03001104static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001105 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1106 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1107 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1108 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1109 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1110 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1111 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1112 {0x23, 0x09}, {0x01, 0x08},
1113};
1114
Joe Perches58aa68c2009-09-02 01:12:13 -03001115static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001116{
1117 struct usb_device *dev = gspca_dev->dev;
1118 int result;
1119 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1120 0x00,
1121 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1122 reg,
1123 0x00,
1124 gspca_dev->usb_buf,
1125 length,
1126 500);
1127 if (unlikely(result < 0 || result != length)) {
Joe Perches91f58422011-08-21 19:56:55 -03001128 pr_err("Read register failed 0x%02X\n", reg);
Brian Johnson26e744b2009-07-19 05:52:58 -03001129 return -EIO;
1130 }
1131 return 0;
1132}
1133
Joe Perches58aa68c2009-09-02 01:12:13 -03001134static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1135 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001136{
1137 struct usb_device *dev = gspca_dev->dev;
1138 int result;
1139 memcpy(gspca_dev->usb_buf, buffer, length);
1140 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1141 0x08,
1142 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1143 reg,
1144 0x00,
1145 gspca_dev->usb_buf,
1146 length,
1147 500);
1148 if (unlikely(result < 0 || result != length)) {
Joe Perches91f58422011-08-21 19:56:55 -03001149 pr_err("Write register failed index 0x%02X\n", reg);
Brian Johnson26e744b2009-07-19 05:52:58 -03001150 return -EIO;
1151 }
1152 return 0;
1153}
1154
Joe Perches58aa68c2009-09-02 01:12:13 -03001155static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001156{
1157 u8 data[1] = {value};
1158 return reg_w(gspca_dev, reg, data, 1);
1159}
1160
Joe Perches58aa68c2009-09-02 01:12:13 -03001161static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001162{
1163 int i;
1164 reg_w(gspca_dev, 0x10c0, buffer, 8);
1165 for (i = 0; i < 5; i++) {
1166 reg_r(gspca_dev, 0x10c0, 1);
1167 if (gspca_dev->usb_buf[0] & 0x04) {
1168 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001169 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001170 return 0;
1171 }
1172 msleep(1);
1173 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001174 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001175}
1176
Joe Perches58aa68c2009-09-02 01:12:13 -03001177static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001178{
1179 struct sd *sd = (struct sd *) gspca_dev;
1180
1181 u8 row[8];
1182
1183 /*
1184 * from the point of view of the bridge, the length
1185 * includes the address
1186 */
1187 row[0] = 0x81 | (2 << 4);
1188 row[1] = sd->i2c_addr;
1189 row[2] = reg;
1190 row[3] = val;
1191 row[4] = 0x00;
1192 row[5] = 0x00;
1193 row[6] = 0x00;
1194 row[7] = 0x10;
1195
1196 return i2c_w(gspca_dev, row);
1197}
1198
Joe Perches58aa68c2009-09-02 01:12:13 -03001199static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001200{
1201 struct sd *sd = (struct sd *) gspca_dev;
1202 u8 row[8];
1203
1204 /*
1205 * from the point of view of the bridge, the length
1206 * includes the address
1207 */
1208 row[0] = 0x81 | (3 << 4);
1209 row[1] = sd->i2c_addr;
1210 row[2] = reg;
1211 row[3] = (val >> 8) & 0xff;
1212 row[4] = val & 0xff;
1213 row[5] = 0x00;
1214 row[6] = 0x00;
1215 row[7] = 0x10;
1216
1217 return i2c_w(gspca_dev, row);
1218}
1219
Jean-Francois Moine83955552009-12-12 06:58:01 -03001220static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001221{
1222 struct sd *sd = (struct sd *) gspca_dev;
1223 u8 row[8];
1224
Brian Johnson00b581e2009-07-23 05:55:43 -03001225 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001226 row[1] = sd->i2c_addr;
1227 row[2] = reg;
1228 row[3] = 0;
1229 row[4] = 0;
1230 row[5] = 0;
1231 row[6] = 0;
1232 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001233 if (i2c_w(gspca_dev, row) < 0)
1234 return -EIO;
1235 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001236 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001237 if (i2c_w(gspca_dev, row) < 0)
1238 return -EIO;
1239 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1240 return -EIO;
1241 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001242 return 0;
1243}
1244
Jean-Francois Moine83955552009-12-12 06:58:01 -03001245static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001246{
1247 struct sd *sd = (struct sd *) gspca_dev;
1248 u8 row[8];
1249
Brian Johnson00b581e2009-07-23 05:55:43 -03001250 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001251 row[1] = sd->i2c_addr;
1252 row[2] = reg;
1253 row[3] = 0;
1254 row[4] = 0;
1255 row[5] = 0;
1256 row[6] = 0;
1257 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001258 if (i2c_w(gspca_dev, row) < 0)
1259 return -EIO;
1260 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001261 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001262 if (i2c_w(gspca_dev, row) < 0)
1263 return -EIO;
1264 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1265 return -EIO;
1266 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001267 return 0;
1268}
1269
1270static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1271{
1272 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001273 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001274 struct sd *sd = (struct sd *) gspca_dev;
1275
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001276 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1277 return -EINVAL;
1278
1279 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001280 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001281 return -ENODEV;
1282 }
1283
Brian Johnson26e744b2009-07-19 05:52:58 -03001284 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001285 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1286 ov9650_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001287 pr_err("OV9650 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001288 return -ENODEV;
1289 }
1290 }
1291 sd->hstart = 1;
1292 sd->vstart = 7;
1293 return 0;
1294}
1295
1296static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1297{
1298 int i;
1299 struct sd *sd = (struct sd *) gspca_dev;
1300
1301 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001302 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1303 ov9655_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001304 pr_err("OV9655 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001305 return -ENODEV;
1306 }
1307 }
1308 /* disable hflip and vflip */
1309 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001310 sd->hstart = 1;
1311 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001312 return 0;
1313}
1314
1315static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1316{
1317 int i;
1318 struct sd *sd = (struct sd *) gspca_dev;
1319
1320 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001321 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1322 soi968_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001323 pr_err("SOI968 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001324 return -ENODEV;
1325 }
1326 }
1327 /* disable hflip and vflip */
Jean-François Moine780e3122010-10-19 04:29:10 -03001328 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1329 | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001330 sd->hstart = 60;
1331 sd->vstart = 11;
1332 return 0;
1333}
1334
1335static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1336{
1337 int i;
1338 struct sd *sd = (struct sd *) gspca_dev;
1339
1340 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001341 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1342 ov7660_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001343 pr_err("OV7660 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001344 return -ENODEV;
1345 }
1346 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001347 sd->hstart = 3;
1348 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001349 return 0;
1350}
1351
1352static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1353{
1354 int i;
1355 struct sd *sd = (struct sd *) gspca_dev;
1356
1357 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001358 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1359 ov7670_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001360 pr_err("OV7670 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001361 return -ENODEV;
1362 }
1363 }
1364 /* disable hflip and vflip */
1365 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1366 sd->hstart = 0;
1367 sd->vstart = 1;
1368 return 0;
1369}
1370
1371static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1372{
1373 struct sd *sd = (struct sd *) gspca_dev;
1374 int i;
1375 u16 value;
1376 int ret;
1377
1378 sd->i2c_addr = 0x5d;
1379 ret = i2c_r2(gspca_dev, 0xff, &value);
1380 if ((ret == 0) && (value == 0x8243)) {
1381 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001382 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1383 mt9v011_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001384 pr_err("MT9V011 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001385 return -ENODEV;
1386 }
1387 }
1388 sd->hstart = 2;
1389 sd->vstart = 2;
1390 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001391 pr_info("MT9V011 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001392 return 0;
1393 }
1394
1395 sd->i2c_addr = 0x5c;
1396 i2c_w2(gspca_dev, 0x01, 0x0004);
1397 ret = i2c_r2(gspca_dev, 0xff, &value);
1398 if ((ret == 0) && (value == 0x823a)) {
1399 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001400 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1401 mt9v111_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001402 pr_err("MT9V111 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001403 return -ENODEV;
1404 }
1405 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001406 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1407 | (1 << AUTOGAIN_IDX)
1408 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001409 sd->hstart = 2;
1410 sd->vstart = 2;
1411 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001412 pr_info("MT9V111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001413 return 0;
1414 }
1415
1416 sd->i2c_addr = 0x5d;
1417 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1418 if (ret < 0) {
1419 sd->i2c_addr = 0x48;
1420 i2c_w2(gspca_dev, 0xf0, 0x0000);
1421 }
1422 ret = i2c_r2(gspca_dev, 0x00, &value);
1423 if ((ret == 0) && (value == 0x1229)) {
1424 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001425 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1426 mt9v112_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001427 pr_err("MT9V112 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001428 return -ENODEV;
1429 }
1430 }
1431 sd->hstart = 6;
1432 sd->vstart = 2;
1433 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001434 pr_info("MT9V112 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001435 return 0;
1436 }
1437
1438 return -ENODEV;
1439}
1440
Brian Johnsone99ac542010-03-16 13:58:28 -03001441static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444 int i;
1445 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1446 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1447 mt9m112_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001448 pr_err("MT9M112 sensor initialization failed\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001449 return -ENODEV;
1450 }
1451 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001452 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1453 | (1 << GAIN_IDX);
Brian Johnsone99ac542010-03-16 13:58:28 -03001454 sd->hstart = 0;
1455 sd->vstart = 2;
1456 return 0;
1457}
1458
Brian Johnson26e744b2009-07-19 05:52:58 -03001459static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1460{
1461 struct sd *sd = (struct sd *) gspca_dev;
1462 int i;
1463 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001464 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1465 mt9m111_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001466 pr_err("MT9M111 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001467 return -ENODEV;
1468 }
1469 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001470 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1471 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001472 sd->hstart = 0;
1473 sd->vstart = 2;
1474 return 0;
1475}
1476
1477static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1478{
1479 struct sd *sd = (struct sd *) gspca_dev;
1480 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001481 u16 id;
1482
1483 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1484 return -EINVAL;
1485
1486 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1487 switch (id) {
1488 case 0x8411:
1489 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001490 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001491 break;
1492 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001493 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001494 break;
1495 default:
Joe Perches91f58422011-08-21 19:56:55 -03001496 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001497 return -ENODEV;
1498 }
1499
Brian Johnson26e744b2009-07-19 05:52:58 -03001500 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001501 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1502 mt9m001_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001503 pr_err("MT9M001 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001504 return -ENODEV;
1505 }
1506 }
1507 /* disable hflip and vflip */
1508 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001509 sd->hstart = 1;
1510 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001511 return 0;
1512}
1513
1514static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1515{
1516 int i;
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001520 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1521 hv7131r_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001522 pr_err("HV7131R Sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001523 return -ENODEV;
1524 }
1525 }
1526 sd->hstart = 0;
1527 sd->vstart = 1;
1528 return 0;
1529}
1530
Brian Johnson26e744b2009-07-19 05:52:58 -03001531static int set_cmatrix(struct gspca_dev *gspca_dev)
1532{
1533 struct sd *sd = (struct sd *) gspca_dev;
1534 s32 hue_coord, hue_index = 180 + sd->hue;
1535 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001536
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001537 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001538 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1539 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1540 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1541 cmatrix[18] = sd->brightness - 0x80;
1542
1543 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001544 cmatrix[6] = hue_coord;
1545 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001546
1547 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001548 cmatrix[8] = hue_coord;
1549 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001550
1551 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001552 cmatrix[10] = hue_coord;
1553 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001554
1555 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001556 cmatrix[12] = hue_coord;
1557 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001558
1559 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001560 cmatrix[14] = hue_coord;
1561 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001562
1563 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001564 cmatrix[16] = hue_coord;
1565 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001566
1567 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1568}
1569
1570static int set_gamma(struct gspca_dev *gspca_dev)
1571{
1572 struct sd *sd = (struct sd *) gspca_dev;
1573 u8 gamma[17];
1574 u8 gval = sd->gamma * 0xb8 / 0x100;
1575
1576
1577 gamma[0] = 0x0a;
1578 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1579 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1580 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1581 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1582 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1583 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1584 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1585 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1586 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1587 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1588 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1589 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1590 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1591 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1592 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1593 gamma[16] = 0xf5;
1594
1595 return reg_w(gspca_dev, 0x1190, gamma, 17);
1596}
1597
1598static int set_redblue(struct gspca_dev *gspca_dev)
1599{
1600 struct sd *sd = (struct sd *) gspca_dev;
1601 reg_w1(gspca_dev, 0x118c, sd->red);
1602 reg_w1(gspca_dev, 0x118f, sd->blue);
1603 return 0;
1604}
1605
1606static int set_hvflip(struct gspca_dev *gspca_dev)
1607{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001608 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001609 u16 value2;
1610 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001611
1612 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1613 hflip = !sd->hflip;
1614 vflip = !sd->vflip;
1615 } else {
1616 hflip = sd->hflip;
1617 vflip = sd->vflip;
1618 }
1619
Brian Johnson26e744b2009-07-19 05:52:58 -03001620 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001621 case SENSOR_OV7660:
1622 value = 0x01;
1623 if (hflip)
1624 value |= 0x20;
1625 if (vflip) {
1626 value |= 0x10;
1627 sd->vstart = 2;
1628 } else
1629 sd->vstart = 3;
1630 reg_w1(gspca_dev, 0x1182, sd->vstart);
1631 i2c_w1(gspca_dev, 0x1e, value);
1632 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001633 case SENSOR_OV9650:
1634 i2c_r1(gspca_dev, 0x1e, &value);
1635 value &= ~0x30;
1636 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001637 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001638 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001639 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001640 value |= 0x10;
1641 tslb = 0x49;
1642 }
1643 i2c_w1(gspca_dev, 0x1e, value);
1644 i2c_w1(gspca_dev, 0x3a, tslb);
1645 break;
1646 case SENSOR_MT9V111:
1647 case SENSOR_MT9V011:
1648 i2c_r2(gspca_dev, 0x20, &value2);
1649 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001650 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001651 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001652 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001653 value2 |= 0x4020;
1654 i2c_w2(gspca_dev, 0x20, value2);
1655 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001656 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001657 case SENSOR_MT9M111:
1658 case SENSOR_MT9V112:
1659 i2c_r2(gspca_dev, 0x20, &value2);
1660 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001661 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001662 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001663 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001664 value2 |= 0x0001;
1665 i2c_w2(gspca_dev, 0x20, value2);
1666 break;
1667 case SENSOR_HV7131R:
1668 i2c_r1(gspca_dev, 0x01, &value);
1669 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001670 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001671 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001672 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001673 value |= 0x02;
1674 i2c_w1(gspca_dev, 0x01, value);
1675 break;
1676 }
1677 return 0;
1678}
1679
1680static int set_exposure(struct gspca_dev *gspca_dev)
1681{
1682 struct sd *sd = (struct sd *) gspca_dev;
1683 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1684 switch (sd->sensor) {
1685 case SENSOR_OV7660:
1686 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001687 case SENSOR_OV9655:
1688 case SENSOR_OV9650:
1689 exp[0] |= (3 << 4);
1690 exp[2] = 0x2d;
1691 exp[3] = sd->exposure & 0xff;
1692 exp[4] = sd->exposure >> 8;
1693 break;
1694 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001695 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001696 case SENSOR_MT9V011:
1697 exp[0] |= (3 << 4);
1698 exp[2] = 0x09;
1699 exp[3] = sd->exposure >> 8;
1700 exp[4] = sd->exposure & 0xff;
1701 break;
1702 case SENSOR_HV7131R:
1703 exp[0] |= (4 << 4);
1704 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001705 exp[3] = (sd->exposure >> 5) & 0xff;
1706 exp[4] = (sd->exposure << 3) & 0xff;
1707 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001708 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001709 default:
1710 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001711 }
1712 i2c_w(gspca_dev, exp);
1713 return 0;
1714}
1715
1716static int set_gain(struct gspca_dev *gspca_dev)
1717{
1718 struct sd *sd = (struct sd *) gspca_dev;
1719 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1720 switch (sd->sensor) {
1721 case SENSOR_OV7660:
1722 case SENSOR_OV7670:
1723 case SENSOR_SOI968:
1724 case SENSOR_OV9655:
1725 case SENSOR_OV9650:
1726 gain[0] |= (2 << 4);
1727 gain[3] = ov_gain[sd->gain];
1728 break;
1729 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001730 gain[0] |= (3 << 4);
1731 gain[2] = 0x35;
1732 gain[3] = micron1_gain[sd->gain] >> 8;
1733 gain[4] = micron1_gain[sd->gain] & 0xff;
1734 break;
1735 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001736 gain[0] |= (3 << 4);
1737 gain[2] = 0x2f;
1738 gain[3] = micron1_gain[sd->gain] >> 8;
1739 gain[4] = micron1_gain[sd->gain] & 0xff;
1740 break;
1741 case SENSOR_MT9M001:
1742 gain[0] |= (3 << 4);
1743 gain[2] = 0x2f;
1744 gain[3] = micron2_gain[sd->gain] >> 8;
1745 gain[4] = micron2_gain[sd->gain] & 0xff;
1746 break;
1747 case SENSOR_HV7131R:
1748 gain[0] |= (2 << 4);
1749 gain[2] = 0x30;
1750 gain[3] = hv7131r_gain[sd->gain];
1751 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001752 default:
1753 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001754 }
1755 i2c_w(gspca_dev, gain);
1756 return 0;
1757}
1758
1759static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1760{
1761 struct sd *sd = (struct sd *) gspca_dev;
1762
1763 sd->brightness = val;
1764 if (gspca_dev->streaming)
1765 return set_cmatrix(gspca_dev);
1766 return 0;
1767}
1768
1769static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1770{
1771 struct sd *sd = (struct sd *) gspca_dev;
1772 *val = sd->brightness;
1773 return 0;
1774}
1775
1776
1777static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1778{
1779 struct sd *sd = (struct sd *) gspca_dev;
1780
1781 sd->contrast = val;
1782 if (gspca_dev->streaming)
1783 return set_cmatrix(gspca_dev);
1784 return 0;
1785}
1786
1787static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1788{
1789 struct sd *sd = (struct sd *) gspca_dev;
1790 *val = sd->contrast;
1791 return 0;
1792}
1793
1794static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1795{
1796 struct sd *sd = (struct sd *) gspca_dev;
1797
1798 sd->saturation = val;
1799 if (gspca_dev->streaming)
1800 return set_cmatrix(gspca_dev);
1801 return 0;
1802}
1803
1804static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1805{
1806 struct sd *sd = (struct sd *) gspca_dev;
1807 *val = sd->saturation;
1808 return 0;
1809}
1810
1811static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1812{
1813 struct sd *sd = (struct sd *) gspca_dev;
1814
1815 sd->hue = val;
1816 if (gspca_dev->streaming)
1817 return set_cmatrix(gspca_dev);
1818 return 0;
1819}
1820
1821static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1822{
1823 struct sd *sd = (struct sd *) gspca_dev;
1824 *val = sd->hue;
1825 return 0;
1826}
1827
1828static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1829{
1830 struct sd *sd = (struct sd *) gspca_dev;
1831
1832 sd->gamma = val;
1833 if (gspca_dev->streaming)
1834 return set_gamma(gspca_dev);
1835 return 0;
1836}
1837
1838static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1839{
1840 struct sd *sd = (struct sd *) gspca_dev;
1841 *val = sd->gamma;
1842 return 0;
1843}
1844
1845static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1846{
1847 struct sd *sd = (struct sd *) gspca_dev;
1848
1849 sd->red = val;
1850 if (gspca_dev->streaming)
1851 return set_redblue(gspca_dev);
1852 return 0;
1853}
1854
1855static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1856{
1857 struct sd *sd = (struct sd *) gspca_dev;
1858 *val = sd->red;
1859 return 0;
1860}
1861
1862static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1863{
1864 struct sd *sd = (struct sd *) gspca_dev;
1865
1866 sd->blue = val;
1867 if (gspca_dev->streaming)
1868 return set_redblue(gspca_dev);
1869 return 0;
1870}
1871
1872static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1873{
1874 struct sd *sd = (struct sd *) gspca_dev;
1875 *val = sd->blue;
1876 return 0;
1877}
1878
1879static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1880{
1881 struct sd *sd = (struct sd *) gspca_dev;
1882
1883 sd->hflip = val;
1884 if (gspca_dev->streaming)
1885 return set_hvflip(gspca_dev);
1886 return 0;
1887}
1888
1889static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1890{
1891 struct sd *sd = (struct sd *) gspca_dev;
1892 *val = sd->hflip;
1893 return 0;
1894}
1895
1896static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1897{
1898 struct sd *sd = (struct sd *) gspca_dev;
1899
1900 sd->vflip = val;
1901 if (gspca_dev->streaming)
1902 return set_hvflip(gspca_dev);
1903 return 0;
1904}
1905
1906static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1907{
1908 struct sd *sd = (struct sd *) gspca_dev;
1909 *val = sd->vflip;
1910 return 0;
1911}
1912
1913static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1914{
1915 struct sd *sd = (struct sd *) gspca_dev;
1916
1917 sd->exposure = val;
1918 if (gspca_dev->streaming)
1919 return set_exposure(gspca_dev);
1920 return 0;
1921}
1922
1923static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1924{
1925 struct sd *sd = (struct sd *) gspca_dev;
1926 *val = sd->exposure;
1927 return 0;
1928}
1929
1930static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1931{
1932 struct sd *sd = (struct sd *) gspca_dev;
1933
1934 sd->gain = val;
1935 if (gspca_dev->streaming)
1936 return set_gain(gspca_dev);
1937 return 0;
1938}
1939
1940static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1941{
1942 struct sd *sd = (struct sd *) gspca_dev;
1943 *val = sd->gain;
1944 return 0;
1945}
1946
1947static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1948{
1949 struct sd *sd = (struct sd *) gspca_dev;
1950 sd->auto_exposure = val;
1951 return 0;
1952}
1953
1954static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1955{
1956 struct sd *sd = (struct sd *) gspca_dev;
1957 *val = sd->auto_exposure;
1958 return 0;
1959}
1960
1961#ifdef CONFIG_VIDEO_ADV_DEBUG
1962static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1963 struct v4l2_dbg_register *reg)
1964{
1965 struct sd *sd = (struct sd *) gspca_dev;
1966 switch (reg->match.type) {
1967 case V4L2_CHIP_MATCH_HOST:
1968 if (reg->match.addr != 0)
1969 return -EINVAL;
1970 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1971 return -EINVAL;
1972 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1973 return -EINVAL;
1974 reg->val = gspca_dev->usb_buf[0];
1975 return 0;
1976 case V4L2_CHIP_MATCH_I2C_ADDR:
1977 if (reg->match.addr != sd->i2c_addr)
1978 return -EINVAL;
1979 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001980 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001981 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1982 return -EINVAL;
1983 } else {
1984 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1985 return -EINVAL;
1986 }
1987 return 0;
1988 }
1989 return -EINVAL;
1990}
1991
1992static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1993 struct v4l2_dbg_register *reg)
1994{
1995 struct sd *sd = (struct sd *) gspca_dev;
1996 switch (reg->match.type) {
1997 case V4L2_CHIP_MATCH_HOST:
1998 if (reg->match.addr != 0)
1999 return -EINVAL;
2000 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
2001 return -EINVAL;
2002 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
2003 return -EINVAL;
2004 return 0;
2005 case V4L2_CHIP_MATCH_I2C_ADDR:
2006 if (reg->match.addr != sd->i2c_addr)
2007 return -EINVAL;
2008 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03002009 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002010 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
2011 return -EINVAL;
2012 } else {
2013 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
2014 return -EINVAL;
2015 }
2016 return 0;
2017 }
2018 return -EINVAL;
2019}
2020#endif
2021
2022static int sd_chip_ident(struct gspca_dev *gspca_dev,
2023 struct v4l2_dbg_chip_ident *chip)
2024{
2025 struct sd *sd = (struct sd *) gspca_dev;
2026
2027 switch (chip->match.type) {
2028 case V4L2_CHIP_MATCH_HOST:
2029 if (chip->match.addr != 0)
2030 return -EINVAL;
2031 chip->revision = 0;
2032 chip->ident = V4L2_IDENT_SN9C20X;
2033 return 0;
2034 case V4L2_CHIP_MATCH_I2C_ADDR:
2035 if (chip->match.addr != sd->i2c_addr)
2036 return -EINVAL;
2037 chip->revision = 0;
2038 chip->ident = i2c_ident[sd->sensor];
2039 return 0;
2040 }
2041 return -EINVAL;
2042}
2043
2044static int sd_config(struct gspca_dev *gspca_dev,
2045 const struct usb_device_id *id)
2046{
2047 struct sd *sd = (struct sd *) gspca_dev;
2048 struct cam *cam;
2049
2050 cam = &gspca_dev->cam;
2051
2052 sd->sensor = (id->driver_info >> 8) & 0xff;
2053 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002054 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03002055
2056 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03002057 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002058 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03002059 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002060 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03002061 cam->cam_mode = sxga_mode;
2062 cam->nmodes = ARRAY_SIZE(sxga_mode);
2063 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03002064 case SENSOR_MT9M001:
2065 cam->cam_mode = mono_mode;
2066 cam->nmodes = ARRAY_SIZE(mono_mode);
2067 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002068 default:
2069 cam->cam_mode = vga_mode;
2070 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002071 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002072 }
2073
2074 sd->old_step = 0;
2075 sd->older_step = 0;
2076 sd->exposure_step = 16;
2077
2078 sd->brightness = BRIGHTNESS_DEFAULT;
2079 sd->contrast = CONTRAST_DEFAULT;
2080 sd->saturation = SATURATION_DEFAULT;
2081 sd->hue = HUE_DEFAULT;
2082 sd->gamma = GAMMA_DEFAULT;
2083 sd->red = RED_DEFAULT;
2084 sd->blue = BLUE_DEFAULT;
2085
2086 sd->hflip = HFLIP_DEFAULT;
2087 sd->vflip = VFLIP_DEFAULT;
2088 sd->exposure = EXPOSURE_DEFAULT;
2089 sd->gain = GAIN_DEFAULT;
2090 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2091
2092 sd->quality = 95;
2093
Brian Johnson26e744b2009-07-19 05:52:58 -03002094 return 0;
2095}
2096
2097static int sd_init(struct gspca_dev *gspca_dev)
2098{
2099 struct sd *sd = (struct sd *) gspca_dev;
2100 int i;
2101 u8 value;
2102 u8 i2c_init[9] =
2103 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2104
2105 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2106 value = bridge_init[i][1];
2107 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03002108 pr_err("Device initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002109 return -ENODEV;
2110 }
2111 }
2112
Brian Johnson0c045eb2010-03-16 13:58:27 -03002113 if (sd->flags & LED_REVERSE)
2114 reg_w1(gspca_dev, 0x1006, 0x00);
2115 else
2116 reg_w1(gspca_dev, 0x1006, 0x20);
2117
Brian Johnson26e744b2009-07-19 05:52:58 -03002118 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03002119 pr_err("Device initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002120 return -ENODEV;
2121 }
2122
2123 switch (sd->sensor) {
2124 case SENSOR_OV9650:
2125 if (ov9650_init_sensor(gspca_dev) < 0)
2126 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002127 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002128 break;
2129 case SENSOR_OV9655:
2130 if (ov9655_init_sensor(gspca_dev) < 0)
2131 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002132 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002133 break;
2134 case SENSOR_SOI968:
2135 if (soi968_init_sensor(gspca_dev) < 0)
2136 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002137 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002138 break;
2139 case SENSOR_OV7660:
2140 if (ov7660_init_sensor(gspca_dev) < 0)
2141 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002142 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002143 break;
2144 case SENSOR_OV7670:
2145 if (ov7670_init_sensor(gspca_dev) < 0)
2146 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002147 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002148 break;
2149 case SENSOR_MT9VPRB:
2150 if (mt9v_init_sensor(gspca_dev) < 0)
2151 return -ENODEV;
2152 break;
2153 case SENSOR_MT9M111:
2154 if (mt9m111_init_sensor(gspca_dev) < 0)
2155 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002156 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002157 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002158 case SENSOR_MT9M112:
2159 if (mt9m112_init_sensor(gspca_dev) < 0)
2160 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002161 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03002162 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002163 case SENSOR_MT9M001:
2164 if (mt9m001_init_sensor(gspca_dev) < 0)
2165 return -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03002166 break;
2167 case SENSOR_HV7131R:
2168 if (hv7131r_init_sensor(gspca_dev) < 0)
2169 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03002170 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002171 break;
2172 default:
Joe Perches91f58422011-08-21 19:56:55 -03002173 pr_info("Unsupported Sensor\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002174 return -ENODEV;
2175 }
2176
2177 return 0;
2178}
2179
2180static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2181{
2182 struct sd *sd = (struct sd *) gspca_dev;
2183 u8 value;
2184 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002185 case SENSOR_SOI968:
2186 if (mode & MODE_SXGA) {
2187 i2c_w1(gspca_dev, 0x17, 0x1d);
2188 i2c_w1(gspca_dev, 0x18, 0xbd);
2189 i2c_w1(gspca_dev, 0x19, 0x01);
2190 i2c_w1(gspca_dev, 0x1a, 0x81);
2191 i2c_w1(gspca_dev, 0x12, 0x00);
2192 sd->hstart = 140;
2193 sd->vstart = 19;
2194 } else {
2195 i2c_w1(gspca_dev, 0x17, 0x13);
2196 i2c_w1(gspca_dev, 0x18, 0x63);
2197 i2c_w1(gspca_dev, 0x19, 0x01);
2198 i2c_w1(gspca_dev, 0x1a, 0x79);
2199 i2c_w1(gspca_dev, 0x12, 0x40);
2200 sd->hstart = 60;
2201 sd->vstart = 11;
2202 }
2203 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002204 case SENSOR_OV9650:
2205 if (mode & MODE_SXGA) {
2206 i2c_w1(gspca_dev, 0x17, 0x1b);
2207 i2c_w1(gspca_dev, 0x18, 0xbc);
2208 i2c_w1(gspca_dev, 0x19, 0x01);
2209 i2c_w1(gspca_dev, 0x1a, 0x82);
2210 i2c_r1(gspca_dev, 0x12, &value);
2211 i2c_w1(gspca_dev, 0x12, value & 0x07);
2212 } else {
2213 i2c_w1(gspca_dev, 0x17, 0x24);
2214 i2c_w1(gspca_dev, 0x18, 0xc5);
2215 i2c_w1(gspca_dev, 0x19, 0x00);
2216 i2c_w1(gspca_dev, 0x1a, 0x3c);
2217 i2c_r1(gspca_dev, 0x12, &value);
2218 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2219 }
2220 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002221 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002222 case SENSOR_MT9M111:
2223 if (mode & MODE_SXGA) {
2224 i2c_w2(gspca_dev, 0xf0, 0x0002);
2225 i2c_w2(gspca_dev, 0xc8, 0x970b);
2226 i2c_w2(gspca_dev, 0xf0, 0x0000);
2227 } else {
2228 i2c_w2(gspca_dev, 0xf0, 0x0002);
2229 i2c_w2(gspca_dev, 0xc8, 0x8000);
2230 i2c_w2(gspca_dev, 0xf0, 0x0000);
2231 }
2232 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002233 }
2234}
2235
2236#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002237((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002238(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2239(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2240
2241#define CLR_WIN(width, height) \
2242((const u8 [])\
2243{0, width >> 2, 0, height >> 1,\
2244((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2245
2246static int sd_start(struct gspca_dev *gspca_dev)
2247{
2248 struct sd *sd = (struct sd *) gspca_dev;
2249 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2250 int width = gspca_dev->width;
2251 int height = gspca_dev->height;
2252 u8 fmt, scale = 0;
2253
Brian Johnson26e744b2009-07-19 05:52:58 -03002254 jpeg_define(sd->jpeg_hdr, height, width,
2255 0x21);
2256 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2257
2258 if (mode & MODE_RAW)
2259 fmt = 0x2d;
2260 else if (mode & MODE_JPEG)
2261 fmt = 0x2c;
2262 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002263 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002264
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002265 switch (mode & SCALE_MASK) {
2266 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002267 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002268 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002269 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002270 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002271 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002272 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002273 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002274 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002275 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002276 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002277 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002278 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002279 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002280 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002281 break;
2282 }
2283
2284 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002285 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2286 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002287 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2288 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2289 reg_w1(gspca_dev, 0x1189, scale);
2290 reg_w1(gspca_dev, 0x10e0, fmt);
2291
2292 set_cmatrix(gspca_dev);
2293 set_gamma(gspca_dev);
2294 set_redblue(gspca_dev);
2295 set_gain(gspca_dev);
2296 set_exposure(gspca_dev);
2297 set_hvflip(gspca_dev);
2298
Brian Johnson0c045eb2010-03-16 13:58:27 -03002299 reg_w1(gspca_dev, 0x1007, 0x20);
2300
Brian Johnson26e744b2009-07-19 05:52:58 -03002301 reg_r(gspca_dev, 0x1061, 1);
2302 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2303 return 0;
2304}
2305
2306static void sd_stopN(struct gspca_dev *gspca_dev)
2307{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002308 reg_w1(gspca_dev, 0x1007, 0x00);
2309
Brian Johnson26e744b2009-07-19 05:52:58 -03002310 reg_r(gspca_dev, 0x1061, 1);
2311 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2312}
2313
Brian Johnsone1430472009-09-02 12:39:41 -03002314static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002315{
2316 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002317 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002318
2319 /*
2320 * some hardcoded values are present
2321 * like those for maximal/minimal exposure
2322 * and exposure steps
2323 */
2324 if (avg_lum < MIN_AVG_LUM) {
2325 if (sd->exposure > 0x1770)
2326 return;
2327
2328 new_exp = sd->exposure + sd->exposure_step;
2329 if (new_exp > 0x1770)
2330 new_exp = 0x1770;
2331 if (new_exp < 0x10)
2332 new_exp = 0x10;
2333 sd->exposure = new_exp;
2334 set_exposure(gspca_dev);
2335
2336 sd->older_step = sd->old_step;
2337 sd->old_step = 1;
2338
2339 if (sd->old_step ^ sd->older_step)
2340 sd->exposure_step /= 2;
2341 else
2342 sd->exposure_step += 2;
2343 }
2344 if (avg_lum > MAX_AVG_LUM) {
2345 if (sd->exposure < 0x10)
2346 return;
2347 new_exp = sd->exposure - sd->exposure_step;
2348 if (new_exp > 0x1700)
2349 new_exp = 0x1770;
2350 if (new_exp < 0x10)
2351 new_exp = 0x10;
2352 sd->exposure = new_exp;
2353 set_exposure(gspca_dev);
2354 sd->older_step = sd->old_step;
2355 sd->old_step = 0;
2356
2357 if (sd->old_step ^ sd->older_step)
2358 sd->exposure_step /= 2;
2359 else
2360 sd->exposure_step += 2;
2361 }
2362}
2363
Brian Johnsone1430472009-09-02 12:39:41 -03002364static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2365{
2366 struct sd *sd = (struct sd *) gspca_dev;
2367
2368 if (avg_lum < MIN_AVG_LUM) {
2369 if (sd->gain + 1 <= 28) {
2370 sd->gain++;
2371 set_gain(gspca_dev);
2372 }
2373 }
2374 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002375 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002376 sd->gain--;
2377 set_gain(gspca_dev);
2378 }
2379 }
2380}
2381
2382static void sd_dqcallback(struct gspca_dev *gspca_dev)
2383{
2384 struct sd *sd = (struct sd *) gspca_dev;
2385 int avg_lum;
2386
2387 if (!sd->auto_exposure)
2388 return;
2389
2390 avg_lum = atomic_read(&sd->avg_lum);
2391 if (sd->sensor == SENSOR_SOI968)
2392 do_autogain(gspca_dev, avg_lum);
2393 else
2394 do_autoexposure(gspca_dev, avg_lum);
2395}
2396
Jean-François Moine28566432010-10-01 07:33:26 -03002397#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002398static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2399 u8 *data, /* interrupt packet */
2400 int len) /* interrupt packet length */
2401{
2402 struct sd *sd = (struct sd *) gspca_dev;
2403 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002404 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002405 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2406 input_sync(gspca_dev->input_dev);
2407 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2408 input_sync(gspca_dev->input_dev);
2409 ret = 0;
2410 }
2411 return ret;
2412}
2413#endif
2414
Brian Johnson26e744b2009-07-19 05:52:58 -03002415static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002416 u8 *data, /* isoc packet */
2417 int len) /* iso packet length */
2418{
2419 struct sd *sd = (struct sd *) gspca_dev;
2420 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002421 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002422 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2423 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2424 avg_lum = ((data[35] >> 2) & 3) |
2425 (data[20] << 2) |
2426 (data[19] << 10);
2427 avg_lum += ((data[35] >> 4) & 3) |
2428 (data[22] << 2) |
2429 (data[21] << 10);
2430 avg_lum += ((data[35] >> 6) & 3) |
2431 (data[24] << 2) |
2432 (data[23] << 10);
2433 avg_lum += (data[36] & 3) |
2434 (data[26] << 2) |
2435 (data[25] << 10);
2436 avg_lum += ((data[36] >> 2) & 3) |
2437 (data[28] << 2) |
2438 (data[27] << 10);
2439 avg_lum += ((data[36] >> 4) & 3) |
2440 (data[30] << 2) |
2441 (data[29] << 10);
2442 avg_lum += ((data[36] >> 6) & 3) |
2443 (data[32] << 2) |
2444 (data[31] << 10);
2445 avg_lum += ((data[44] >> 4) & 3) |
2446 (data[34] << 2) |
2447 (data[33] << 10);
2448 avg_lum >>= 9;
2449 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002450 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Brian Johnson26e744b2009-07-19 05:52:58 -03002451 return;
2452 }
2453 if (gspca_dev->last_packet_type == LAST_PACKET) {
2454 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2455 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002456 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002457 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002458 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002459 data, len);
2460 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002461 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002462 data, len);
2463 }
2464 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002465 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002466 }
2467}
2468
2469/* sub-driver description */
2470static const struct sd_desc sd_desc = {
2471 .name = MODULE_NAME,
2472 .ctrls = sd_ctrls,
2473 .nctrls = ARRAY_SIZE(sd_ctrls),
2474 .config = sd_config,
2475 .init = sd_init,
2476 .start = sd_start,
2477 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002478 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002479#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002480 .int_pkt_scan = sd_int_pkt_scan,
2481#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002482 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002483#ifdef CONFIG_VIDEO_ADV_DEBUG
2484 .set_register = sd_dbg_s_register,
2485 .get_register = sd_dbg_g_register,
2486#endif
2487 .get_chip_ident = sd_chip_ident,
2488};
2489
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002490#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002491 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002492 | (SENSOR_ ## sensor << 8) \
2493 | (i2c_addr)
2494
Jean-François Moine95c967c2011-01-13 05:20:29 -03002495static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002496 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2497 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2498 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002499 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002500 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2501 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2502 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002503 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2504 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2505 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2506 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002507 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002508 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2509 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2510 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2511 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002512 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002513 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002514 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2515 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2516 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2517 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2518 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002519 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002520 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2521 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2522 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2523 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002524 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2525 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002526 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2527 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2528 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2529 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002530 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002531 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2532 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2533 {}
2534};
2535MODULE_DEVICE_TABLE(usb, device_table);
2536
2537/* -- device connect -- */
2538static int sd_probe(struct usb_interface *intf,
2539 const struct usb_device_id *id)
2540{
2541 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2542 THIS_MODULE);
2543}
2544
Brian Johnson26e744b2009-07-19 05:52:58 -03002545static struct usb_driver sd_driver = {
2546 .name = MODULE_NAME,
2547 .id_table = device_table,
2548 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002549 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002550#ifdef CONFIG_PM
2551 .suspend = gspca_suspend,
2552 .resume = gspca_resume,
2553 .reset_resume = gspca_resume,
2554#endif
2555};
2556
2557/* -- module insert / remove -- */
2558static int __init sd_mod_init(void)
2559{
Jean-François Moine54826432010-09-13 04:53:03 -03002560 return usb_register(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002561}
2562static void __exit sd_mod_exit(void)
2563{
2564 usb_deregister(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002565}
2566
2567module_init(sd_mod_init);
2568module_exit(sd_mod_exit);