blob: 52f44a5c1b2f3c77b055dbb5108fc6e3abfbb635 [file] [log] [blame]
Brian Johnson26e744b2009-07-19 05:52:58 -03001/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Brian Johnson26e744b2009-07-19 05:52:58 -030021#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030022
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030023#include "gspca.h"
24#include "jpeg.h"
25
26#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030027#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030028
Brian Johnson26e744b2009-07-19 05:52:58 -030029MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
30 "microdia project <microdia@googlegroups.com>");
31MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34#define MODULE_NAME "sn9c20x"
35
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -030036/*
37 * Pixel format private data
38 */
39#define SCALE_MASK 0x0f
40#define SCALE_160x120 0
41#define SCALE_320x240 1
42#define SCALE_640x480 2
43#define SCALE_1280x1024 3
Brian Johnson26e744b2009-07-19 05:52:58 -030044#define MODE_RAW 0x10
45#define MODE_JPEG 0x20
46#define MODE_SXGA 0x80
47
48#define SENSOR_OV9650 0
49#define SENSOR_OV9655 1
50#define SENSOR_SOI968 2
51#define SENSOR_OV7660 3
52#define SENSOR_OV7670 4
53#define SENSOR_MT9V011 5
54#define SENSOR_MT9V111 6
55#define SENSOR_MT9V112 7
56#define SENSOR_MT9M001 8
57#define SENSOR_MT9M111 9
Brian Johnsone99ac542010-03-16 13:58:28 -030058#define SENSOR_MT9M112 10
59#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030060#define SENSOR_MT9VPRB 20
61
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030062/* camera flags */
Brian Johnson33ddc162010-04-18 21:42:40 -030063#define HAS_NO_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030064#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030065#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030066
Brian Johnson26e744b2009-07-19 05:52:58 -030067/* specific webcam descriptor */
68struct sd {
69 struct gspca_dev gspca_dev;
70
71#define MIN_AVG_LUM 80
72#define MAX_AVG_LUM 130
73 atomic_t avg_lum;
74 u8 old_step;
75 u8 older_step;
76 u8 exposure_step;
77
78 u8 brightness;
79 u8 contrast;
80 u8 saturation;
81 s16 hue;
82 u8 gamma;
83 u8 red;
84 u8 blue;
85
86 u8 hflip;
87 u8 vflip;
88 u8 gain;
89 u16 exposure;
90 u8 auto_exposure;
91
92 u8 i2c_addr;
93 u8 sensor;
94 u8 hstart;
95 u8 vstart;
96
Jean-François Moine9a731a32010-06-04 05:26:42 -030097 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -030098 u8 quality;
99
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300100 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300101};
102
Joe Perches58aa68c2009-09-02 01:12:13 -0300103struct i2c_reg_u8 {
104 u8 reg;
105 u8 val;
106};
107
108struct i2c_reg_u16 {
109 u8 reg;
110 u16 val;
111};
112
Brian Johnson26e744b2009-07-19 05:52:58 -0300113static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
114static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
115static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
116static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
117static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
118static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
119static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
120static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
121static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
122static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
123static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
124static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
125static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
126static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
127static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
128static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
129static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
130static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
131static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
132static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
133static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
134static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
135static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
136static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
137
Brian Johnson7ddaac72010-03-16 13:58:27 -0300138static const struct dmi_system_id flip_dmi_table[] = {
139 {
140 .ident = "MSI MS-1034",
141 .matches = {
142 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
143 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
144 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
145 }
146 },
147 {
148 .ident = "MSI MS-1632",
149 .matches = {
150 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
151 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
152 }
153 },
Brian Johnsone077f862010-04-05 20:52:52 -0300154 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300155 .ident = "MSI MS-1635X",
156 .matches = {
157 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
158 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
159 }
160 },
161 {
Brian Johnsone077f862010-04-05 20:52:52 -0300162 .ident = "ASUSTeK W7J",
163 .matches = {
164 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
165 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
166 }
167 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300168 {}
169};
170
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300171static const struct ctrl sd_ctrls[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300172 {
173#define BRIGHTNESS_IDX 0
174 {
175 .id = V4L2_CID_BRIGHTNESS,
176 .type = V4L2_CTRL_TYPE_INTEGER,
177 .name = "Brightness",
178 .minimum = 0,
179 .maximum = 0xff,
180 .step = 1,
181#define BRIGHTNESS_DEFAULT 0x7f
182 .default_value = BRIGHTNESS_DEFAULT,
183 },
184 .set = sd_setbrightness,
185 .get = sd_getbrightness,
186 },
187 {
188#define CONTRAST_IDX 1
189 {
190 .id = V4L2_CID_CONTRAST,
191 .type = V4L2_CTRL_TYPE_INTEGER,
192 .name = "Contrast",
193 .minimum = 0,
194 .maximum = 0xff,
195 .step = 1,
196#define CONTRAST_DEFAULT 0x7f
197 .default_value = CONTRAST_DEFAULT,
198 },
199 .set = sd_setcontrast,
200 .get = sd_getcontrast,
201 },
202 {
203#define SATURATION_IDX 2
204 {
205 .id = V4L2_CID_SATURATION,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Saturation",
208 .minimum = 0,
209 .maximum = 0xff,
210 .step = 1,
211#define SATURATION_DEFAULT 0x7f
212 .default_value = SATURATION_DEFAULT,
213 },
214 .set = sd_setsaturation,
215 .get = sd_getsaturation,
216 },
217 {
218#define HUE_IDX 3
219 {
220 .id = V4L2_CID_HUE,
221 .type = V4L2_CTRL_TYPE_INTEGER,
222 .name = "Hue",
223 .minimum = -180,
224 .maximum = 180,
225 .step = 1,
226#define HUE_DEFAULT 0
227 .default_value = HUE_DEFAULT,
228 },
229 .set = sd_sethue,
230 .get = sd_gethue,
231 },
232 {
233#define GAMMA_IDX 4
234 {
235 .id = V4L2_CID_GAMMA,
236 .type = V4L2_CTRL_TYPE_INTEGER,
237 .name = "Gamma",
238 .minimum = 0,
239 .maximum = 0xff,
240 .step = 1,
241#define GAMMA_DEFAULT 0x10
242 .default_value = GAMMA_DEFAULT,
243 },
244 .set = sd_setgamma,
245 .get = sd_getgamma,
246 },
247 {
248#define BLUE_IDX 5
249 {
250 .id = V4L2_CID_BLUE_BALANCE,
251 .type = V4L2_CTRL_TYPE_INTEGER,
252 .name = "Blue Balance",
253 .minimum = 0,
254 .maximum = 0x7f,
255 .step = 1,
256#define BLUE_DEFAULT 0x28
257 .default_value = BLUE_DEFAULT,
258 },
259 .set = sd_setbluebalance,
260 .get = sd_getbluebalance,
261 },
262 {
263#define RED_IDX 6
264 {
265 .id = V4L2_CID_RED_BALANCE,
266 .type = V4L2_CTRL_TYPE_INTEGER,
267 .name = "Red Balance",
268 .minimum = 0,
269 .maximum = 0x7f,
270 .step = 1,
271#define RED_DEFAULT 0x28
272 .default_value = RED_DEFAULT,
273 },
274 .set = sd_setredbalance,
275 .get = sd_getredbalance,
276 },
277 {
278#define HFLIP_IDX 7
279 {
280 .id = V4L2_CID_HFLIP,
281 .type = V4L2_CTRL_TYPE_BOOLEAN,
282 .name = "Horizontal Flip",
283 .minimum = 0,
284 .maximum = 1,
285 .step = 1,
286#define HFLIP_DEFAULT 0
287 .default_value = HFLIP_DEFAULT,
288 },
289 .set = sd_sethflip,
290 .get = sd_gethflip,
291 },
292 {
293#define VFLIP_IDX 8
294 {
295 .id = V4L2_CID_VFLIP,
296 .type = V4L2_CTRL_TYPE_BOOLEAN,
297 .name = "Vertical Flip",
298 .minimum = 0,
299 .maximum = 1,
300 .step = 1,
301#define VFLIP_DEFAULT 0
302 .default_value = VFLIP_DEFAULT,
303 },
304 .set = sd_setvflip,
305 .get = sd_getvflip,
306 },
307 {
308#define EXPOSURE_IDX 9
309 {
310 .id = V4L2_CID_EXPOSURE,
311 .type = V4L2_CTRL_TYPE_INTEGER,
312 .name = "Exposure",
313 .minimum = 0,
314 .maximum = 0x1780,
315 .step = 1,
316#define EXPOSURE_DEFAULT 0x33
317 .default_value = EXPOSURE_DEFAULT,
318 },
319 .set = sd_setexposure,
320 .get = sd_getexposure,
321 },
322 {
323#define GAIN_IDX 10
324 {
325 .id = V4L2_CID_GAIN,
326 .type = V4L2_CTRL_TYPE_INTEGER,
327 .name = "Gain",
328 .minimum = 0,
329 .maximum = 28,
330 .step = 1,
331#define GAIN_DEFAULT 0x00
332 .default_value = GAIN_DEFAULT,
333 },
334 .set = sd_setgain,
335 .get = sd_getgain,
336 },
337 {
338#define AUTOGAIN_IDX 11
339 {
340 .id = V4L2_CID_AUTOGAIN,
341 .type = V4L2_CTRL_TYPE_BOOLEAN,
342 .name = "Auto Exposure",
343 .minimum = 0,
344 .maximum = 1,
345 .step = 1,
346#define AUTO_EXPOSURE_DEFAULT 1
347 .default_value = AUTO_EXPOSURE_DEFAULT,
348 },
349 .set = sd_setautoexposure,
350 .get = sd_getautoexposure,
351 },
352};
353
354static const struct v4l2_pix_format vga_mode[] = {
355 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300356 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300357 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300358 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300359 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300360 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
361 .bytesperline = 160,
362 .sizeimage = 160 * 120,
363 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300364 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300365 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300366 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300367 .sizeimage = 240 * 120,
368 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300369 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300370 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300371 .bytesperline = 320,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300372 .sizeimage = 320 * 240 * 3 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300373 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300374 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300375 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
376 .bytesperline = 320,
377 .sizeimage = 320 * 240 ,
378 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300379 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300380 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300381 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300382 .sizeimage = 480 * 240 ,
383 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300384 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300385 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300386 .bytesperline = 640,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300387 .sizeimage = 640 * 480 * 3 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300388 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300389 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300390 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
391 .bytesperline = 640,
392 .sizeimage = 640 * 480,
393 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300394 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300395 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300396 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300397 .sizeimage = 960 * 480,
398 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300399 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300400};
401
402static const struct v4l2_pix_format sxga_mode[] = {
403 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300404 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300405 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300407 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300408 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
409 .bytesperline = 160,
410 .sizeimage = 160 * 120,
411 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300412 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300413 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300414 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300415 .sizeimage = 240 * 120,
416 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300417 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300418 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300419 .bytesperline = 320,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300420 .sizeimage = 320 * 240 * 3 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300421 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300422 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300423 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
424 .bytesperline = 320,
425 .sizeimage = 320 * 240 ,
426 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300427 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300428 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300429 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300430 .sizeimage = 480 * 240 ,
431 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300432 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300433 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300434 .bytesperline = 640,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300435 .sizeimage = 640 * 480 * 3 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300436 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300437 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300438 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
439 .bytesperline = 640,
440 .sizeimage = 640 * 480,
441 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300442 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300443 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300444 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300445 .sizeimage = 960 * 480,
446 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300447 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300448 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
449 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300450 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300451 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300452 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300453};
454
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300455static const struct v4l2_pix_format mono_mode[] = {
456 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
457 .bytesperline = 160,
458 .sizeimage = 160 * 120,
459 .colorspace = V4L2_COLORSPACE_SRGB,
460 .priv = SCALE_160x120 | MODE_RAW},
461 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
462 .bytesperline = 320,
463 .sizeimage = 320 * 240 ,
464 .colorspace = V4L2_COLORSPACE_SRGB,
465 .priv = SCALE_320x240 | MODE_RAW},
466 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
467 .bytesperline = 640,
468 .sizeimage = 640 * 480,
469 .colorspace = V4L2_COLORSPACE_SRGB,
470 .priv = SCALE_640x480 | MODE_RAW},
471 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
472 .bytesperline = 1280,
473 .sizeimage = 1280 * 1024,
474 .colorspace = V4L2_COLORSPACE_SRGB,
475 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
476};
477
Joe Perches58aa68c2009-09-02 01:12:13 -0300478static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300479 41, 44, 46, 48, 50, 52, 54, 56,
480 58, 60, 62, 64, 66, 68, 70, 72,
481 74, 76, 78, 80, 81, 83, 85, 87,
482 88, 90, 92, 93, 95, 97, 98, 100,
483 101, 102, 104, 105, 107, 108, 109, 110,
484 112, 113, 114, 115, 116, 117, 118, 119,
485 120, 121, 122, 123, 123, 124, 125, 125,
486 126, 127, 127, 128, 128, 129, 129, 129,
487 130, 130, 130, 130, 131, 131, 131, 131,
488 131, 131, 131, 131, 130, 130, 130, 130,
489 129, 129, 129, 128, 128, 127, 127, 126,
490 125, 125, 124, 123, 122, 122, 121, 120,
491 119, 118, 117, 116, 115, 114, 112, 111,
492 110, 109, 107, 106, 105, 103, 102, 101,
493 99, 98, 96, 94, 93, 91, 90, 88,
494 86, 84, 83, 81, 79, 77, 75, 74,
495 72, 70, 68, 66, 64, 62, 60, 58,
496 56, 54, 52, 49, 47, 45, 43, 41,
497 39, 36, 34, 32, 30, 28, 25, 23,
498 21, 19, 16, 14, 12, 9, 7, 5,
499 3, 0, -1, -3, -6, -8, -10, -12,
500 -15, -17, -19, -22, -24, -26, -28, -30,
501 -33, -35, -37, -39, -41, -44, -46, -48,
502 -50, -52, -54, -56, -58, -60, -62, -64,
503 -66, -68, -70, -72, -74, -76, -78, -80,
504 -81, -83, -85, -87, -88, -90, -92, -93,
505 -95, -97, -98, -100, -101, -102, -104, -105,
506 -107, -108, -109, -110, -112, -113, -114, -115,
507 -116, -117, -118, -119, -120, -121, -122, -123,
508 -123, -124, -125, -125, -126, -127, -127, -128,
509 -128, -128, -128, -128, -128, -128, -128, -128,
510 -128, -128, -128, -128, -128, -128, -128, -128,
511 -128, -128, -128, -128, -128, -128, -128, -128,
512 -128, -127, -127, -126, -125, -125, -124, -123,
513 -122, -122, -121, -120, -119, -118, -117, -116,
514 -115, -114, -112, -111, -110, -109, -107, -106,
515 -105, -103, -102, -101, -99, -98, -96, -94,
516 -93, -91, -90, -88, -86, -84, -83, -81,
517 -79, -77, -75, -74, -72, -70, -68, -66,
518 -64, -62, -60, -58, -56, -54, -52, -49,
519 -47, -45, -43, -41, -39, -36, -34, -32,
520 -30, -28, -25, -23, -21, -19, -16, -14,
521 -12, -9, -7, -5, -3, 0, 1, 3,
522 6, 8, 10, 12, 15, 17, 19, 22,
523 24, 26, 28, 30, 33, 35, 37, 39, 41
524};
525
Joe Perches58aa68c2009-09-02 01:12:13 -0300526static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300527 82, 80, 78, 76, 74, 73, 71, 69,
528 67, 65, 63, 61, 58, 56, 54, 52,
529 50, 48, 46, 44, 41, 39, 37, 35,
530 32, 30, 28, 26, 23, 21, 19, 16,
531 14, 12, 10, 7, 5, 3, 0, -1,
532 -3, -6, -8, -10, -13, -15, -17, -19,
533 -22, -24, -26, -29, -31, -33, -35, -38,
534 -40, -42, -44, -46, -48, -51, -53, -55,
535 -57, -59, -61, -63, -65, -67, -69, -71,
536 -73, -75, -77, -79, -81, -82, -84, -86,
537 -88, -89, -91, -93, -94, -96, -98, -99,
538 -101, -102, -104, -105, -106, -108, -109, -110,
539 -112, -113, -114, -115, -116, -117, -119, -120,
540 -120, -121, -122, -123, -124, -125, -126, -126,
541 -127, -128, -128, -128, -128, -128, -128, -128,
542 -128, -128, -128, -128, -128, -128, -128, -128,
543 -128, -128, -128, -128, -128, -128, -128, -128,
544 -128, -128, -128, -128, -128, -128, -128, -128,
545 -127, -127, -126, -125, -125, -124, -123, -122,
546 -121, -120, -119, -118, -117, -116, -115, -114,
547 -113, -111, -110, -109, -107, -106, -105, -103,
548 -102, -100, -99, -97, -96, -94, -92, -91,
549 -89, -87, -85, -84, -82, -80, -78, -76,
550 -74, -73, -71, -69, -67, -65, -63, -61,
551 -58, -56, -54, -52, -50, -48, -46, -44,
552 -41, -39, -37, -35, -32, -30, -28, -26,
553 -23, -21, -19, -16, -14, -12, -10, -7,
554 -5, -3, 0, 1, 3, 6, 8, 10,
555 13, 15, 17, 19, 22, 24, 26, 29,
556 31, 33, 35, 38, 40, 42, 44, 46,
557 48, 51, 53, 55, 57, 59, 61, 63,
558 65, 67, 69, 71, 73, 75, 77, 79,
559 81, 82, 84, 86, 88, 89, 91, 93,
560 94, 96, 98, 99, 101, 102, 104, 105,
561 106, 108, 109, 110, 112, 113, 114, 115,
562 116, 117, 119, 120, 120, 121, 122, 123,
563 124, 125, 126, 126, 127, 128, 128, 129,
564 129, 130, 130, 131, 131, 131, 131, 132,
565 132, 132, 132, 132, 132, 132, 132, 132,
566 132, 132, 132, 131, 131, 131, 130, 130,
567 130, 129, 129, 128, 127, 127, 126, 125,
568 125, 124, 123, 122, 121, 120, 119, 118,
569 117, 116, 115, 114, 113, 111, 110, 109,
570 107, 106, 105, 103, 102, 100, 99, 97,
571 96, 94, 92, 91, 89, 87, 85, 84, 82
572};
573
Joe Perches58aa68c2009-09-02 01:12:13 -0300574static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300575 -124, -124, -125, -125, -125, -125, -125, -125,
576 -125, -126, -126, -125, -125, -125, -125, -125,
577 -125, -124, -124, -124, -123, -123, -122, -122,
578 -121, -121, -120, -120, -119, -118, -117, -117,
579 -116, -115, -114, -113, -112, -111, -110, -109,
580 -108, -107, -105, -104, -103, -102, -100, -99,
581 -98, -96, -95, -93, -92, -91, -89, -87,
582 -86, -84, -83, -81, -79, -77, -76, -74,
583 -72, -70, -69, -67, -65, -63, -61, -59,
584 -57, -55, -53, -51, -49, -47, -45, -43,
585 -41, -39, -37, -35, -33, -30, -28, -26,
586 -24, -22, -20, -18, -15, -13, -11, -9,
587 -7, -4, -2, 0, 1, 3, 6, 8,
588 10, 12, 14, 17, 19, 21, 23, 25,
589 27, 29, 32, 34, 36, 38, 40, 42,
590 44, 46, 48, 50, 52, 54, 56, 58,
591 60, 62, 64, 66, 68, 70, 71, 73,
592 75, 77, 78, 80, 82, 83, 85, 87,
593 88, 90, 91, 93, 94, 96, 97, 98,
594 100, 101, 102, 104, 105, 106, 107, 108,
595 109, 111, 112, 113, 113, 114, 115, 116,
596 117, 118, 118, 119, 120, 120, 121, 122,
597 122, 123, 123, 124, 124, 124, 125, 125,
598 125, 125, 125, 125, 125, 126, 126, 125,
599 125, 125, 125, 125, 125, 124, 124, 124,
600 123, 123, 122, 122, 121, 121, 120, 120,
601 119, 118, 117, 117, 116, 115, 114, 113,
602 112, 111, 110, 109, 108, 107, 105, 104,
603 103, 102, 100, 99, 98, 96, 95, 93,
604 92, 91, 89, 87, 86, 84, 83, 81,
605 79, 77, 76, 74, 72, 70, 69, 67,
606 65, 63, 61, 59, 57, 55, 53, 51,
607 49, 47, 45, 43, 41, 39, 37, 35,
608 33, 30, 28, 26, 24, 22, 20, 18,
609 15, 13, 11, 9, 7, 4, 2, 0,
610 -1, -3, -6, -8, -10, -12, -14, -17,
611 -19, -21, -23, -25, -27, -29, -32, -34,
612 -36, -38, -40, -42, -44, -46, -48, -50,
613 -52, -54, -56, -58, -60, -62, -64, -66,
614 -68, -70, -71, -73, -75, -77, -78, -80,
615 -82, -83, -85, -87, -88, -90, -91, -93,
616 -94, -96, -97, -98, -100, -101, -102, -104,
617 -105, -106, -107, -108, -109, -111, -112, -113,
618 -113, -114, -115, -116, -117, -118, -118, -119,
619 -120, -120, -121, -122, -122, -123, -123, -124, -124
620};
621
Joe Perches58aa68c2009-09-02 01:12:13 -0300622static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300623 -100, -99, -98, -97, -95, -94, -93, -91,
624 -90, -89, -87, -86, -84, -83, -81, -80,
625 -78, -76, -75, -73, -71, -70, -68, -66,
626 -64, -63, -61, -59, -57, -55, -53, -51,
627 -49, -48, -46, -44, -42, -40, -38, -36,
628 -34, -32, -30, -27, -25, -23, -21, -19,
629 -17, -15, -13, -11, -9, -7, -4, -2,
630 0, 1, 3, 5, 7, 9, 11, 14,
631 16, 18, 20, 22, 24, 26, 28, 30,
632 32, 34, 36, 38, 40, 42, 44, 46,
633 48, 50, 52, 54, 56, 58, 59, 61,
634 63, 65, 67, 68, 70, 72, 74, 75,
635 77, 78, 80, 82, 83, 85, 86, 88,
636 89, 90, 92, 93, 95, 96, 97, 98,
637 100, 101, 102, 103, 104, 105, 106, 107,
638 108, 109, 110, 111, 112, 112, 113, 114,
639 115, 115, 116, 116, 117, 117, 118, 118,
640 119, 119, 119, 120, 120, 120, 120, 120,
641 121, 121, 121, 121, 121, 121, 120, 120,
642 120, 120, 120, 119, 119, 119, 118, 118,
643 117, 117, 116, 116, 115, 114, 114, 113,
644 112, 111, 111, 110, 109, 108, 107, 106,
645 105, 104, 103, 102, 100, 99, 98, 97,
646 95, 94, 93, 91, 90, 89, 87, 86,
647 84, 83, 81, 80, 78, 76, 75, 73,
648 71, 70, 68, 66, 64, 63, 61, 59,
649 57, 55, 53, 51, 49, 48, 46, 44,
650 42, 40, 38, 36, 34, 32, 30, 27,
651 25, 23, 21, 19, 17, 15, 13, 11,
652 9, 7, 4, 2, 0, -1, -3, -5,
653 -7, -9, -11, -14, -16, -18, -20, -22,
654 -24, -26, -28, -30, -32, -34, -36, -38,
655 -40, -42, -44, -46, -48, -50, -52, -54,
656 -56, -58, -59, -61, -63, -65, -67, -68,
657 -70, -72, -74, -75, -77, -78, -80, -82,
658 -83, -85, -86, -88, -89, -90, -92, -93,
659 -95, -96, -97, -98, -100, -101, -102, -103,
660 -104, -105, -106, -107, -108, -109, -110, -111,
661 -112, -112, -113, -114, -115, -115, -116, -116,
662 -117, -117, -118, -118, -119, -119, -119, -120,
663 -120, -120, -120, -120, -121, -121, -121, -121,
664 -121, -121, -120, -120, -120, -120, -120, -119,
665 -119, -119, -118, -118, -117, -117, -116, -116,
666 -115, -114, -114, -113, -112, -111, -111, -110,
667 -109, -108, -107, -106, -105, -104, -103, -102, -100
668};
669
Joe Perches58aa68c2009-09-02 01:12:13 -0300670static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300671 112, 113, 114, 114, 115, 116, 117, 117,
672 118, 118, 119, 119, 120, 120, 120, 121,
673 121, 121, 122, 122, 122, 122, 122, 122,
674 122, 122, 122, 122, 122, 122, 121, 121,
675 121, 120, 120, 120, 119, 119, 118, 118,
676 117, 116, 116, 115, 114, 113, 113, 112,
677 111, 110, 109, 108, 107, 106, 105, 104,
678 103, 102, 100, 99, 98, 97, 95, 94,
679 93, 91, 90, 88, 87, 85, 84, 82,
680 80, 79, 77, 76, 74, 72, 70, 69,
681 67, 65, 63, 61, 60, 58, 56, 54,
682 52, 50, 48, 46, 44, 42, 40, 38,
683 36, 34, 32, 30, 28, 26, 24, 22,
684 19, 17, 15, 13, 11, 9, 7, 5,
685 2, 0, -1, -3, -5, -7, -9, -12,
686 -14, -16, -18, -20, -22, -24, -26, -28,
687 -31, -33, -35, -37, -39, -41, -43, -45,
688 -47, -49, -51, -53, -54, -56, -58, -60,
689 -62, -64, -66, -67, -69, -71, -73, -74,
690 -76, -78, -79, -81, -83, -84, -86, -87,
691 -89, -90, -92, -93, -94, -96, -97, -98,
692 -99, -101, -102, -103, -104, -105, -106, -107,
693 -108, -109, -110, -111, -112, -113, -114, -114,
694 -115, -116, -117, -117, -118, -118, -119, -119,
695 -120, -120, -120, -121, -121, -121, -122, -122,
696 -122, -122, -122, -122, -122, -122, -122, -122,
697 -122, -122, -121, -121, -121, -120, -120, -120,
698 -119, -119, -118, -118, -117, -116, -116, -115,
699 -114, -113, -113, -112, -111, -110, -109, -108,
700 -107, -106, -105, -104, -103, -102, -100, -99,
701 -98, -97, -95, -94, -93, -91, -90, -88,
702 -87, -85, -84, -82, -80, -79, -77, -76,
703 -74, -72, -70, -69, -67, -65, -63, -61,
704 -60, -58, -56, -54, -52, -50, -48, -46,
705 -44, -42, -40, -38, -36, -34, -32, -30,
706 -28, -26, -24, -22, -19, -17, -15, -13,
707 -11, -9, -7, -5, -2, 0, 1, 3,
708 5, 7, 9, 12, 14, 16, 18, 20,
709 22, 24, 26, 28, 31, 33, 35, 37,
710 39, 41, 43, 45, 47, 49, 51, 53,
711 54, 56, 58, 60, 62, 64, 66, 67,
712 69, 71, 73, 74, 76, 78, 79, 81,
713 83, 84, 86, 87, 89, 90, 92, 93,
714 94, 96, 97, 98, 99, 101, 102, 103,
715 104, 105, 106, 107, 108, 109, 110, 111, 112
716};
717
Joe Perches58aa68c2009-09-02 01:12:13 -0300718static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300719 -11, -13, -15, -17, -19, -21, -23, -25,
720 -27, -29, -31, -33, -35, -37, -39, -41,
721 -43, -45, -46, -48, -50, -52, -54, -55,
722 -57, -59, -61, -62, -64, -66, -67, -69,
723 -71, -72, -74, -75, -77, -78, -80, -81,
724 -83, -84, -86, -87, -88, -90, -91, -92,
725 -93, -95, -96, -97, -98, -99, -100, -101,
726 -102, -103, -104, -105, -106, -106, -107, -108,
727 -109, -109, -110, -111, -111, -112, -112, -113,
728 -113, -114, -114, -114, -115, -115, -115, -115,
729 -116, -116, -116, -116, -116, -116, -116, -116,
730 -116, -115, -115, -115, -115, -114, -114, -114,
731 -113, -113, -112, -112, -111, -111, -110, -110,
732 -109, -108, -108, -107, -106, -105, -104, -103,
733 -102, -101, -100, -99, -98, -97, -96, -95,
734 -94, -93, -91, -90, -89, -88, -86, -85,
735 -84, -82, -81, -79, -78, -76, -75, -73,
736 -71, -70, -68, -67, -65, -63, -62, -60,
737 -58, -56, -55, -53, -51, -49, -47, -45,
738 -44, -42, -40, -38, -36, -34, -32, -30,
739 -28, -26, -24, -22, -20, -18, -16, -14,
740 -12, -10, -8, -6, -4, -2, 0, 1,
741 3, 5, 7, 9, 11, 13, 15, 17,
742 19, 21, 23, 25, 27, 29, 31, 33,
743 35, 37, 39, 41, 43, 45, 46, 48,
744 50, 52, 54, 55, 57, 59, 61, 62,
745 64, 66, 67, 69, 71, 72, 74, 75,
746 77, 78, 80, 81, 83, 84, 86, 87,
747 88, 90, 91, 92, 93, 95, 96, 97,
748 98, 99, 100, 101, 102, 103, 104, 105,
749 106, 106, 107, 108, 109, 109, 110, 111,
750 111, 112, 112, 113, 113, 114, 114, 114,
751 115, 115, 115, 115, 116, 116, 116, 116,
752 116, 116, 116, 116, 116, 115, 115, 115,
753 115, 114, 114, 114, 113, 113, 112, 112,
754 111, 111, 110, 110, 109, 108, 108, 107,
755 106, 105, 104, 103, 102, 101, 100, 99,
756 98, 97, 96, 95, 94, 93, 91, 90,
757 89, 88, 86, 85, 84, 82, 81, 79,
758 78, 76, 75, 73, 71, 70, 68, 67,
759 65, 63, 62, 60, 58, 56, 55, 53,
760 51, 49, 47, 45, 44, 42, 40, 38,
761 36, 34, 32, 30, 28, 26, 24, 22,
762 20, 18, 16, 14, 12, 10, 8, 6,
763 4, 2, 0, -1, -3, -5, -7, -9, -11
764};
765
766static u16 i2c_ident[] = {
767 V4L2_IDENT_OV9650,
768 V4L2_IDENT_OV9655,
769 V4L2_IDENT_SOI968,
770 V4L2_IDENT_OV7660,
771 V4L2_IDENT_OV7670,
772 V4L2_IDENT_MT9V011,
773 V4L2_IDENT_MT9V111,
774 V4L2_IDENT_MT9V112,
775 V4L2_IDENT_MT9M001C12ST,
776 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300777 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300778 V4L2_IDENT_HV7131R,
779};
780
781static u16 bridge_init[][2] = {
782 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
783 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
784 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
785 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
786 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
787 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
788 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
789 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
790 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
791 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
792 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
793 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
794 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
795 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
796 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
797 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
798 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
799 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300800 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
801 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300802};
803
804/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
805static u8 ov_gain[] = {
806 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
807 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
808 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
809 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
810 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
811 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
812 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
813 0x70 /* 8x */
814};
815
816/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
817static u16 micron1_gain[] = {
818 /* 1x 1.25x 1.5x 1.75x */
819 0x0020, 0x0028, 0x0030, 0x0038,
820 /* 2x 2.25x 2.5x 2.75x */
821 0x00a0, 0x00a4, 0x00a8, 0x00ac,
822 /* 3x 3.25x 3.5x 3.75x */
823 0x00b0, 0x00b4, 0x00b8, 0x00bc,
824 /* 4x 4.25x 4.5x 4.75x */
825 0x00c0, 0x00c4, 0x00c8, 0x00cc,
826 /* 5x 5.25x 5.5x 5.75x */
827 0x00d0, 0x00d4, 0x00d8, 0x00dc,
828 /* 6x 6.25x 6.5x 6.75x */
829 0x00e0, 0x00e4, 0x00e8, 0x00ec,
830 /* 7x 7.25x 7.5x 7.75x */
831 0x00f0, 0x00f4, 0x00f8, 0x00fc,
832 /* 8x */
833 0x01c0
834};
835
836/* mt9m001 sensor uses a different gain formula then other micron sensors */
837/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
838static u16 micron2_gain[] = {
839 /* 1x 1.25x 1.5x 1.75x */
840 0x0008, 0x000a, 0x000c, 0x000e,
841 /* 2x 2.25x 2.5x 2.75x */
842 0x0010, 0x0012, 0x0014, 0x0016,
843 /* 3x 3.25x 3.5x 3.75x */
844 0x0018, 0x001a, 0x001c, 0x001e,
845 /* 4x 4.25x 4.5x 4.75x */
846 0x0020, 0x0051, 0x0052, 0x0053,
847 /* 5x 5.25x 5.5x 5.75x */
848 0x0054, 0x0055, 0x0056, 0x0057,
849 /* 6x 6.25x 6.5x 6.75x */
850 0x0058, 0x0059, 0x005a, 0x005b,
851 /* 7x 7.25x 7.5x 7.75x */
852 0x005c, 0x005d, 0x005e, 0x005f,
853 /* 8x */
854 0x0060
855};
856
857/* Gain = .5 + bit[7:0] / 16 */
858static u8 hv7131r_gain[] = {
859 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
860 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
861 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
862 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
863 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
864 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
865 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
866 0x78 /* 8x */
867};
868
Joe Perches58aa68c2009-09-02 01:12:13 -0300869static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300870 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
871 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
872 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
873 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
874 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
875 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300876 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300877 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
878 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
879 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
880 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
881};
882
Joe Perches58aa68c2009-09-02 01:12:13 -0300883static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300884 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
885 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
886 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300887 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
888 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
889 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300890 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
891 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
892 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
893};
894
Joe Perches58aa68c2009-09-02 01:12:13 -0300895static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300896 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
897 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
898 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
899 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
900 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
901 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
902 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
903 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
904 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
905 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
906 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
907 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
908 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
909 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
910 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
911 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
912 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
913 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
914 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
915 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
916 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
917 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
918 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
919 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
920 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
921 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
922 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
923 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
924 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
925 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
926 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
927 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
928 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
929 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
930 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
931 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
932 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
933 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
934 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
935 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
936 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
937 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
938 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
939 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
940 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
941 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
942 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
943 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
944 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
945 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
946 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
947 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
948 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
949 {0x93, 0x00},
950};
951
Joe Perches58aa68c2009-09-02 01:12:13 -0300952static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300953 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
954 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
955 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
956 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
957 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
958 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
959 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
960 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
961 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
962 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
963 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
964 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
965 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
966 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
967 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
968 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
969 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
970 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
971 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
972 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
973 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
974 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
975 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
976 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
977 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
978 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
979 {0xaa, 0x92}, {0xab, 0x0a},
980};
981
Joe Perches58aa68c2009-09-02 01:12:13 -0300982static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300983 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
984 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
985 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
986 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
987 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
988 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
989 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
990 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
991 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
992 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
993 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
994 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
995 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
996 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
997 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
998 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300999 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001000 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
1001 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -03001002 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001003 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
1004 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
1005 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
1006 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -03001007};
1008
Joe Perches58aa68c2009-09-02 01:12:13 -03001009static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001010 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
1011 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
1012 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
1013 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1014 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1015 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1016 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1017 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1018 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1019 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1020 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1021 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1022 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1023 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1024 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1025 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1026};
1027
Joe Perches58aa68c2009-09-02 01:12:13 -03001028static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001029 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001030 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1031 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1032 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1033 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1034 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1035 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001036};
1037
Joe Perches58aa68c2009-09-02 01:12:13 -03001038static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001039 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1040 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1041 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1042 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1043 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1044 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1045 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1046 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1047 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1048 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1049 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1050 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1051 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1052 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1053 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1054 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1055 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1056 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1057 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1058 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1059 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1060 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1061 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1062 {0x06, 0x0029}, {0x05, 0x0009},
1063};
1064
Joe Perches58aa68c2009-09-02 01:12:13 -03001065static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001066 {0x0d, 0x0001},
1067 {0x0d, 0x0000},
1068 {0x04, 0x0500}, /* hres = 1280 */
1069 {0x03, 0x0400}, /* vres = 1024 */
1070 {0x20, 0x1100},
1071 {0x06, 0x0010},
1072 {0x2b, 0x0024},
1073 {0x2e, 0x0024},
1074 {0x35, 0x0024},
1075 {0x2d, 0x0020},
1076 {0x2c, 0x0020},
1077 {0x09, 0x0ad4},
1078 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001079};
1080
Joe Perches58aa68c2009-09-02 01:12:13 -03001081static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001082 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1083 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001084 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1085 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001086};
1087
Brian Johnsone99ac542010-03-16 13:58:28 -03001088static struct i2c_reg_u16 mt9m112_init[] = {
1089 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1090 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1091 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1092 {0xf0, 0x0000},
1093};
1094
Joe Perches58aa68c2009-09-02 01:12:13 -03001095static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001096 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1097 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1098 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1099 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1100 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1101 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1102 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1103 {0x23, 0x09}, {0x01, 0x08},
1104};
1105
Joe Perches58aa68c2009-09-02 01:12:13 -03001106static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001107{
1108 struct usb_device *dev = gspca_dev->dev;
1109 int result;
1110 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1111 0x00,
1112 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1113 reg,
1114 0x00,
1115 gspca_dev->usb_buf,
1116 length,
1117 500);
1118 if (unlikely(result < 0 || result != length)) {
1119 err("Read register failed 0x%02X", reg);
1120 return -EIO;
1121 }
1122 return 0;
1123}
1124
Joe Perches58aa68c2009-09-02 01:12:13 -03001125static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1126 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001127{
1128 struct usb_device *dev = gspca_dev->dev;
1129 int result;
1130 memcpy(gspca_dev->usb_buf, buffer, length);
1131 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1132 0x08,
1133 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1134 reg,
1135 0x00,
1136 gspca_dev->usb_buf,
1137 length,
1138 500);
1139 if (unlikely(result < 0 || result != length)) {
1140 err("Write register failed index 0x%02X", reg);
1141 return -EIO;
1142 }
1143 return 0;
1144}
1145
Joe Perches58aa68c2009-09-02 01:12:13 -03001146static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001147{
1148 u8 data[1] = {value};
1149 return reg_w(gspca_dev, reg, data, 1);
1150}
1151
Joe Perches58aa68c2009-09-02 01:12:13 -03001152static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001153{
1154 int i;
1155 reg_w(gspca_dev, 0x10c0, buffer, 8);
1156 for (i = 0; i < 5; i++) {
1157 reg_r(gspca_dev, 0x10c0, 1);
1158 if (gspca_dev->usb_buf[0] & 0x04) {
1159 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001160 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001161 return 0;
1162 }
1163 msleep(1);
1164 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001165 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001166}
1167
Joe Perches58aa68c2009-09-02 01:12:13 -03001168static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001169{
1170 struct sd *sd = (struct sd *) gspca_dev;
1171
1172 u8 row[8];
1173
1174 /*
1175 * from the point of view of the bridge, the length
1176 * includes the address
1177 */
1178 row[0] = 0x81 | (2 << 4);
1179 row[1] = sd->i2c_addr;
1180 row[2] = reg;
1181 row[3] = val;
1182 row[4] = 0x00;
1183 row[5] = 0x00;
1184 row[6] = 0x00;
1185 row[7] = 0x10;
1186
1187 return i2c_w(gspca_dev, row);
1188}
1189
Joe Perches58aa68c2009-09-02 01:12:13 -03001190static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001191{
1192 struct sd *sd = (struct sd *) gspca_dev;
1193 u8 row[8];
1194
1195 /*
1196 * from the point of view of the bridge, the length
1197 * includes the address
1198 */
1199 row[0] = 0x81 | (3 << 4);
1200 row[1] = sd->i2c_addr;
1201 row[2] = reg;
1202 row[3] = (val >> 8) & 0xff;
1203 row[4] = val & 0xff;
1204 row[5] = 0x00;
1205 row[6] = 0x00;
1206 row[7] = 0x10;
1207
1208 return i2c_w(gspca_dev, row);
1209}
1210
Jean-Francois Moine83955552009-12-12 06:58:01 -03001211static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001212{
1213 struct sd *sd = (struct sd *) gspca_dev;
1214 u8 row[8];
1215
Brian Johnson00b581e2009-07-23 05:55:43 -03001216 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001217 row[1] = sd->i2c_addr;
1218 row[2] = reg;
1219 row[3] = 0;
1220 row[4] = 0;
1221 row[5] = 0;
1222 row[6] = 0;
1223 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001224 if (i2c_w(gspca_dev, row) < 0)
1225 return -EIO;
1226 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001227 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001228 if (i2c_w(gspca_dev, row) < 0)
1229 return -EIO;
1230 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1231 return -EIO;
1232 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001233 return 0;
1234}
1235
Jean-Francois Moine83955552009-12-12 06:58:01 -03001236static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001237{
1238 struct sd *sd = (struct sd *) gspca_dev;
1239 u8 row[8];
1240
Brian Johnson00b581e2009-07-23 05:55:43 -03001241 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001242 row[1] = sd->i2c_addr;
1243 row[2] = reg;
1244 row[3] = 0;
1245 row[4] = 0;
1246 row[5] = 0;
1247 row[6] = 0;
1248 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001249 if (i2c_w(gspca_dev, row) < 0)
1250 return -EIO;
1251 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001252 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001253 if (i2c_w(gspca_dev, row) < 0)
1254 return -EIO;
1255 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1256 return -EIO;
1257 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001258 return 0;
1259}
1260
1261static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1262{
1263 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001264 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001265 struct sd *sd = (struct sd *) gspca_dev;
1266
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001267 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1268 return -EINVAL;
1269
1270 if (id != 0x7fa2) {
1271 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1272 return -ENODEV;
1273 }
1274
Brian Johnson26e744b2009-07-19 05:52:58 -03001275 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001276 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1277 ov9650_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001278 err("OV9650 sensor initialization failed");
1279 return -ENODEV;
1280 }
1281 }
1282 sd->hstart = 1;
1283 sd->vstart = 7;
1284 return 0;
1285}
1286
1287static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1288{
1289 int i;
1290 struct sd *sd = (struct sd *) gspca_dev;
1291
1292 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001293 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1294 ov9655_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001295 err("OV9655 sensor initialization failed");
1296 return -ENODEV;
1297 }
1298 }
1299 /* disable hflip and vflip */
1300 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001301 sd->hstart = 1;
1302 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001303 return 0;
1304}
1305
1306static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1307{
1308 int i;
1309 struct sd *sd = (struct sd *) gspca_dev;
1310
1311 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001312 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1313 soi968_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001314 err("SOI968 sensor initialization failed");
1315 return -ENODEV;
1316 }
1317 }
1318 /* disable hflip and vflip */
Jean-François Moine780e3122010-10-19 04:29:10 -03001319 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1320 | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001321 sd->hstart = 60;
1322 sd->vstart = 11;
1323 return 0;
1324}
1325
1326static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1327{
1328 int i;
1329 struct sd *sd = (struct sd *) gspca_dev;
1330
1331 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001332 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1333 ov7660_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001334 err("OV7660 sensor initialization failed");
1335 return -ENODEV;
1336 }
1337 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001338 sd->hstart = 3;
1339 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001340 return 0;
1341}
1342
1343static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1344{
1345 int i;
1346 struct sd *sd = (struct sd *) gspca_dev;
1347
1348 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001349 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1350 ov7670_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001351 err("OV7670 sensor initialization failed");
1352 return -ENODEV;
1353 }
1354 }
1355 /* disable hflip and vflip */
1356 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1357 sd->hstart = 0;
1358 sd->vstart = 1;
1359 return 0;
1360}
1361
1362static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1363{
1364 struct sd *sd = (struct sd *) gspca_dev;
1365 int i;
1366 u16 value;
1367 int ret;
1368
1369 sd->i2c_addr = 0x5d;
1370 ret = i2c_r2(gspca_dev, 0xff, &value);
1371 if ((ret == 0) && (value == 0x8243)) {
1372 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001373 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1374 mt9v011_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001375 err("MT9V011 sensor initialization failed");
1376 return -ENODEV;
1377 }
1378 }
1379 sd->hstart = 2;
1380 sd->vstart = 2;
1381 sd->sensor = SENSOR_MT9V011;
1382 info("MT9V011 sensor detected");
1383 return 0;
1384 }
1385
1386 sd->i2c_addr = 0x5c;
1387 i2c_w2(gspca_dev, 0x01, 0x0004);
1388 ret = i2c_r2(gspca_dev, 0xff, &value);
1389 if ((ret == 0) && (value == 0x823a)) {
1390 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001391 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1392 mt9v111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001393 err("MT9V111 sensor initialization failed");
1394 return -ENODEV;
1395 }
1396 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001397 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1398 | (1 << AUTOGAIN_IDX)
1399 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001400 sd->hstart = 2;
1401 sd->vstart = 2;
1402 sd->sensor = SENSOR_MT9V111;
1403 info("MT9V111 sensor detected");
1404 return 0;
1405 }
1406
1407 sd->i2c_addr = 0x5d;
1408 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1409 if (ret < 0) {
1410 sd->i2c_addr = 0x48;
1411 i2c_w2(gspca_dev, 0xf0, 0x0000);
1412 }
1413 ret = i2c_r2(gspca_dev, 0x00, &value);
1414 if ((ret == 0) && (value == 0x1229)) {
1415 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001416 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1417 mt9v112_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001418 err("MT9V112 sensor initialization failed");
1419 return -ENODEV;
1420 }
1421 }
1422 sd->hstart = 6;
1423 sd->vstart = 2;
1424 sd->sensor = SENSOR_MT9V112;
1425 info("MT9V112 sensor detected");
1426 return 0;
1427 }
1428
1429 return -ENODEV;
1430}
1431
Brian Johnsone99ac542010-03-16 13:58:28 -03001432static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1433{
1434 struct sd *sd = (struct sd *) gspca_dev;
1435 int i;
1436 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1437 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1438 mt9m112_init[i].val) < 0) {
1439 err("MT9M112 sensor initialization failed");
1440 return -ENODEV;
1441 }
1442 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001443 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1444 | (1 << GAIN_IDX);
Brian Johnsone99ac542010-03-16 13:58:28 -03001445 sd->hstart = 0;
1446 sd->vstart = 2;
1447 return 0;
1448}
1449
Brian Johnson26e744b2009-07-19 05:52:58 -03001450static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1451{
1452 struct sd *sd = (struct sd *) gspca_dev;
1453 int i;
1454 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001455 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1456 mt9m111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001457 err("MT9M111 sensor initialization failed");
1458 return -ENODEV;
1459 }
1460 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001461 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1462 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001463 sd->hstart = 0;
1464 sd->vstart = 2;
1465 return 0;
1466}
1467
1468static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1469{
1470 struct sd *sd = (struct sd *) gspca_dev;
1471 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001472 u16 id;
1473
1474 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1475 return -EINVAL;
1476
1477 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1478 switch (id) {
1479 case 0x8411:
1480 case 0x8421:
1481 info("MT9M001 color sensor detected");
1482 break;
1483 case 0x8431:
1484 info("MT9M001 mono sensor detected");
1485 break;
1486 default:
1487 err("No MT9M001 chip detected, ID = %x\n", id);
1488 return -ENODEV;
1489 }
1490
Brian Johnson26e744b2009-07-19 05:52:58 -03001491 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001492 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1493 mt9m001_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001494 err("MT9M001 sensor initialization failed");
1495 return -ENODEV;
1496 }
1497 }
1498 /* disable hflip and vflip */
1499 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001500 sd->hstart = 1;
1501 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001502 return 0;
1503}
1504
1505static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1506{
1507 int i;
1508 struct sd *sd = (struct sd *) gspca_dev;
1509
1510 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001511 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1512 hv7131r_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001513 err("HV7131R Sensor initialization failed");
1514 return -ENODEV;
1515 }
1516 }
1517 sd->hstart = 0;
1518 sd->vstart = 1;
1519 return 0;
1520}
1521
Brian Johnson26e744b2009-07-19 05:52:58 -03001522static int set_cmatrix(struct gspca_dev *gspca_dev)
1523{
1524 struct sd *sd = (struct sd *) gspca_dev;
1525 s32 hue_coord, hue_index = 180 + sd->hue;
1526 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001527
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001528 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001529 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1530 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1531 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1532 cmatrix[18] = sd->brightness - 0x80;
1533
1534 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001535 cmatrix[6] = hue_coord;
1536 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001537
1538 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001539 cmatrix[8] = hue_coord;
1540 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001541
1542 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001543 cmatrix[10] = hue_coord;
1544 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001545
1546 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001547 cmatrix[12] = hue_coord;
1548 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001549
1550 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001551 cmatrix[14] = hue_coord;
1552 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001553
1554 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001555 cmatrix[16] = hue_coord;
1556 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001557
1558 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1559}
1560
1561static int set_gamma(struct gspca_dev *gspca_dev)
1562{
1563 struct sd *sd = (struct sd *) gspca_dev;
1564 u8 gamma[17];
1565 u8 gval = sd->gamma * 0xb8 / 0x100;
1566
1567
1568 gamma[0] = 0x0a;
1569 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1570 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1571 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1572 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1573 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1574 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1575 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1576 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1577 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1578 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1579 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1580 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1581 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1582 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1583 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1584 gamma[16] = 0xf5;
1585
1586 return reg_w(gspca_dev, 0x1190, gamma, 17);
1587}
1588
1589static int set_redblue(struct gspca_dev *gspca_dev)
1590{
1591 struct sd *sd = (struct sd *) gspca_dev;
1592 reg_w1(gspca_dev, 0x118c, sd->red);
1593 reg_w1(gspca_dev, 0x118f, sd->blue);
1594 return 0;
1595}
1596
1597static int set_hvflip(struct gspca_dev *gspca_dev)
1598{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001599 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001600 u16 value2;
1601 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001602
1603 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1604 hflip = !sd->hflip;
1605 vflip = !sd->vflip;
1606 } else {
1607 hflip = sd->hflip;
1608 vflip = sd->vflip;
1609 }
1610
Brian Johnson26e744b2009-07-19 05:52:58 -03001611 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001612 case SENSOR_OV7660:
1613 value = 0x01;
1614 if (hflip)
1615 value |= 0x20;
1616 if (vflip) {
1617 value |= 0x10;
1618 sd->vstart = 2;
1619 } else
1620 sd->vstart = 3;
1621 reg_w1(gspca_dev, 0x1182, sd->vstart);
1622 i2c_w1(gspca_dev, 0x1e, value);
1623 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001624 case SENSOR_OV9650:
1625 i2c_r1(gspca_dev, 0x1e, &value);
1626 value &= ~0x30;
1627 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001628 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001629 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001630 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001631 value |= 0x10;
1632 tslb = 0x49;
1633 }
1634 i2c_w1(gspca_dev, 0x1e, value);
1635 i2c_w1(gspca_dev, 0x3a, tslb);
1636 break;
1637 case SENSOR_MT9V111:
1638 case SENSOR_MT9V011:
1639 i2c_r2(gspca_dev, 0x20, &value2);
1640 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001641 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001642 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001643 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001644 value2 |= 0x4020;
1645 i2c_w2(gspca_dev, 0x20, value2);
1646 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001647 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001648 case SENSOR_MT9M111:
1649 case SENSOR_MT9V112:
1650 i2c_r2(gspca_dev, 0x20, &value2);
1651 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001652 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001653 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001654 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001655 value2 |= 0x0001;
1656 i2c_w2(gspca_dev, 0x20, value2);
1657 break;
1658 case SENSOR_HV7131R:
1659 i2c_r1(gspca_dev, 0x01, &value);
1660 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001661 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001662 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001663 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001664 value |= 0x02;
1665 i2c_w1(gspca_dev, 0x01, value);
1666 break;
1667 }
1668 return 0;
1669}
1670
1671static int set_exposure(struct gspca_dev *gspca_dev)
1672{
1673 struct sd *sd = (struct sd *) gspca_dev;
1674 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1675 switch (sd->sensor) {
1676 case SENSOR_OV7660:
1677 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001678 case SENSOR_OV9655:
1679 case SENSOR_OV9650:
1680 exp[0] |= (3 << 4);
1681 exp[2] = 0x2d;
1682 exp[3] = sd->exposure & 0xff;
1683 exp[4] = sd->exposure >> 8;
1684 break;
1685 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001687 case SENSOR_MT9V011:
1688 exp[0] |= (3 << 4);
1689 exp[2] = 0x09;
1690 exp[3] = sd->exposure >> 8;
1691 exp[4] = sd->exposure & 0xff;
1692 break;
1693 case SENSOR_HV7131R:
1694 exp[0] |= (4 << 4);
1695 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001696 exp[3] = (sd->exposure >> 5) & 0xff;
1697 exp[4] = (sd->exposure << 3) & 0xff;
1698 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001699 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001700 default:
1701 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001702 }
1703 i2c_w(gspca_dev, exp);
1704 return 0;
1705}
1706
1707static int set_gain(struct gspca_dev *gspca_dev)
1708{
1709 struct sd *sd = (struct sd *) gspca_dev;
1710 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1711 switch (sd->sensor) {
1712 case SENSOR_OV7660:
1713 case SENSOR_OV7670:
1714 case SENSOR_SOI968:
1715 case SENSOR_OV9655:
1716 case SENSOR_OV9650:
1717 gain[0] |= (2 << 4);
1718 gain[3] = ov_gain[sd->gain];
1719 break;
1720 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001721 gain[0] |= (3 << 4);
1722 gain[2] = 0x35;
1723 gain[3] = micron1_gain[sd->gain] >> 8;
1724 gain[4] = micron1_gain[sd->gain] & 0xff;
1725 break;
1726 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001727 gain[0] |= (3 << 4);
1728 gain[2] = 0x2f;
1729 gain[3] = micron1_gain[sd->gain] >> 8;
1730 gain[4] = micron1_gain[sd->gain] & 0xff;
1731 break;
1732 case SENSOR_MT9M001:
1733 gain[0] |= (3 << 4);
1734 gain[2] = 0x2f;
1735 gain[3] = micron2_gain[sd->gain] >> 8;
1736 gain[4] = micron2_gain[sd->gain] & 0xff;
1737 break;
1738 case SENSOR_HV7131R:
1739 gain[0] |= (2 << 4);
1740 gain[2] = 0x30;
1741 gain[3] = hv7131r_gain[sd->gain];
1742 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001743 default:
1744 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001745 }
1746 i2c_w(gspca_dev, gain);
1747 return 0;
1748}
1749
1750static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1751{
1752 struct sd *sd = (struct sd *) gspca_dev;
1753
1754 sd->brightness = val;
1755 if (gspca_dev->streaming)
1756 return set_cmatrix(gspca_dev);
1757 return 0;
1758}
1759
1760static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1761{
1762 struct sd *sd = (struct sd *) gspca_dev;
1763 *val = sd->brightness;
1764 return 0;
1765}
1766
1767
1768static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1769{
1770 struct sd *sd = (struct sd *) gspca_dev;
1771
1772 sd->contrast = val;
1773 if (gspca_dev->streaming)
1774 return set_cmatrix(gspca_dev);
1775 return 0;
1776}
1777
1778static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1779{
1780 struct sd *sd = (struct sd *) gspca_dev;
1781 *val = sd->contrast;
1782 return 0;
1783}
1784
1785static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1786{
1787 struct sd *sd = (struct sd *) gspca_dev;
1788
1789 sd->saturation = val;
1790 if (gspca_dev->streaming)
1791 return set_cmatrix(gspca_dev);
1792 return 0;
1793}
1794
1795static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1796{
1797 struct sd *sd = (struct sd *) gspca_dev;
1798 *val = sd->saturation;
1799 return 0;
1800}
1801
1802static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1803{
1804 struct sd *sd = (struct sd *) gspca_dev;
1805
1806 sd->hue = val;
1807 if (gspca_dev->streaming)
1808 return set_cmatrix(gspca_dev);
1809 return 0;
1810}
1811
1812static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1813{
1814 struct sd *sd = (struct sd *) gspca_dev;
1815 *val = sd->hue;
1816 return 0;
1817}
1818
1819static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1820{
1821 struct sd *sd = (struct sd *) gspca_dev;
1822
1823 sd->gamma = val;
1824 if (gspca_dev->streaming)
1825 return set_gamma(gspca_dev);
1826 return 0;
1827}
1828
1829static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1830{
1831 struct sd *sd = (struct sd *) gspca_dev;
1832 *val = sd->gamma;
1833 return 0;
1834}
1835
1836static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1837{
1838 struct sd *sd = (struct sd *) gspca_dev;
1839
1840 sd->red = val;
1841 if (gspca_dev->streaming)
1842 return set_redblue(gspca_dev);
1843 return 0;
1844}
1845
1846static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1847{
1848 struct sd *sd = (struct sd *) gspca_dev;
1849 *val = sd->red;
1850 return 0;
1851}
1852
1853static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1854{
1855 struct sd *sd = (struct sd *) gspca_dev;
1856
1857 sd->blue = val;
1858 if (gspca_dev->streaming)
1859 return set_redblue(gspca_dev);
1860 return 0;
1861}
1862
1863static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1864{
1865 struct sd *sd = (struct sd *) gspca_dev;
1866 *val = sd->blue;
1867 return 0;
1868}
1869
1870static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1871{
1872 struct sd *sd = (struct sd *) gspca_dev;
1873
1874 sd->hflip = val;
1875 if (gspca_dev->streaming)
1876 return set_hvflip(gspca_dev);
1877 return 0;
1878}
1879
1880static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1881{
1882 struct sd *sd = (struct sd *) gspca_dev;
1883 *val = sd->hflip;
1884 return 0;
1885}
1886
1887static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1888{
1889 struct sd *sd = (struct sd *) gspca_dev;
1890
1891 sd->vflip = val;
1892 if (gspca_dev->streaming)
1893 return set_hvflip(gspca_dev);
1894 return 0;
1895}
1896
1897static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1898{
1899 struct sd *sd = (struct sd *) gspca_dev;
1900 *val = sd->vflip;
1901 return 0;
1902}
1903
1904static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1905{
1906 struct sd *sd = (struct sd *) gspca_dev;
1907
1908 sd->exposure = val;
1909 if (gspca_dev->streaming)
1910 return set_exposure(gspca_dev);
1911 return 0;
1912}
1913
1914static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1915{
1916 struct sd *sd = (struct sd *) gspca_dev;
1917 *val = sd->exposure;
1918 return 0;
1919}
1920
1921static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1922{
1923 struct sd *sd = (struct sd *) gspca_dev;
1924
1925 sd->gain = val;
1926 if (gspca_dev->streaming)
1927 return set_gain(gspca_dev);
1928 return 0;
1929}
1930
1931static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1932{
1933 struct sd *sd = (struct sd *) gspca_dev;
1934 *val = sd->gain;
1935 return 0;
1936}
1937
1938static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1939{
1940 struct sd *sd = (struct sd *) gspca_dev;
1941 sd->auto_exposure = val;
1942 return 0;
1943}
1944
1945static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1946{
1947 struct sd *sd = (struct sd *) gspca_dev;
1948 *val = sd->auto_exposure;
1949 return 0;
1950}
1951
1952#ifdef CONFIG_VIDEO_ADV_DEBUG
1953static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1954 struct v4l2_dbg_register *reg)
1955{
1956 struct sd *sd = (struct sd *) gspca_dev;
1957 switch (reg->match.type) {
1958 case V4L2_CHIP_MATCH_HOST:
1959 if (reg->match.addr != 0)
1960 return -EINVAL;
1961 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1962 return -EINVAL;
1963 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1964 return -EINVAL;
1965 reg->val = gspca_dev->usb_buf[0];
1966 return 0;
1967 case V4L2_CHIP_MATCH_I2C_ADDR:
1968 if (reg->match.addr != sd->i2c_addr)
1969 return -EINVAL;
1970 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001971 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001972 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1973 return -EINVAL;
1974 } else {
1975 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1976 return -EINVAL;
1977 }
1978 return 0;
1979 }
1980 return -EINVAL;
1981}
1982
1983static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1984 struct v4l2_dbg_register *reg)
1985{
1986 struct sd *sd = (struct sd *) gspca_dev;
1987 switch (reg->match.type) {
1988 case V4L2_CHIP_MATCH_HOST:
1989 if (reg->match.addr != 0)
1990 return -EINVAL;
1991 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1992 return -EINVAL;
1993 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1994 return -EINVAL;
1995 return 0;
1996 case V4L2_CHIP_MATCH_I2C_ADDR:
1997 if (reg->match.addr != sd->i2c_addr)
1998 return -EINVAL;
1999 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03002000 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002001 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
2002 return -EINVAL;
2003 } else {
2004 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
2005 return -EINVAL;
2006 }
2007 return 0;
2008 }
2009 return -EINVAL;
2010}
2011#endif
2012
2013static int sd_chip_ident(struct gspca_dev *gspca_dev,
2014 struct v4l2_dbg_chip_ident *chip)
2015{
2016 struct sd *sd = (struct sd *) gspca_dev;
2017
2018 switch (chip->match.type) {
2019 case V4L2_CHIP_MATCH_HOST:
2020 if (chip->match.addr != 0)
2021 return -EINVAL;
2022 chip->revision = 0;
2023 chip->ident = V4L2_IDENT_SN9C20X;
2024 return 0;
2025 case V4L2_CHIP_MATCH_I2C_ADDR:
2026 if (chip->match.addr != sd->i2c_addr)
2027 return -EINVAL;
2028 chip->revision = 0;
2029 chip->ident = i2c_ident[sd->sensor];
2030 return 0;
2031 }
2032 return -EINVAL;
2033}
2034
2035static int sd_config(struct gspca_dev *gspca_dev,
2036 const struct usb_device_id *id)
2037{
2038 struct sd *sd = (struct sd *) gspca_dev;
2039 struct cam *cam;
2040
2041 cam = &gspca_dev->cam;
2042
2043 sd->sensor = (id->driver_info >> 8) & 0xff;
2044 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002045 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03002046
2047 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03002048 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002049 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03002050 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002051 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03002052 cam->cam_mode = sxga_mode;
2053 cam->nmodes = ARRAY_SIZE(sxga_mode);
2054 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03002055 case SENSOR_MT9M001:
2056 cam->cam_mode = mono_mode;
2057 cam->nmodes = ARRAY_SIZE(mono_mode);
2058 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002059 default:
2060 cam->cam_mode = vga_mode;
2061 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002062 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002063 }
2064
2065 sd->old_step = 0;
2066 sd->older_step = 0;
2067 sd->exposure_step = 16;
2068
2069 sd->brightness = BRIGHTNESS_DEFAULT;
2070 sd->contrast = CONTRAST_DEFAULT;
2071 sd->saturation = SATURATION_DEFAULT;
2072 sd->hue = HUE_DEFAULT;
2073 sd->gamma = GAMMA_DEFAULT;
2074 sd->red = RED_DEFAULT;
2075 sd->blue = BLUE_DEFAULT;
2076
2077 sd->hflip = HFLIP_DEFAULT;
2078 sd->vflip = VFLIP_DEFAULT;
2079 sd->exposure = EXPOSURE_DEFAULT;
2080 sd->gain = GAIN_DEFAULT;
2081 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2082
2083 sd->quality = 95;
2084
Brian Johnson26e744b2009-07-19 05:52:58 -03002085 return 0;
2086}
2087
2088static int sd_init(struct gspca_dev *gspca_dev)
2089{
2090 struct sd *sd = (struct sd *) gspca_dev;
2091 int i;
2092 u8 value;
2093 u8 i2c_init[9] =
2094 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2095
2096 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2097 value = bridge_init[i][1];
2098 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2099 err("Device initialization failed");
2100 return -ENODEV;
2101 }
2102 }
2103
Brian Johnson0c045eb2010-03-16 13:58:27 -03002104 if (sd->flags & LED_REVERSE)
2105 reg_w1(gspca_dev, 0x1006, 0x00);
2106 else
2107 reg_w1(gspca_dev, 0x1006, 0x20);
2108
Brian Johnson26e744b2009-07-19 05:52:58 -03002109 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2110 err("Device initialization failed");
2111 return -ENODEV;
2112 }
2113
2114 switch (sd->sensor) {
2115 case SENSOR_OV9650:
2116 if (ov9650_init_sensor(gspca_dev) < 0)
2117 return -ENODEV;
2118 info("OV9650 sensor detected");
2119 break;
2120 case SENSOR_OV9655:
2121 if (ov9655_init_sensor(gspca_dev) < 0)
2122 return -ENODEV;
2123 info("OV9655 sensor detected");
2124 break;
2125 case SENSOR_SOI968:
2126 if (soi968_init_sensor(gspca_dev) < 0)
2127 return -ENODEV;
2128 info("SOI968 sensor detected");
2129 break;
2130 case SENSOR_OV7660:
2131 if (ov7660_init_sensor(gspca_dev) < 0)
2132 return -ENODEV;
2133 info("OV7660 sensor detected");
2134 break;
2135 case SENSOR_OV7670:
2136 if (ov7670_init_sensor(gspca_dev) < 0)
2137 return -ENODEV;
2138 info("OV7670 sensor detected");
2139 break;
2140 case SENSOR_MT9VPRB:
2141 if (mt9v_init_sensor(gspca_dev) < 0)
2142 return -ENODEV;
2143 break;
2144 case SENSOR_MT9M111:
2145 if (mt9m111_init_sensor(gspca_dev) < 0)
2146 return -ENODEV;
2147 info("MT9M111 sensor detected");
2148 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002149 case SENSOR_MT9M112:
2150 if (mt9m112_init_sensor(gspca_dev) < 0)
2151 return -ENODEV;
2152 info("MT9M112 sensor detected");
2153 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002154 case SENSOR_MT9M001:
2155 if (mt9m001_init_sensor(gspca_dev) < 0)
2156 return -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03002157 break;
2158 case SENSOR_HV7131R:
2159 if (hv7131r_init_sensor(gspca_dev) < 0)
2160 return -ENODEV;
2161 info("HV7131R sensor detected");
2162 break;
2163 default:
2164 info("Unsupported Sensor");
2165 return -ENODEV;
2166 }
2167
2168 return 0;
2169}
2170
2171static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2172{
2173 struct sd *sd = (struct sd *) gspca_dev;
2174 u8 value;
2175 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002176 case SENSOR_SOI968:
2177 if (mode & MODE_SXGA) {
2178 i2c_w1(gspca_dev, 0x17, 0x1d);
2179 i2c_w1(gspca_dev, 0x18, 0xbd);
2180 i2c_w1(gspca_dev, 0x19, 0x01);
2181 i2c_w1(gspca_dev, 0x1a, 0x81);
2182 i2c_w1(gspca_dev, 0x12, 0x00);
2183 sd->hstart = 140;
2184 sd->vstart = 19;
2185 } else {
2186 i2c_w1(gspca_dev, 0x17, 0x13);
2187 i2c_w1(gspca_dev, 0x18, 0x63);
2188 i2c_w1(gspca_dev, 0x19, 0x01);
2189 i2c_w1(gspca_dev, 0x1a, 0x79);
2190 i2c_w1(gspca_dev, 0x12, 0x40);
2191 sd->hstart = 60;
2192 sd->vstart = 11;
2193 }
2194 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002195 case SENSOR_OV9650:
2196 if (mode & MODE_SXGA) {
2197 i2c_w1(gspca_dev, 0x17, 0x1b);
2198 i2c_w1(gspca_dev, 0x18, 0xbc);
2199 i2c_w1(gspca_dev, 0x19, 0x01);
2200 i2c_w1(gspca_dev, 0x1a, 0x82);
2201 i2c_r1(gspca_dev, 0x12, &value);
2202 i2c_w1(gspca_dev, 0x12, value & 0x07);
2203 } else {
2204 i2c_w1(gspca_dev, 0x17, 0x24);
2205 i2c_w1(gspca_dev, 0x18, 0xc5);
2206 i2c_w1(gspca_dev, 0x19, 0x00);
2207 i2c_w1(gspca_dev, 0x1a, 0x3c);
2208 i2c_r1(gspca_dev, 0x12, &value);
2209 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2210 }
2211 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002212 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002213 case SENSOR_MT9M111:
2214 if (mode & MODE_SXGA) {
2215 i2c_w2(gspca_dev, 0xf0, 0x0002);
2216 i2c_w2(gspca_dev, 0xc8, 0x970b);
2217 i2c_w2(gspca_dev, 0xf0, 0x0000);
2218 } else {
2219 i2c_w2(gspca_dev, 0xf0, 0x0002);
2220 i2c_w2(gspca_dev, 0xc8, 0x8000);
2221 i2c_w2(gspca_dev, 0xf0, 0x0000);
2222 }
2223 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002224 }
2225}
2226
2227#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002228((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002229(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2230(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2231
2232#define CLR_WIN(width, height) \
2233((const u8 [])\
2234{0, width >> 2, 0, height >> 1,\
2235((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2236
2237static int sd_start(struct gspca_dev *gspca_dev)
2238{
2239 struct sd *sd = (struct sd *) gspca_dev;
2240 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2241 int width = gspca_dev->width;
2242 int height = gspca_dev->height;
2243 u8 fmt, scale = 0;
2244
Brian Johnson26e744b2009-07-19 05:52:58 -03002245 jpeg_define(sd->jpeg_hdr, height, width,
2246 0x21);
2247 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2248
2249 if (mode & MODE_RAW)
2250 fmt = 0x2d;
2251 else if (mode & MODE_JPEG)
2252 fmt = 0x2c;
2253 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002254 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002255
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002256 switch (mode & SCALE_MASK) {
2257 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002258 scale = 0xc0;
2259 info("Set 1280x1024");
2260 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002261 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002262 scale = 0x80;
2263 info("Set 640x480");
2264 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002265 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002266 scale = 0x90;
2267 info("Set 320x240");
2268 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002269 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002270 scale = 0xa0;
2271 info("Set 160x120");
2272 break;
2273 }
2274
2275 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002276 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2277 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002278 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2279 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2280 reg_w1(gspca_dev, 0x1189, scale);
2281 reg_w1(gspca_dev, 0x10e0, fmt);
2282
2283 set_cmatrix(gspca_dev);
2284 set_gamma(gspca_dev);
2285 set_redblue(gspca_dev);
2286 set_gain(gspca_dev);
2287 set_exposure(gspca_dev);
2288 set_hvflip(gspca_dev);
2289
Brian Johnson0c045eb2010-03-16 13:58:27 -03002290 reg_w1(gspca_dev, 0x1007, 0x20);
2291
Brian Johnson26e744b2009-07-19 05:52:58 -03002292 reg_r(gspca_dev, 0x1061, 1);
2293 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2294 return 0;
2295}
2296
2297static void sd_stopN(struct gspca_dev *gspca_dev)
2298{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002299 reg_w1(gspca_dev, 0x1007, 0x00);
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}
2304
Brian Johnsone1430472009-09-02 12:39:41 -03002305static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002306{
2307 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002308 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002309
2310 /*
2311 * some hardcoded values are present
2312 * like those for maximal/minimal exposure
2313 * and exposure steps
2314 */
2315 if (avg_lum < MIN_AVG_LUM) {
2316 if (sd->exposure > 0x1770)
2317 return;
2318
2319 new_exp = sd->exposure + sd->exposure_step;
2320 if (new_exp > 0x1770)
2321 new_exp = 0x1770;
2322 if (new_exp < 0x10)
2323 new_exp = 0x10;
2324 sd->exposure = new_exp;
2325 set_exposure(gspca_dev);
2326
2327 sd->older_step = sd->old_step;
2328 sd->old_step = 1;
2329
2330 if (sd->old_step ^ sd->older_step)
2331 sd->exposure_step /= 2;
2332 else
2333 sd->exposure_step += 2;
2334 }
2335 if (avg_lum > MAX_AVG_LUM) {
2336 if (sd->exposure < 0x10)
2337 return;
2338 new_exp = sd->exposure - sd->exposure_step;
2339 if (new_exp > 0x1700)
2340 new_exp = 0x1770;
2341 if (new_exp < 0x10)
2342 new_exp = 0x10;
2343 sd->exposure = new_exp;
2344 set_exposure(gspca_dev);
2345 sd->older_step = sd->old_step;
2346 sd->old_step = 0;
2347
2348 if (sd->old_step ^ sd->older_step)
2349 sd->exposure_step /= 2;
2350 else
2351 sd->exposure_step += 2;
2352 }
2353}
2354
Brian Johnsone1430472009-09-02 12:39:41 -03002355static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2356{
2357 struct sd *sd = (struct sd *) gspca_dev;
2358
2359 if (avg_lum < MIN_AVG_LUM) {
2360 if (sd->gain + 1 <= 28) {
2361 sd->gain++;
2362 set_gain(gspca_dev);
2363 }
2364 }
2365 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002366 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002367 sd->gain--;
2368 set_gain(gspca_dev);
2369 }
2370 }
2371}
2372
2373static void sd_dqcallback(struct gspca_dev *gspca_dev)
2374{
2375 struct sd *sd = (struct sd *) gspca_dev;
2376 int avg_lum;
2377
2378 if (!sd->auto_exposure)
2379 return;
2380
2381 avg_lum = atomic_read(&sd->avg_lum);
2382 if (sd->sensor == SENSOR_SOI968)
2383 do_autogain(gspca_dev, avg_lum);
2384 else
2385 do_autoexposure(gspca_dev, avg_lum);
2386}
2387
Jean-François Moine28566432010-10-01 07:33:26 -03002388#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002389static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2390 u8 *data, /* interrupt packet */
2391 int len) /* interrupt packet length */
2392{
2393 struct sd *sd = (struct sd *) gspca_dev;
2394 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002395 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002396 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2397 input_sync(gspca_dev->input_dev);
2398 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2399 input_sync(gspca_dev->input_dev);
2400 ret = 0;
2401 }
2402 return ret;
2403}
2404#endif
2405
Brian Johnson26e744b2009-07-19 05:52:58 -03002406static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002407 u8 *data, /* isoc packet */
2408 int len) /* iso packet length */
2409{
2410 struct sd *sd = (struct sd *) gspca_dev;
2411 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002412 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002413 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2414 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2415 avg_lum = ((data[35] >> 2) & 3) |
2416 (data[20] << 2) |
2417 (data[19] << 10);
2418 avg_lum += ((data[35] >> 4) & 3) |
2419 (data[22] << 2) |
2420 (data[21] << 10);
2421 avg_lum += ((data[35] >> 6) & 3) |
2422 (data[24] << 2) |
2423 (data[23] << 10);
2424 avg_lum += (data[36] & 3) |
2425 (data[26] << 2) |
2426 (data[25] << 10);
2427 avg_lum += ((data[36] >> 2) & 3) |
2428 (data[28] << 2) |
2429 (data[27] << 10);
2430 avg_lum += ((data[36] >> 4) & 3) |
2431 (data[30] << 2) |
2432 (data[29] << 10);
2433 avg_lum += ((data[36] >> 6) & 3) |
2434 (data[32] << 2) |
2435 (data[31] << 10);
2436 avg_lum += ((data[44] >> 4) & 3) |
2437 (data[34] << 2) |
2438 (data[33] << 10);
2439 avg_lum >>= 9;
2440 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002441 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Brian Johnson26e744b2009-07-19 05:52:58 -03002442 return;
2443 }
2444 if (gspca_dev->last_packet_type == LAST_PACKET) {
2445 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2446 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002447 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002448 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002449 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002450 data, len);
2451 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002452 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002453 data, len);
2454 }
2455 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002456 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002457 }
2458}
2459
2460/* sub-driver description */
2461static const struct sd_desc sd_desc = {
2462 .name = MODULE_NAME,
2463 .ctrls = sd_ctrls,
2464 .nctrls = ARRAY_SIZE(sd_ctrls),
2465 .config = sd_config,
2466 .init = sd_init,
2467 .start = sd_start,
2468 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002469 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002470#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002471 .int_pkt_scan = sd_int_pkt_scan,
2472#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002473 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002474#ifdef CONFIG_VIDEO_ADV_DEBUG
2475 .set_register = sd_dbg_s_register,
2476 .get_register = sd_dbg_g_register,
2477#endif
2478 .get_chip_ident = sd_chip_ident,
2479};
2480
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002481#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002482 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002483 | (SENSOR_ ## sensor << 8) \
2484 | (i2c_addr)
2485
Jean-François Moine95c967c2011-01-13 05:20:29 -03002486static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002487 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2488 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2489 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002490 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002491 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2492 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2493 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002494 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2495 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2496 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2497 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002498 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002499 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2500 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2501 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2502 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002503 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002504 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002505 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2506 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2507 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2508 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2509 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002510 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002511 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2512 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2513 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2514 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002515 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2516 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002517 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2518 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2519 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2520 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002521 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002522 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2523 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2524 {}
2525};
2526MODULE_DEVICE_TABLE(usb, device_table);
2527
2528/* -- device connect -- */
2529static int sd_probe(struct usb_interface *intf,
2530 const struct usb_device_id *id)
2531{
2532 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2533 THIS_MODULE);
2534}
2535
Brian Johnson26e744b2009-07-19 05:52:58 -03002536static struct usb_driver sd_driver = {
2537 .name = MODULE_NAME,
2538 .id_table = device_table,
2539 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002540 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002541#ifdef CONFIG_PM
2542 .suspend = gspca_suspend,
2543 .resume = gspca_resume,
2544 .reset_resume = gspca_resume,
2545#endif
2546};
2547
2548/* -- module insert / remove -- */
2549static int __init sd_mod_init(void)
2550{
Jean-François Moine54826432010-09-13 04:53:03 -03002551 return usb_register(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002552}
2553static void __exit sd_mod_exit(void)
2554{
2555 usb_deregister(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002556}
2557
2558module_init(sd_mod_init);
2559module_exit(sd_mod_exit);