blob: fcf29897b71308f9148ddf40bdb515497e09f5c6 [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},
887 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
888 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
889 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
890};
891
Joe Perches58aa68c2009-09-02 01:12:13 -0300892static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300893 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
894 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
895 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
896 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
897 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
898 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
899 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
900 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
901 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
902 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
903 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
904 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
905 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
906 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
907 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
908 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
909 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
910 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
911 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
912 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
913 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
914 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
915 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
916 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
917 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
918 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
919 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
920 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
921 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
922 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
923 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
924 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
925 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
926 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
927 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
928 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
929 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
930 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
931 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
932 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
933 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
934 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
935 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
936 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
937 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
938 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
939 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
940 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
941 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
942 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
943 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
944 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
945 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
946 {0x93, 0x00},
947};
948
Joe Perches58aa68c2009-09-02 01:12:13 -0300949static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300950 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
951 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
952 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
953 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
954 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
955 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
956 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
957 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
958 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
959 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
960 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
961 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
962 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
963 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
964 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
965 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
966 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
967 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
968 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
969 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
970 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
971 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
972 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
973 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
974 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
975 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
976 {0xaa, 0x92}, {0xab, 0x0a},
977};
978
Joe Perches58aa68c2009-09-02 01:12:13 -0300979static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300980 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
981 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
982 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
983 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
984 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
985 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
986 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
987 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
988 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
989 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
990 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
991 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
992 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
993 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
994 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
995 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300996 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300997 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
998 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300999 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001000 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
1001 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
1002 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
1003 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -03001004};
1005
Joe Perches58aa68c2009-09-02 01:12:13 -03001006static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001007 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
1008 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
1009 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
1010 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1011 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1012 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1013 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1014 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1015 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1016 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1017 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1018 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1019 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1020 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1021 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1022 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1023};
1024
Joe Perches58aa68c2009-09-02 01:12:13 -03001025static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001026 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001027 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1028 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1029 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1030 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1031 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1032 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001033};
1034
Joe Perches58aa68c2009-09-02 01:12:13 -03001035static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001036 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1037 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1038 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1039 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1040 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1041 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1042 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1043 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1044 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1045 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1046 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1047 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1048 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1049 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1050 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1051 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1052 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1053 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1054 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1055 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1056 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1057 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1058 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1059 {0x06, 0x0029}, {0x05, 0x0009},
1060};
1061
Joe Perches58aa68c2009-09-02 01:12:13 -03001062static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001063 {0x0d, 0x0001},
1064 {0x0d, 0x0000},
1065 {0x04, 0x0500}, /* hres = 1280 */
1066 {0x03, 0x0400}, /* vres = 1024 */
1067 {0x20, 0x1100},
1068 {0x06, 0x0010},
1069 {0x2b, 0x0024},
1070 {0x2e, 0x0024},
1071 {0x35, 0x0024},
1072 {0x2d, 0x0020},
1073 {0x2c, 0x0020},
1074 {0x09, 0x0ad4},
1075 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001076};
1077
Joe Perches58aa68c2009-09-02 01:12:13 -03001078static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001079 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1080 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001081 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1082 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001083};
1084
Brian Johnsone99ac542010-03-16 13:58:28 -03001085static struct i2c_reg_u16 mt9m112_init[] = {
1086 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1087 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1088 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1089 {0xf0, 0x0000},
1090};
1091
Joe Perches58aa68c2009-09-02 01:12:13 -03001092static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001093 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1094 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1095 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1096 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1097 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1098 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1099 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1100 {0x23, 0x09}, {0x01, 0x08},
1101};
1102
Joe Perches58aa68c2009-09-02 01:12:13 -03001103static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001104{
1105 struct usb_device *dev = gspca_dev->dev;
1106 int result;
1107 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1108 0x00,
1109 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1110 reg,
1111 0x00,
1112 gspca_dev->usb_buf,
1113 length,
1114 500);
1115 if (unlikely(result < 0 || result != length)) {
1116 err("Read register failed 0x%02X", reg);
1117 return -EIO;
1118 }
1119 return 0;
1120}
1121
Joe Perches58aa68c2009-09-02 01:12:13 -03001122static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1123 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001124{
1125 struct usb_device *dev = gspca_dev->dev;
1126 int result;
1127 memcpy(gspca_dev->usb_buf, buffer, length);
1128 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1129 0x08,
1130 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1131 reg,
1132 0x00,
1133 gspca_dev->usb_buf,
1134 length,
1135 500);
1136 if (unlikely(result < 0 || result != length)) {
1137 err("Write register failed index 0x%02X", reg);
1138 return -EIO;
1139 }
1140 return 0;
1141}
1142
Joe Perches58aa68c2009-09-02 01:12:13 -03001143static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001144{
1145 u8 data[1] = {value};
1146 return reg_w(gspca_dev, reg, data, 1);
1147}
1148
Joe Perches58aa68c2009-09-02 01:12:13 -03001149static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001150{
1151 int i;
1152 reg_w(gspca_dev, 0x10c0, buffer, 8);
1153 for (i = 0; i < 5; i++) {
1154 reg_r(gspca_dev, 0x10c0, 1);
1155 if (gspca_dev->usb_buf[0] & 0x04) {
1156 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001157 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001158 return 0;
1159 }
1160 msleep(1);
1161 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001162 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001163}
1164
Joe Perches58aa68c2009-09-02 01:12:13 -03001165static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001166{
1167 struct sd *sd = (struct sd *) gspca_dev;
1168
1169 u8 row[8];
1170
1171 /*
1172 * from the point of view of the bridge, the length
1173 * includes the address
1174 */
1175 row[0] = 0x81 | (2 << 4);
1176 row[1] = sd->i2c_addr;
1177 row[2] = reg;
1178 row[3] = val;
1179 row[4] = 0x00;
1180 row[5] = 0x00;
1181 row[6] = 0x00;
1182 row[7] = 0x10;
1183
1184 return i2c_w(gspca_dev, row);
1185}
1186
Joe Perches58aa68c2009-09-02 01:12:13 -03001187static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001188{
1189 struct sd *sd = (struct sd *) gspca_dev;
1190 u8 row[8];
1191
1192 /*
1193 * from the point of view of the bridge, the length
1194 * includes the address
1195 */
1196 row[0] = 0x81 | (3 << 4);
1197 row[1] = sd->i2c_addr;
1198 row[2] = reg;
1199 row[3] = (val >> 8) & 0xff;
1200 row[4] = val & 0xff;
1201 row[5] = 0x00;
1202 row[6] = 0x00;
1203 row[7] = 0x10;
1204
1205 return i2c_w(gspca_dev, row);
1206}
1207
Jean-Francois Moine83955552009-12-12 06:58:01 -03001208static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001209{
1210 struct sd *sd = (struct sd *) gspca_dev;
1211 u8 row[8];
1212
Brian Johnson00b581e2009-07-23 05:55:43 -03001213 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001214 row[1] = sd->i2c_addr;
1215 row[2] = reg;
1216 row[3] = 0;
1217 row[4] = 0;
1218 row[5] = 0;
1219 row[6] = 0;
1220 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001221 if (i2c_w(gspca_dev, row) < 0)
1222 return -EIO;
1223 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001224 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001225 if (i2c_w(gspca_dev, row) < 0)
1226 return -EIO;
1227 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1228 return -EIO;
1229 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001230 return 0;
1231}
1232
Jean-Francois Moine83955552009-12-12 06:58:01 -03001233static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001234{
1235 struct sd *sd = (struct sd *) gspca_dev;
1236 u8 row[8];
1237
Brian Johnson00b581e2009-07-23 05:55:43 -03001238 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001239 row[1] = sd->i2c_addr;
1240 row[2] = reg;
1241 row[3] = 0;
1242 row[4] = 0;
1243 row[5] = 0;
1244 row[6] = 0;
1245 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001246 if (i2c_w(gspca_dev, row) < 0)
1247 return -EIO;
1248 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001249 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001250 if (i2c_w(gspca_dev, row) < 0)
1251 return -EIO;
1252 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1253 return -EIO;
1254 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001255 return 0;
1256}
1257
1258static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1259{
1260 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001261 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001262 struct sd *sd = (struct sd *) gspca_dev;
1263
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001264 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1265 return -EINVAL;
1266
1267 if (id != 0x7fa2) {
1268 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1269 return -ENODEV;
1270 }
1271
Brian Johnson26e744b2009-07-19 05:52:58 -03001272 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001273 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1274 ov9650_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001275 err("OV9650 sensor initialization failed");
1276 return -ENODEV;
1277 }
1278 }
1279 sd->hstart = 1;
1280 sd->vstart = 7;
1281 return 0;
1282}
1283
1284static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1285{
1286 int i;
1287 struct sd *sd = (struct sd *) gspca_dev;
1288
1289 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001290 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1291 ov9655_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001292 err("OV9655 sensor initialization failed");
1293 return -ENODEV;
1294 }
1295 }
1296 /* disable hflip and vflip */
1297 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001298 sd->hstart = 1;
1299 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001300 return 0;
1301}
1302
1303static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1304{
1305 int i;
1306 struct sd *sd = (struct sd *) gspca_dev;
1307
1308 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001309 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1310 soi968_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001311 err("SOI968 sensor initialization failed");
1312 return -ENODEV;
1313 }
1314 }
1315 /* disable hflip and vflip */
Jean-François Moine780e3122010-10-19 04:29:10 -03001316 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1317 | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001318 sd->hstart = 60;
1319 sd->vstart = 11;
1320 return 0;
1321}
1322
1323static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1324{
1325 int i;
1326 struct sd *sd = (struct sd *) gspca_dev;
1327
1328 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001329 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1330 ov7660_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001331 err("OV7660 sensor initialization failed");
1332 return -ENODEV;
1333 }
1334 }
1335 /* disable hflip and vflip */
1336 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1337 sd->hstart = 1;
1338 sd->vstart = 1;
1339 return 0;
1340}
1341
1342static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1343{
1344 int i;
1345 struct sd *sd = (struct sd *) gspca_dev;
1346
1347 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001348 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1349 ov7670_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001350 err("OV7670 sensor initialization failed");
1351 return -ENODEV;
1352 }
1353 }
1354 /* disable hflip and vflip */
1355 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1356 sd->hstart = 0;
1357 sd->vstart = 1;
1358 return 0;
1359}
1360
1361static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1362{
1363 struct sd *sd = (struct sd *) gspca_dev;
1364 int i;
1365 u16 value;
1366 int ret;
1367
1368 sd->i2c_addr = 0x5d;
1369 ret = i2c_r2(gspca_dev, 0xff, &value);
1370 if ((ret == 0) && (value == 0x8243)) {
1371 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001372 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1373 mt9v011_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001374 err("MT9V011 sensor initialization failed");
1375 return -ENODEV;
1376 }
1377 }
1378 sd->hstart = 2;
1379 sd->vstart = 2;
1380 sd->sensor = SENSOR_MT9V011;
1381 info("MT9V011 sensor detected");
1382 return 0;
1383 }
1384
1385 sd->i2c_addr = 0x5c;
1386 i2c_w2(gspca_dev, 0x01, 0x0004);
1387 ret = i2c_r2(gspca_dev, 0xff, &value);
1388 if ((ret == 0) && (value == 0x823a)) {
1389 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001390 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1391 mt9v111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001392 err("MT9V111 sensor initialization failed");
1393 return -ENODEV;
1394 }
1395 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001396 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1397 | (1 << AUTOGAIN_IDX)
1398 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001399 sd->hstart = 2;
1400 sd->vstart = 2;
1401 sd->sensor = SENSOR_MT9V111;
1402 info("MT9V111 sensor detected");
1403 return 0;
1404 }
1405
1406 sd->i2c_addr = 0x5d;
1407 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1408 if (ret < 0) {
1409 sd->i2c_addr = 0x48;
1410 i2c_w2(gspca_dev, 0xf0, 0x0000);
1411 }
1412 ret = i2c_r2(gspca_dev, 0x00, &value);
1413 if ((ret == 0) && (value == 0x1229)) {
1414 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001415 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1416 mt9v112_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001417 err("MT9V112 sensor initialization failed");
1418 return -ENODEV;
1419 }
1420 }
1421 sd->hstart = 6;
1422 sd->vstart = 2;
1423 sd->sensor = SENSOR_MT9V112;
1424 info("MT9V112 sensor detected");
1425 return 0;
1426 }
1427
1428 return -ENODEV;
1429}
1430
Brian Johnsone99ac542010-03-16 13:58:28 -03001431static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1432{
1433 struct sd *sd = (struct sd *) gspca_dev;
1434 int i;
1435 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1436 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1437 mt9m112_init[i].val) < 0) {
1438 err("MT9M112 sensor initialization failed");
1439 return -ENODEV;
1440 }
1441 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001442 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1443 | (1 << GAIN_IDX);
Brian Johnsone99ac542010-03-16 13:58:28 -03001444 sd->hstart = 0;
1445 sd->vstart = 2;
1446 return 0;
1447}
1448
Brian Johnson26e744b2009-07-19 05:52:58 -03001449static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1450{
1451 struct sd *sd = (struct sd *) gspca_dev;
1452 int i;
1453 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001454 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1455 mt9m111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001456 err("MT9M111 sensor initialization failed");
1457 return -ENODEV;
1458 }
1459 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001460 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1461 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001462 sd->hstart = 0;
1463 sd->vstart = 2;
1464 return 0;
1465}
1466
1467static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1468{
1469 struct sd *sd = (struct sd *) gspca_dev;
1470 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001471 u16 id;
1472
1473 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1474 return -EINVAL;
1475
1476 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1477 switch (id) {
1478 case 0x8411:
1479 case 0x8421:
1480 info("MT9M001 color sensor detected");
1481 break;
1482 case 0x8431:
1483 info("MT9M001 mono sensor detected");
1484 break;
1485 default:
1486 err("No MT9M001 chip detected, ID = %x\n", id);
1487 return -ENODEV;
1488 }
1489
Brian Johnson26e744b2009-07-19 05:52:58 -03001490 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001491 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1492 mt9m001_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001493 err("MT9M001 sensor initialization failed");
1494 return -ENODEV;
1495 }
1496 }
1497 /* disable hflip and vflip */
1498 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001499 sd->hstart = 1;
1500 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501 return 0;
1502}
1503
1504static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1505{
1506 int i;
1507 struct sd *sd = (struct sd *) gspca_dev;
1508
1509 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001510 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1511 hv7131r_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001512 err("HV7131R Sensor initialization failed");
1513 return -ENODEV;
1514 }
1515 }
1516 sd->hstart = 0;
1517 sd->vstart = 1;
1518 return 0;
1519}
1520
Brian Johnson26e744b2009-07-19 05:52:58 -03001521static int set_cmatrix(struct gspca_dev *gspca_dev)
1522{
1523 struct sd *sd = (struct sd *) gspca_dev;
1524 s32 hue_coord, hue_index = 180 + sd->hue;
1525 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001526
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001527 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001528 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1529 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1530 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1531 cmatrix[18] = sd->brightness - 0x80;
1532
1533 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001534 cmatrix[6] = hue_coord;
1535 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001536
1537 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001538 cmatrix[8] = hue_coord;
1539 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001540
1541 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001542 cmatrix[10] = hue_coord;
1543 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001544
1545 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001546 cmatrix[12] = hue_coord;
1547 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001548
1549 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001550 cmatrix[14] = hue_coord;
1551 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001552
1553 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001554 cmatrix[16] = hue_coord;
1555 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001556
1557 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1558}
1559
1560static int set_gamma(struct gspca_dev *gspca_dev)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563 u8 gamma[17];
1564 u8 gval = sd->gamma * 0xb8 / 0x100;
1565
1566
1567 gamma[0] = 0x0a;
1568 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1569 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1570 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1571 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1572 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1573 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1574 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1575 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1576 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1577 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1578 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1579 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1580 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1581 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1582 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1583 gamma[16] = 0xf5;
1584
1585 return reg_w(gspca_dev, 0x1190, gamma, 17);
1586}
1587
1588static int set_redblue(struct gspca_dev *gspca_dev)
1589{
1590 struct sd *sd = (struct sd *) gspca_dev;
1591 reg_w1(gspca_dev, 0x118c, sd->red);
1592 reg_w1(gspca_dev, 0x118f, sd->blue);
1593 return 0;
1594}
1595
1596static int set_hvflip(struct gspca_dev *gspca_dev)
1597{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001598 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001599 u16 value2;
1600 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001601
1602 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1603 hflip = !sd->hflip;
1604 vflip = !sd->vflip;
1605 } else {
1606 hflip = sd->hflip;
1607 vflip = sd->vflip;
1608 }
1609
Brian Johnson26e744b2009-07-19 05:52:58 -03001610 switch (sd->sensor) {
1611 case SENSOR_OV9650:
1612 i2c_r1(gspca_dev, 0x1e, &value);
1613 value &= ~0x30;
1614 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001615 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001616 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001617 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001618 value |= 0x10;
1619 tslb = 0x49;
1620 }
1621 i2c_w1(gspca_dev, 0x1e, value);
1622 i2c_w1(gspca_dev, 0x3a, tslb);
1623 break;
1624 case SENSOR_MT9V111:
1625 case SENSOR_MT9V011:
1626 i2c_r2(gspca_dev, 0x20, &value2);
1627 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001628 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001629 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001630 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001631 value2 |= 0x4020;
1632 i2c_w2(gspca_dev, 0x20, value2);
1633 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001634 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001635 case SENSOR_MT9M111:
1636 case SENSOR_MT9V112:
1637 i2c_r2(gspca_dev, 0x20, &value2);
1638 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001639 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001640 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001641 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001642 value2 |= 0x0001;
1643 i2c_w2(gspca_dev, 0x20, value2);
1644 break;
1645 case SENSOR_HV7131R:
1646 i2c_r1(gspca_dev, 0x01, &value);
1647 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001648 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001649 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001650 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001651 value |= 0x02;
1652 i2c_w1(gspca_dev, 0x01, value);
1653 break;
1654 }
1655 return 0;
1656}
1657
1658static int set_exposure(struct gspca_dev *gspca_dev)
1659{
1660 struct sd *sd = (struct sd *) gspca_dev;
1661 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1662 switch (sd->sensor) {
1663 case SENSOR_OV7660:
1664 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001665 case SENSOR_OV9655:
1666 case SENSOR_OV9650:
1667 exp[0] |= (3 << 4);
1668 exp[2] = 0x2d;
1669 exp[3] = sd->exposure & 0xff;
1670 exp[4] = sd->exposure >> 8;
1671 break;
1672 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001673 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001674 case SENSOR_MT9V011:
1675 exp[0] |= (3 << 4);
1676 exp[2] = 0x09;
1677 exp[3] = sd->exposure >> 8;
1678 exp[4] = sd->exposure & 0xff;
1679 break;
1680 case SENSOR_HV7131R:
1681 exp[0] |= (4 << 4);
1682 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001683 exp[3] = (sd->exposure >> 5) & 0xff;
1684 exp[4] = (sd->exposure << 3) & 0xff;
1685 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001687 default:
1688 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001689 }
1690 i2c_w(gspca_dev, exp);
1691 return 0;
1692}
1693
1694static int set_gain(struct gspca_dev *gspca_dev)
1695{
1696 struct sd *sd = (struct sd *) gspca_dev;
1697 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1698 switch (sd->sensor) {
1699 case SENSOR_OV7660:
1700 case SENSOR_OV7670:
1701 case SENSOR_SOI968:
1702 case SENSOR_OV9655:
1703 case SENSOR_OV9650:
1704 gain[0] |= (2 << 4);
1705 gain[3] = ov_gain[sd->gain];
1706 break;
1707 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001708 gain[0] |= (3 << 4);
1709 gain[2] = 0x35;
1710 gain[3] = micron1_gain[sd->gain] >> 8;
1711 gain[4] = micron1_gain[sd->gain] & 0xff;
1712 break;
1713 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001714 gain[0] |= (3 << 4);
1715 gain[2] = 0x2f;
1716 gain[3] = micron1_gain[sd->gain] >> 8;
1717 gain[4] = micron1_gain[sd->gain] & 0xff;
1718 break;
1719 case SENSOR_MT9M001:
1720 gain[0] |= (3 << 4);
1721 gain[2] = 0x2f;
1722 gain[3] = micron2_gain[sd->gain] >> 8;
1723 gain[4] = micron2_gain[sd->gain] & 0xff;
1724 break;
1725 case SENSOR_HV7131R:
1726 gain[0] |= (2 << 4);
1727 gain[2] = 0x30;
1728 gain[3] = hv7131r_gain[sd->gain];
1729 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001730 default:
1731 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001732 }
1733 i2c_w(gspca_dev, gain);
1734 return 0;
1735}
1736
1737static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1738{
1739 struct sd *sd = (struct sd *) gspca_dev;
1740
1741 sd->brightness = val;
1742 if (gspca_dev->streaming)
1743 return set_cmatrix(gspca_dev);
1744 return 0;
1745}
1746
1747static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1748{
1749 struct sd *sd = (struct sd *) gspca_dev;
1750 *val = sd->brightness;
1751 return 0;
1752}
1753
1754
1755static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1756{
1757 struct sd *sd = (struct sd *) gspca_dev;
1758
1759 sd->contrast = val;
1760 if (gspca_dev->streaming)
1761 return set_cmatrix(gspca_dev);
1762 return 0;
1763}
1764
1765static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1766{
1767 struct sd *sd = (struct sd *) gspca_dev;
1768 *val = sd->contrast;
1769 return 0;
1770}
1771
1772static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1773{
1774 struct sd *sd = (struct sd *) gspca_dev;
1775
1776 sd->saturation = val;
1777 if (gspca_dev->streaming)
1778 return set_cmatrix(gspca_dev);
1779 return 0;
1780}
1781
1782static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1783{
1784 struct sd *sd = (struct sd *) gspca_dev;
1785 *val = sd->saturation;
1786 return 0;
1787}
1788
1789static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1790{
1791 struct sd *sd = (struct sd *) gspca_dev;
1792
1793 sd->hue = val;
1794 if (gspca_dev->streaming)
1795 return set_cmatrix(gspca_dev);
1796 return 0;
1797}
1798
1799static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1800{
1801 struct sd *sd = (struct sd *) gspca_dev;
1802 *val = sd->hue;
1803 return 0;
1804}
1805
1806static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1807{
1808 struct sd *sd = (struct sd *) gspca_dev;
1809
1810 sd->gamma = val;
1811 if (gspca_dev->streaming)
1812 return set_gamma(gspca_dev);
1813 return 0;
1814}
1815
1816static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1817{
1818 struct sd *sd = (struct sd *) gspca_dev;
1819 *val = sd->gamma;
1820 return 0;
1821}
1822
1823static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1824{
1825 struct sd *sd = (struct sd *) gspca_dev;
1826
1827 sd->red = val;
1828 if (gspca_dev->streaming)
1829 return set_redblue(gspca_dev);
1830 return 0;
1831}
1832
1833static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1834{
1835 struct sd *sd = (struct sd *) gspca_dev;
1836 *val = sd->red;
1837 return 0;
1838}
1839
1840static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1841{
1842 struct sd *sd = (struct sd *) gspca_dev;
1843
1844 sd->blue = val;
1845 if (gspca_dev->streaming)
1846 return set_redblue(gspca_dev);
1847 return 0;
1848}
1849
1850static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1851{
1852 struct sd *sd = (struct sd *) gspca_dev;
1853 *val = sd->blue;
1854 return 0;
1855}
1856
1857static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1858{
1859 struct sd *sd = (struct sd *) gspca_dev;
1860
1861 sd->hflip = val;
1862 if (gspca_dev->streaming)
1863 return set_hvflip(gspca_dev);
1864 return 0;
1865}
1866
1867static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1868{
1869 struct sd *sd = (struct sd *) gspca_dev;
1870 *val = sd->hflip;
1871 return 0;
1872}
1873
1874static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1875{
1876 struct sd *sd = (struct sd *) gspca_dev;
1877
1878 sd->vflip = val;
1879 if (gspca_dev->streaming)
1880 return set_hvflip(gspca_dev);
1881 return 0;
1882}
1883
1884static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1885{
1886 struct sd *sd = (struct sd *) gspca_dev;
1887 *val = sd->vflip;
1888 return 0;
1889}
1890
1891static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1892{
1893 struct sd *sd = (struct sd *) gspca_dev;
1894
1895 sd->exposure = val;
1896 if (gspca_dev->streaming)
1897 return set_exposure(gspca_dev);
1898 return 0;
1899}
1900
1901static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1902{
1903 struct sd *sd = (struct sd *) gspca_dev;
1904 *val = sd->exposure;
1905 return 0;
1906}
1907
1908static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1909{
1910 struct sd *sd = (struct sd *) gspca_dev;
1911
1912 sd->gain = val;
1913 if (gspca_dev->streaming)
1914 return set_gain(gspca_dev);
1915 return 0;
1916}
1917
1918static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1919{
1920 struct sd *sd = (struct sd *) gspca_dev;
1921 *val = sd->gain;
1922 return 0;
1923}
1924
1925static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1926{
1927 struct sd *sd = (struct sd *) gspca_dev;
1928 sd->auto_exposure = val;
1929 return 0;
1930}
1931
1932static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1933{
1934 struct sd *sd = (struct sd *) gspca_dev;
1935 *val = sd->auto_exposure;
1936 return 0;
1937}
1938
1939#ifdef CONFIG_VIDEO_ADV_DEBUG
1940static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1941 struct v4l2_dbg_register *reg)
1942{
1943 struct sd *sd = (struct sd *) gspca_dev;
1944 switch (reg->match.type) {
1945 case V4L2_CHIP_MATCH_HOST:
1946 if (reg->match.addr != 0)
1947 return -EINVAL;
1948 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1949 return -EINVAL;
1950 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1951 return -EINVAL;
1952 reg->val = gspca_dev->usb_buf[0];
1953 return 0;
1954 case V4L2_CHIP_MATCH_I2C_ADDR:
1955 if (reg->match.addr != sd->i2c_addr)
1956 return -EINVAL;
1957 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001958 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001959 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1960 return -EINVAL;
1961 } else {
1962 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1963 return -EINVAL;
1964 }
1965 return 0;
1966 }
1967 return -EINVAL;
1968}
1969
1970static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1971 struct v4l2_dbg_register *reg)
1972{
1973 struct sd *sd = (struct sd *) gspca_dev;
1974 switch (reg->match.type) {
1975 case V4L2_CHIP_MATCH_HOST:
1976 if (reg->match.addr != 0)
1977 return -EINVAL;
1978 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1979 return -EINVAL;
1980 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1981 return -EINVAL;
1982 return 0;
1983 case V4L2_CHIP_MATCH_I2C_ADDR:
1984 if (reg->match.addr != sd->i2c_addr)
1985 return -EINVAL;
1986 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001987 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001988 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1989 return -EINVAL;
1990 } else {
1991 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1992 return -EINVAL;
1993 }
1994 return 0;
1995 }
1996 return -EINVAL;
1997}
1998#endif
1999
2000static int sd_chip_ident(struct gspca_dev *gspca_dev,
2001 struct v4l2_dbg_chip_ident *chip)
2002{
2003 struct sd *sd = (struct sd *) gspca_dev;
2004
2005 switch (chip->match.type) {
2006 case V4L2_CHIP_MATCH_HOST:
2007 if (chip->match.addr != 0)
2008 return -EINVAL;
2009 chip->revision = 0;
2010 chip->ident = V4L2_IDENT_SN9C20X;
2011 return 0;
2012 case V4L2_CHIP_MATCH_I2C_ADDR:
2013 if (chip->match.addr != sd->i2c_addr)
2014 return -EINVAL;
2015 chip->revision = 0;
2016 chip->ident = i2c_ident[sd->sensor];
2017 return 0;
2018 }
2019 return -EINVAL;
2020}
2021
2022static int sd_config(struct gspca_dev *gspca_dev,
2023 const struct usb_device_id *id)
2024{
2025 struct sd *sd = (struct sd *) gspca_dev;
2026 struct cam *cam;
2027
2028 cam = &gspca_dev->cam;
2029
2030 sd->sensor = (id->driver_info >> 8) & 0xff;
2031 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002032 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03002033
2034 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03002035 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002036 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03002037 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002038 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03002039 cam->cam_mode = sxga_mode;
2040 cam->nmodes = ARRAY_SIZE(sxga_mode);
2041 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03002042 case SENSOR_MT9M001:
2043 cam->cam_mode = mono_mode;
2044 cam->nmodes = ARRAY_SIZE(mono_mode);
2045 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002046 default:
2047 cam->cam_mode = vga_mode;
2048 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002049 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002050 }
2051
2052 sd->old_step = 0;
2053 sd->older_step = 0;
2054 sd->exposure_step = 16;
2055
2056 sd->brightness = BRIGHTNESS_DEFAULT;
2057 sd->contrast = CONTRAST_DEFAULT;
2058 sd->saturation = SATURATION_DEFAULT;
2059 sd->hue = HUE_DEFAULT;
2060 sd->gamma = GAMMA_DEFAULT;
2061 sd->red = RED_DEFAULT;
2062 sd->blue = BLUE_DEFAULT;
2063
2064 sd->hflip = HFLIP_DEFAULT;
2065 sd->vflip = VFLIP_DEFAULT;
2066 sd->exposure = EXPOSURE_DEFAULT;
2067 sd->gain = GAIN_DEFAULT;
2068 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2069
2070 sd->quality = 95;
2071
Brian Johnson26e744b2009-07-19 05:52:58 -03002072 return 0;
2073}
2074
2075static int sd_init(struct gspca_dev *gspca_dev)
2076{
2077 struct sd *sd = (struct sd *) gspca_dev;
2078 int i;
2079 u8 value;
2080 u8 i2c_init[9] =
2081 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2082
2083 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2084 value = bridge_init[i][1];
2085 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2086 err("Device initialization failed");
2087 return -ENODEV;
2088 }
2089 }
2090
Brian Johnson0c045eb2010-03-16 13:58:27 -03002091 if (sd->flags & LED_REVERSE)
2092 reg_w1(gspca_dev, 0x1006, 0x00);
2093 else
2094 reg_w1(gspca_dev, 0x1006, 0x20);
2095
Brian Johnson26e744b2009-07-19 05:52:58 -03002096 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2097 err("Device initialization failed");
2098 return -ENODEV;
2099 }
2100
2101 switch (sd->sensor) {
2102 case SENSOR_OV9650:
2103 if (ov9650_init_sensor(gspca_dev) < 0)
2104 return -ENODEV;
2105 info("OV9650 sensor detected");
2106 break;
2107 case SENSOR_OV9655:
2108 if (ov9655_init_sensor(gspca_dev) < 0)
2109 return -ENODEV;
2110 info("OV9655 sensor detected");
2111 break;
2112 case SENSOR_SOI968:
2113 if (soi968_init_sensor(gspca_dev) < 0)
2114 return -ENODEV;
2115 info("SOI968 sensor detected");
2116 break;
2117 case SENSOR_OV7660:
2118 if (ov7660_init_sensor(gspca_dev) < 0)
2119 return -ENODEV;
2120 info("OV7660 sensor detected");
2121 break;
2122 case SENSOR_OV7670:
2123 if (ov7670_init_sensor(gspca_dev) < 0)
2124 return -ENODEV;
2125 info("OV7670 sensor detected");
2126 break;
2127 case SENSOR_MT9VPRB:
2128 if (mt9v_init_sensor(gspca_dev) < 0)
2129 return -ENODEV;
2130 break;
2131 case SENSOR_MT9M111:
2132 if (mt9m111_init_sensor(gspca_dev) < 0)
2133 return -ENODEV;
2134 info("MT9M111 sensor detected");
2135 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002136 case SENSOR_MT9M112:
2137 if (mt9m112_init_sensor(gspca_dev) < 0)
2138 return -ENODEV;
2139 info("MT9M112 sensor detected");
2140 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002141 case SENSOR_MT9M001:
2142 if (mt9m001_init_sensor(gspca_dev) < 0)
2143 return -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03002144 break;
2145 case SENSOR_HV7131R:
2146 if (hv7131r_init_sensor(gspca_dev) < 0)
2147 return -ENODEV;
2148 info("HV7131R sensor detected");
2149 break;
2150 default:
2151 info("Unsupported Sensor");
2152 return -ENODEV;
2153 }
2154
2155 return 0;
2156}
2157
2158static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2159{
2160 struct sd *sd = (struct sd *) gspca_dev;
2161 u8 value;
2162 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002163 case SENSOR_SOI968:
2164 if (mode & MODE_SXGA) {
2165 i2c_w1(gspca_dev, 0x17, 0x1d);
2166 i2c_w1(gspca_dev, 0x18, 0xbd);
2167 i2c_w1(gspca_dev, 0x19, 0x01);
2168 i2c_w1(gspca_dev, 0x1a, 0x81);
2169 i2c_w1(gspca_dev, 0x12, 0x00);
2170 sd->hstart = 140;
2171 sd->vstart = 19;
2172 } else {
2173 i2c_w1(gspca_dev, 0x17, 0x13);
2174 i2c_w1(gspca_dev, 0x18, 0x63);
2175 i2c_w1(gspca_dev, 0x19, 0x01);
2176 i2c_w1(gspca_dev, 0x1a, 0x79);
2177 i2c_w1(gspca_dev, 0x12, 0x40);
2178 sd->hstart = 60;
2179 sd->vstart = 11;
2180 }
2181 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002182 case SENSOR_OV9650:
2183 if (mode & MODE_SXGA) {
2184 i2c_w1(gspca_dev, 0x17, 0x1b);
2185 i2c_w1(gspca_dev, 0x18, 0xbc);
2186 i2c_w1(gspca_dev, 0x19, 0x01);
2187 i2c_w1(gspca_dev, 0x1a, 0x82);
2188 i2c_r1(gspca_dev, 0x12, &value);
2189 i2c_w1(gspca_dev, 0x12, value & 0x07);
2190 } else {
2191 i2c_w1(gspca_dev, 0x17, 0x24);
2192 i2c_w1(gspca_dev, 0x18, 0xc5);
2193 i2c_w1(gspca_dev, 0x19, 0x00);
2194 i2c_w1(gspca_dev, 0x1a, 0x3c);
2195 i2c_r1(gspca_dev, 0x12, &value);
2196 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2197 }
2198 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002199 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002200 case SENSOR_MT9M111:
2201 if (mode & MODE_SXGA) {
2202 i2c_w2(gspca_dev, 0xf0, 0x0002);
2203 i2c_w2(gspca_dev, 0xc8, 0x970b);
2204 i2c_w2(gspca_dev, 0xf0, 0x0000);
2205 } else {
2206 i2c_w2(gspca_dev, 0xf0, 0x0002);
2207 i2c_w2(gspca_dev, 0xc8, 0x8000);
2208 i2c_w2(gspca_dev, 0xf0, 0x0000);
2209 }
2210 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002211 }
2212}
2213
2214#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002215((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002216(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2217(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2218
2219#define CLR_WIN(width, height) \
2220((const u8 [])\
2221{0, width >> 2, 0, height >> 1,\
2222((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2223
2224static int sd_start(struct gspca_dev *gspca_dev)
2225{
2226 struct sd *sd = (struct sd *) gspca_dev;
2227 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2228 int width = gspca_dev->width;
2229 int height = gspca_dev->height;
2230 u8 fmt, scale = 0;
2231
Brian Johnson26e744b2009-07-19 05:52:58 -03002232 jpeg_define(sd->jpeg_hdr, height, width,
2233 0x21);
2234 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2235
2236 if (mode & MODE_RAW)
2237 fmt = 0x2d;
2238 else if (mode & MODE_JPEG)
2239 fmt = 0x2c;
2240 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002241 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002242
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002243 switch (mode & SCALE_MASK) {
2244 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002245 scale = 0xc0;
2246 info("Set 1280x1024");
2247 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002248 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002249 scale = 0x80;
2250 info("Set 640x480");
2251 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002252 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002253 scale = 0x90;
2254 info("Set 320x240");
2255 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002256 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002257 scale = 0xa0;
2258 info("Set 160x120");
2259 break;
2260 }
2261
2262 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002263 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2264 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002265 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2266 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2267 reg_w1(gspca_dev, 0x1189, scale);
2268 reg_w1(gspca_dev, 0x10e0, fmt);
2269
2270 set_cmatrix(gspca_dev);
2271 set_gamma(gspca_dev);
2272 set_redblue(gspca_dev);
2273 set_gain(gspca_dev);
2274 set_exposure(gspca_dev);
2275 set_hvflip(gspca_dev);
2276
Brian Johnson0c045eb2010-03-16 13:58:27 -03002277 reg_w1(gspca_dev, 0x1007, 0x20);
2278
Brian Johnson26e744b2009-07-19 05:52:58 -03002279 reg_r(gspca_dev, 0x1061, 1);
2280 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2281 return 0;
2282}
2283
2284static void sd_stopN(struct gspca_dev *gspca_dev)
2285{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002286 reg_w1(gspca_dev, 0x1007, 0x00);
2287
Brian Johnson26e744b2009-07-19 05:52:58 -03002288 reg_r(gspca_dev, 0x1061, 1);
2289 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2290}
2291
Brian Johnsone1430472009-09-02 12:39:41 -03002292static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002293{
2294 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002295 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002296
2297 /*
2298 * some hardcoded values are present
2299 * like those for maximal/minimal exposure
2300 * and exposure steps
2301 */
2302 if (avg_lum < MIN_AVG_LUM) {
2303 if (sd->exposure > 0x1770)
2304 return;
2305
2306 new_exp = sd->exposure + sd->exposure_step;
2307 if (new_exp > 0x1770)
2308 new_exp = 0x1770;
2309 if (new_exp < 0x10)
2310 new_exp = 0x10;
2311 sd->exposure = new_exp;
2312 set_exposure(gspca_dev);
2313
2314 sd->older_step = sd->old_step;
2315 sd->old_step = 1;
2316
2317 if (sd->old_step ^ sd->older_step)
2318 sd->exposure_step /= 2;
2319 else
2320 sd->exposure_step += 2;
2321 }
2322 if (avg_lum > MAX_AVG_LUM) {
2323 if (sd->exposure < 0x10)
2324 return;
2325 new_exp = sd->exposure - sd->exposure_step;
2326 if (new_exp > 0x1700)
2327 new_exp = 0x1770;
2328 if (new_exp < 0x10)
2329 new_exp = 0x10;
2330 sd->exposure = new_exp;
2331 set_exposure(gspca_dev);
2332 sd->older_step = sd->old_step;
2333 sd->old_step = 0;
2334
2335 if (sd->old_step ^ sd->older_step)
2336 sd->exposure_step /= 2;
2337 else
2338 sd->exposure_step += 2;
2339 }
2340}
2341
Brian Johnsone1430472009-09-02 12:39:41 -03002342static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2343{
2344 struct sd *sd = (struct sd *) gspca_dev;
2345
2346 if (avg_lum < MIN_AVG_LUM) {
2347 if (sd->gain + 1 <= 28) {
2348 sd->gain++;
2349 set_gain(gspca_dev);
2350 }
2351 }
2352 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002353 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002354 sd->gain--;
2355 set_gain(gspca_dev);
2356 }
2357 }
2358}
2359
2360static void sd_dqcallback(struct gspca_dev *gspca_dev)
2361{
2362 struct sd *sd = (struct sd *) gspca_dev;
2363 int avg_lum;
2364
2365 if (!sd->auto_exposure)
2366 return;
2367
2368 avg_lum = atomic_read(&sd->avg_lum);
2369 if (sd->sensor == SENSOR_SOI968)
2370 do_autogain(gspca_dev, avg_lum);
2371 else
2372 do_autoexposure(gspca_dev, avg_lum);
2373}
2374
Jean-François Moine28566432010-10-01 07:33:26 -03002375#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002376static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2377 u8 *data, /* interrupt packet */
2378 int len) /* interrupt packet length */
2379{
2380 struct sd *sd = (struct sd *) gspca_dev;
2381 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002382 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002383 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2384 input_sync(gspca_dev->input_dev);
2385 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2386 input_sync(gspca_dev->input_dev);
2387 ret = 0;
2388 }
2389 return ret;
2390}
2391#endif
2392
Brian Johnson26e744b2009-07-19 05:52:58 -03002393static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002394 u8 *data, /* isoc packet */
2395 int len) /* iso packet length */
2396{
2397 struct sd *sd = (struct sd *) gspca_dev;
2398 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002399 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002400 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2401 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2402 avg_lum = ((data[35] >> 2) & 3) |
2403 (data[20] << 2) |
2404 (data[19] << 10);
2405 avg_lum += ((data[35] >> 4) & 3) |
2406 (data[22] << 2) |
2407 (data[21] << 10);
2408 avg_lum += ((data[35] >> 6) & 3) |
2409 (data[24] << 2) |
2410 (data[23] << 10);
2411 avg_lum += (data[36] & 3) |
2412 (data[26] << 2) |
2413 (data[25] << 10);
2414 avg_lum += ((data[36] >> 2) & 3) |
2415 (data[28] << 2) |
2416 (data[27] << 10);
2417 avg_lum += ((data[36] >> 4) & 3) |
2418 (data[30] << 2) |
2419 (data[29] << 10);
2420 avg_lum += ((data[36] >> 6) & 3) |
2421 (data[32] << 2) |
2422 (data[31] << 10);
2423 avg_lum += ((data[44] >> 4) & 3) |
2424 (data[34] << 2) |
2425 (data[33] << 10);
2426 avg_lum >>= 9;
2427 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002428 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Brian Johnson26e744b2009-07-19 05:52:58 -03002429 return;
2430 }
2431 if (gspca_dev->last_packet_type == LAST_PACKET) {
2432 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2433 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002434 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002435 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002436 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002437 data, len);
2438 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002439 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002440 data, len);
2441 }
2442 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002443 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002444 }
2445}
2446
2447/* sub-driver description */
2448static const struct sd_desc sd_desc = {
2449 .name = MODULE_NAME,
2450 .ctrls = sd_ctrls,
2451 .nctrls = ARRAY_SIZE(sd_ctrls),
2452 .config = sd_config,
2453 .init = sd_init,
2454 .start = sd_start,
2455 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002456 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002457#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002458 .int_pkt_scan = sd_int_pkt_scan,
2459#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002460 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002461#ifdef CONFIG_VIDEO_ADV_DEBUG
2462 .set_register = sd_dbg_s_register,
2463 .get_register = sd_dbg_g_register,
2464#endif
2465 .get_chip_ident = sd_chip_ident,
2466};
2467
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002468#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002469 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002470 | (SENSOR_ ## sensor << 8) \
2471 | (i2c_addr)
2472
Jean-François Moine95c967c2011-01-13 05:20:29 -03002473static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002474 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2475 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2476 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002477 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002478 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2479 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2480 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002481 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2482 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2483 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2484 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2485 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
2486 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2487 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2488 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2489 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002490 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002491 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002492 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2493 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2494 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2495 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2496 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002497 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002498 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2499 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2500 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2501 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002502 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2503 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002504 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2505 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2506 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2507 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002508 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002509 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2510 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2511 {}
2512};
2513MODULE_DEVICE_TABLE(usb, device_table);
2514
2515/* -- device connect -- */
2516static int sd_probe(struct usb_interface *intf,
2517 const struct usb_device_id *id)
2518{
2519 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2520 THIS_MODULE);
2521}
2522
Brian Johnson26e744b2009-07-19 05:52:58 -03002523static struct usb_driver sd_driver = {
2524 .name = MODULE_NAME,
2525 .id_table = device_table,
2526 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002527 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002528#ifdef CONFIG_PM
2529 .suspend = gspca_suspend,
2530 .resume = gspca_resume,
2531 .reset_resume = gspca_resume,
2532#endif
2533};
2534
2535/* -- module insert / remove -- */
2536static int __init sd_mod_init(void)
2537{
Jean-François Moine54826432010-09-13 04:53:03 -03002538 return usb_register(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002539}
2540static void __exit sd_mod_exit(void)
2541{
2542 usb_deregister(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002543}
2544
2545module_init(sd_mod_init);
2546module_exit(sd_mod_exit);