blob: e812598a677b8017c2aa47506d5f8acf92b16a77 [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
Joe Perches58aa68c2009-09-02 01:12:13 -0300455static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300456 41, 44, 46, 48, 50, 52, 54, 56,
457 58, 60, 62, 64, 66, 68, 70, 72,
458 74, 76, 78, 80, 81, 83, 85, 87,
459 88, 90, 92, 93, 95, 97, 98, 100,
460 101, 102, 104, 105, 107, 108, 109, 110,
461 112, 113, 114, 115, 116, 117, 118, 119,
462 120, 121, 122, 123, 123, 124, 125, 125,
463 126, 127, 127, 128, 128, 129, 129, 129,
464 130, 130, 130, 130, 131, 131, 131, 131,
465 131, 131, 131, 131, 130, 130, 130, 130,
466 129, 129, 129, 128, 128, 127, 127, 126,
467 125, 125, 124, 123, 122, 122, 121, 120,
468 119, 118, 117, 116, 115, 114, 112, 111,
469 110, 109, 107, 106, 105, 103, 102, 101,
470 99, 98, 96, 94, 93, 91, 90, 88,
471 86, 84, 83, 81, 79, 77, 75, 74,
472 72, 70, 68, 66, 64, 62, 60, 58,
473 56, 54, 52, 49, 47, 45, 43, 41,
474 39, 36, 34, 32, 30, 28, 25, 23,
475 21, 19, 16, 14, 12, 9, 7, 5,
476 3, 0, -1, -3, -6, -8, -10, -12,
477 -15, -17, -19, -22, -24, -26, -28, -30,
478 -33, -35, -37, -39, -41, -44, -46, -48,
479 -50, -52, -54, -56, -58, -60, -62, -64,
480 -66, -68, -70, -72, -74, -76, -78, -80,
481 -81, -83, -85, -87, -88, -90, -92, -93,
482 -95, -97, -98, -100, -101, -102, -104, -105,
483 -107, -108, -109, -110, -112, -113, -114, -115,
484 -116, -117, -118, -119, -120, -121, -122, -123,
485 -123, -124, -125, -125, -126, -127, -127, -128,
486 -128, -128, -128, -128, -128, -128, -128, -128,
487 -128, -128, -128, -128, -128, -128, -128, -128,
488 -128, -128, -128, -128, -128, -128, -128, -128,
489 -128, -127, -127, -126, -125, -125, -124, -123,
490 -122, -122, -121, -120, -119, -118, -117, -116,
491 -115, -114, -112, -111, -110, -109, -107, -106,
492 -105, -103, -102, -101, -99, -98, -96, -94,
493 -93, -91, -90, -88, -86, -84, -83, -81,
494 -79, -77, -75, -74, -72, -70, -68, -66,
495 -64, -62, -60, -58, -56, -54, -52, -49,
496 -47, -45, -43, -41, -39, -36, -34, -32,
497 -30, -28, -25, -23, -21, -19, -16, -14,
498 -12, -9, -7, -5, -3, 0, 1, 3,
499 6, 8, 10, 12, 15, 17, 19, 22,
500 24, 26, 28, 30, 33, 35, 37, 39, 41
501};
502
Joe Perches58aa68c2009-09-02 01:12:13 -0300503static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300504 82, 80, 78, 76, 74, 73, 71, 69,
505 67, 65, 63, 61, 58, 56, 54, 52,
506 50, 48, 46, 44, 41, 39, 37, 35,
507 32, 30, 28, 26, 23, 21, 19, 16,
508 14, 12, 10, 7, 5, 3, 0, -1,
509 -3, -6, -8, -10, -13, -15, -17, -19,
510 -22, -24, -26, -29, -31, -33, -35, -38,
511 -40, -42, -44, -46, -48, -51, -53, -55,
512 -57, -59, -61, -63, -65, -67, -69, -71,
513 -73, -75, -77, -79, -81, -82, -84, -86,
514 -88, -89, -91, -93, -94, -96, -98, -99,
515 -101, -102, -104, -105, -106, -108, -109, -110,
516 -112, -113, -114, -115, -116, -117, -119, -120,
517 -120, -121, -122, -123, -124, -125, -126, -126,
518 -127, -128, -128, -128, -128, -128, -128, -128,
519 -128, -128, -128, -128, -128, -128, -128, -128,
520 -128, -128, -128, -128, -128, -128, -128, -128,
521 -128, -128, -128, -128, -128, -128, -128, -128,
522 -127, -127, -126, -125, -125, -124, -123, -122,
523 -121, -120, -119, -118, -117, -116, -115, -114,
524 -113, -111, -110, -109, -107, -106, -105, -103,
525 -102, -100, -99, -97, -96, -94, -92, -91,
526 -89, -87, -85, -84, -82, -80, -78, -76,
527 -74, -73, -71, -69, -67, -65, -63, -61,
528 -58, -56, -54, -52, -50, -48, -46, -44,
529 -41, -39, -37, -35, -32, -30, -28, -26,
530 -23, -21, -19, -16, -14, -12, -10, -7,
531 -5, -3, 0, 1, 3, 6, 8, 10,
532 13, 15, 17, 19, 22, 24, 26, 29,
533 31, 33, 35, 38, 40, 42, 44, 46,
534 48, 51, 53, 55, 57, 59, 61, 63,
535 65, 67, 69, 71, 73, 75, 77, 79,
536 81, 82, 84, 86, 88, 89, 91, 93,
537 94, 96, 98, 99, 101, 102, 104, 105,
538 106, 108, 109, 110, 112, 113, 114, 115,
539 116, 117, 119, 120, 120, 121, 122, 123,
540 124, 125, 126, 126, 127, 128, 128, 129,
541 129, 130, 130, 131, 131, 131, 131, 132,
542 132, 132, 132, 132, 132, 132, 132, 132,
543 132, 132, 132, 131, 131, 131, 130, 130,
544 130, 129, 129, 128, 127, 127, 126, 125,
545 125, 124, 123, 122, 121, 120, 119, 118,
546 117, 116, 115, 114, 113, 111, 110, 109,
547 107, 106, 105, 103, 102, 100, 99, 97,
548 96, 94, 92, 91, 89, 87, 85, 84, 82
549};
550
Joe Perches58aa68c2009-09-02 01:12:13 -0300551static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300552 -124, -124, -125, -125, -125, -125, -125, -125,
553 -125, -126, -126, -125, -125, -125, -125, -125,
554 -125, -124, -124, -124, -123, -123, -122, -122,
555 -121, -121, -120, -120, -119, -118, -117, -117,
556 -116, -115, -114, -113, -112, -111, -110, -109,
557 -108, -107, -105, -104, -103, -102, -100, -99,
558 -98, -96, -95, -93, -92, -91, -89, -87,
559 -86, -84, -83, -81, -79, -77, -76, -74,
560 -72, -70, -69, -67, -65, -63, -61, -59,
561 -57, -55, -53, -51, -49, -47, -45, -43,
562 -41, -39, -37, -35, -33, -30, -28, -26,
563 -24, -22, -20, -18, -15, -13, -11, -9,
564 -7, -4, -2, 0, 1, 3, 6, 8,
565 10, 12, 14, 17, 19, 21, 23, 25,
566 27, 29, 32, 34, 36, 38, 40, 42,
567 44, 46, 48, 50, 52, 54, 56, 58,
568 60, 62, 64, 66, 68, 70, 71, 73,
569 75, 77, 78, 80, 82, 83, 85, 87,
570 88, 90, 91, 93, 94, 96, 97, 98,
571 100, 101, 102, 104, 105, 106, 107, 108,
572 109, 111, 112, 113, 113, 114, 115, 116,
573 117, 118, 118, 119, 120, 120, 121, 122,
574 122, 123, 123, 124, 124, 124, 125, 125,
575 125, 125, 125, 125, 125, 126, 126, 125,
576 125, 125, 125, 125, 125, 124, 124, 124,
577 123, 123, 122, 122, 121, 121, 120, 120,
578 119, 118, 117, 117, 116, 115, 114, 113,
579 112, 111, 110, 109, 108, 107, 105, 104,
580 103, 102, 100, 99, 98, 96, 95, 93,
581 92, 91, 89, 87, 86, 84, 83, 81,
582 79, 77, 76, 74, 72, 70, 69, 67,
583 65, 63, 61, 59, 57, 55, 53, 51,
584 49, 47, 45, 43, 41, 39, 37, 35,
585 33, 30, 28, 26, 24, 22, 20, 18,
586 15, 13, 11, 9, 7, 4, 2, 0,
587 -1, -3, -6, -8, -10, -12, -14, -17,
588 -19, -21, -23, -25, -27, -29, -32, -34,
589 -36, -38, -40, -42, -44, -46, -48, -50,
590 -52, -54, -56, -58, -60, -62, -64, -66,
591 -68, -70, -71, -73, -75, -77, -78, -80,
592 -82, -83, -85, -87, -88, -90, -91, -93,
593 -94, -96, -97, -98, -100, -101, -102, -104,
594 -105, -106, -107, -108, -109, -111, -112, -113,
595 -113, -114, -115, -116, -117, -118, -118, -119,
596 -120, -120, -121, -122, -122, -123, -123, -124, -124
597};
598
Joe Perches58aa68c2009-09-02 01:12:13 -0300599static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300600 -100, -99, -98, -97, -95, -94, -93, -91,
601 -90, -89, -87, -86, -84, -83, -81, -80,
602 -78, -76, -75, -73, -71, -70, -68, -66,
603 -64, -63, -61, -59, -57, -55, -53, -51,
604 -49, -48, -46, -44, -42, -40, -38, -36,
605 -34, -32, -30, -27, -25, -23, -21, -19,
606 -17, -15, -13, -11, -9, -7, -4, -2,
607 0, 1, 3, 5, 7, 9, 11, 14,
608 16, 18, 20, 22, 24, 26, 28, 30,
609 32, 34, 36, 38, 40, 42, 44, 46,
610 48, 50, 52, 54, 56, 58, 59, 61,
611 63, 65, 67, 68, 70, 72, 74, 75,
612 77, 78, 80, 82, 83, 85, 86, 88,
613 89, 90, 92, 93, 95, 96, 97, 98,
614 100, 101, 102, 103, 104, 105, 106, 107,
615 108, 109, 110, 111, 112, 112, 113, 114,
616 115, 115, 116, 116, 117, 117, 118, 118,
617 119, 119, 119, 120, 120, 120, 120, 120,
618 121, 121, 121, 121, 121, 121, 120, 120,
619 120, 120, 120, 119, 119, 119, 118, 118,
620 117, 117, 116, 116, 115, 114, 114, 113,
621 112, 111, 111, 110, 109, 108, 107, 106,
622 105, 104, 103, 102, 100, 99, 98, 97,
623 95, 94, 93, 91, 90, 89, 87, 86,
624 84, 83, 81, 80, 78, 76, 75, 73,
625 71, 70, 68, 66, 64, 63, 61, 59,
626 57, 55, 53, 51, 49, 48, 46, 44,
627 42, 40, 38, 36, 34, 32, 30, 27,
628 25, 23, 21, 19, 17, 15, 13, 11,
629 9, 7, 4, 2, 0, -1, -3, -5,
630 -7, -9, -11, -14, -16, -18, -20, -22,
631 -24, -26, -28, -30, -32, -34, -36, -38,
632 -40, -42, -44, -46, -48, -50, -52, -54,
633 -56, -58, -59, -61, -63, -65, -67, -68,
634 -70, -72, -74, -75, -77, -78, -80, -82,
635 -83, -85, -86, -88, -89, -90, -92, -93,
636 -95, -96, -97, -98, -100, -101, -102, -103,
637 -104, -105, -106, -107, -108, -109, -110, -111,
638 -112, -112, -113, -114, -115, -115, -116, -116,
639 -117, -117, -118, -118, -119, -119, -119, -120,
640 -120, -120, -120, -120, -121, -121, -121, -121,
641 -121, -121, -120, -120, -120, -120, -120, -119,
642 -119, -119, -118, -118, -117, -117, -116, -116,
643 -115, -114, -114, -113, -112, -111, -111, -110,
644 -109, -108, -107, -106, -105, -104, -103, -102, -100
645};
646
Joe Perches58aa68c2009-09-02 01:12:13 -0300647static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300648 112, 113, 114, 114, 115, 116, 117, 117,
649 118, 118, 119, 119, 120, 120, 120, 121,
650 121, 121, 122, 122, 122, 122, 122, 122,
651 122, 122, 122, 122, 122, 122, 121, 121,
652 121, 120, 120, 120, 119, 119, 118, 118,
653 117, 116, 116, 115, 114, 113, 113, 112,
654 111, 110, 109, 108, 107, 106, 105, 104,
655 103, 102, 100, 99, 98, 97, 95, 94,
656 93, 91, 90, 88, 87, 85, 84, 82,
657 80, 79, 77, 76, 74, 72, 70, 69,
658 67, 65, 63, 61, 60, 58, 56, 54,
659 52, 50, 48, 46, 44, 42, 40, 38,
660 36, 34, 32, 30, 28, 26, 24, 22,
661 19, 17, 15, 13, 11, 9, 7, 5,
662 2, 0, -1, -3, -5, -7, -9, -12,
663 -14, -16, -18, -20, -22, -24, -26, -28,
664 -31, -33, -35, -37, -39, -41, -43, -45,
665 -47, -49, -51, -53, -54, -56, -58, -60,
666 -62, -64, -66, -67, -69, -71, -73, -74,
667 -76, -78, -79, -81, -83, -84, -86, -87,
668 -89, -90, -92, -93, -94, -96, -97, -98,
669 -99, -101, -102, -103, -104, -105, -106, -107,
670 -108, -109, -110, -111, -112, -113, -114, -114,
671 -115, -116, -117, -117, -118, -118, -119, -119,
672 -120, -120, -120, -121, -121, -121, -122, -122,
673 -122, -122, -122, -122, -122, -122, -122, -122,
674 -122, -122, -121, -121, -121, -120, -120, -120,
675 -119, -119, -118, -118, -117, -116, -116, -115,
676 -114, -113, -113, -112, -111, -110, -109, -108,
677 -107, -106, -105, -104, -103, -102, -100, -99,
678 -98, -97, -95, -94, -93, -91, -90, -88,
679 -87, -85, -84, -82, -80, -79, -77, -76,
680 -74, -72, -70, -69, -67, -65, -63, -61,
681 -60, -58, -56, -54, -52, -50, -48, -46,
682 -44, -42, -40, -38, -36, -34, -32, -30,
683 -28, -26, -24, -22, -19, -17, -15, -13,
684 -11, -9, -7, -5, -2, 0, 1, 3,
685 5, 7, 9, 12, 14, 16, 18, 20,
686 22, 24, 26, 28, 31, 33, 35, 37,
687 39, 41, 43, 45, 47, 49, 51, 53,
688 54, 56, 58, 60, 62, 64, 66, 67,
689 69, 71, 73, 74, 76, 78, 79, 81,
690 83, 84, 86, 87, 89, 90, 92, 93,
691 94, 96, 97, 98, 99, 101, 102, 103,
692 104, 105, 106, 107, 108, 109, 110, 111, 112
693};
694
Joe Perches58aa68c2009-09-02 01:12:13 -0300695static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300696 -11, -13, -15, -17, -19, -21, -23, -25,
697 -27, -29, -31, -33, -35, -37, -39, -41,
698 -43, -45, -46, -48, -50, -52, -54, -55,
699 -57, -59, -61, -62, -64, -66, -67, -69,
700 -71, -72, -74, -75, -77, -78, -80, -81,
701 -83, -84, -86, -87, -88, -90, -91, -92,
702 -93, -95, -96, -97, -98, -99, -100, -101,
703 -102, -103, -104, -105, -106, -106, -107, -108,
704 -109, -109, -110, -111, -111, -112, -112, -113,
705 -113, -114, -114, -114, -115, -115, -115, -115,
706 -116, -116, -116, -116, -116, -116, -116, -116,
707 -116, -115, -115, -115, -115, -114, -114, -114,
708 -113, -113, -112, -112, -111, -111, -110, -110,
709 -109, -108, -108, -107, -106, -105, -104, -103,
710 -102, -101, -100, -99, -98, -97, -96, -95,
711 -94, -93, -91, -90, -89, -88, -86, -85,
712 -84, -82, -81, -79, -78, -76, -75, -73,
713 -71, -70, -68, -67, -65, -63, -62, -60,
714 -58, -56, -55, -53, -51, -49, -47, -45,
715 -44, -42, -40, -38, -36, -34, -32, -30,
716 -28, -26, -24, -22, -20, -18, -16, -14,
717 -12, -10, -8, -6, -4, -2, 0, 1,
718 3, 5, 7, 9, 11, 13, 15, 17,
719 19, 21, 23, 25, 27, 29, 31, 33,
720 35, 37, 39, 41, 43, 45, 46, 48,
721 50, 52, 54, 55, 57, 59, 61, 62,
722 64, 66, 67, 69, 71, 72, 74, 75,
723 77, 78, 80, 81, 83, 84, 86, 87,
724 88, 90, 91, 92, 93, 95, 96, 97,
725 98, 99, 100, 101, 102, 103, 104, 105,
726 106, 106, 107, 108, 109, 109, 110, 111,
727 111, 112, 112, 113, 113, 114, 114, 114,
728 115, 115, 115, 115, 116, 116, 116, 116,
729 116, 116, 116, 116, 116, 115, 115, 115,
730 115, 114, 114, 114, 113, 113, 112, 112,
731 111, 111, 110, 110, 109, 108, 108, 107,
732 106, 105, 104, 103, 102, 101, 100, 99,
733 98, 97, 96, 95, 94, 93, 91, 90,
734 89, 88, 86, 85, 84, 82, 81, 79,
735 78, 76, 75, 73, 71, 70, 68, 67,
736 65, 63, 62, 60, 58, 56, 55, 53,
737 51, 49, 47, 45, 44, 42, 40, 38,
738 36, 34, 32, 30, 28, 26, 24, 22,
739 20, 18, 16, 14, 12, 10, 8, 6,
740 4, 2, 0, -1, -3, -5, -7, -9, -11
741};
742
743static u16 i2c_ident[] = {
744 V4L2_IDENT_OV9650,
745 V4L2_IDENT_OV9655,
746 V4L2_IDENT_SOI968,
747 V4L2_IDENT_OV7660,
748 V4L2_IDENT_OV7670,
749 V4L2_IDENT_MT9V011,
750 V4L2_IDENT_MT9V111,
751 V4L2_IDENT_MT9V112,
752 V4L2_IDENT_MT9M001C12ST,
753 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300754 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300755 V4L2_IDENT_HV7131R,
756};
757
758static u16 bridge_init[][2] = {
759 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
760 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
761 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
762 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
763 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
764 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
765 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
766 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
767 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
768 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
769 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
770 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
771 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
772 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
773 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
774 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
775 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
776 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300777 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
778 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300779};
780
781/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
782static u8 ov_gain[] = {
783 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
784 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
785 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
786 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
787 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
788 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
789 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
790 0x70 /* 8x */
791};
792
793/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
794static u16 micron1_gain[] = {
795 /* 1x 1.25x 1.5x 1.75x */
796 0x0020, 0x0028, 0x0030, 0x0038,
797 /* 2x 2.25x 2.5x 2.75x */
798 0x00a0, 0x00a4, 0x00a8, 0x00ac,
799 /* 3x 3.25x 3.5x 3.75x */
800 0x00b0, 0x00b4, 0x00b8, 0x00bc,
801 /* 4x 4.25x 4.5x 4.75x */
802 0x00c0, 0x00c4, 0x00c8, 0x00cc,
803 /* 5x 5.25x 5.5x 5.75x */
804 0x00d0, 0x00d4, 0x00d8, 0x00dc,
805 /* 6x 6.25x 6.5x 6.75x */
806 0x00e0, 0x00e4, 0x00e8, 0x00ec,
807 /* 7x 7.25x 7.5x 7.75x */
808 0x00f0, 0x00f4, 0x00f8, 0x00fc,
809 /* 8x */
810 0x01c0
811};
812
813/* mt9m001 sensor uses a different gain formula then other micron sensors */
814/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
815static u16 micron2_gain[] = {
816 /* 1x 1.25x 1.5x 1.75x */
817 0x0008, 0x000a, 0x000c, 0x000e,
818 /* 2x 2.25x 2.5x 2.75x */
819 0x0010, 0x0012, 0x0014, 0x0016,
820 /* 3x 3.25x 3.5x 3.75x */
821 0x0018, 0x001a, 0x001c, 0x001e,
822 /* 4x 4.25x 4.5x 4.75x */
823 0x0020, 0x0051, 0x0052, 0x0053,
824 /* 5x 5.25x 5.5x 5.75x */
825 0x0054, 0x0055, 0x0056, 0x0057,
826 /* 6x 6.25x 6.5x 6.75x */
827 0x0058, 0x0059, 0x005a, 0x005b,
828 /* 7x 7.25x 7.5x 7.75x */
829 0x005c, 0x005d, 0x005e, 0x005f,
830 /* 8x */
831 0x0060
832};
833
834/* Gain = .5 + bit[7:0] / 16 */
835static u8 hv7131r_gain[] = {
836 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
837 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
838 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
839 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
840 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
841 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
842 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
843 0x78 /* 8x */
844};
845
Joe Perches58aa68c2009-09-02 01:12:13 -0300846static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300847 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
848 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
849 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
850 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
851 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
852 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300853 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300854 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
855 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
856 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
857 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
858};
859
Joe Perches58aa68c2009-09-02 01:12:13 -0300860static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300861 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
862 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
863 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
864 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
865 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
866 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
867};
868
Joe Perches58aa68c2009-09-02 01:12:13 -0300869static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300870 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
871 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
872 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
873 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
874 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
875 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
876 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
877 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
878 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
879 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
880 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
881 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
882 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
883 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
884 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
885 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
886 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
887 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
888 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
889 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
890 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
891 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
892 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
893 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
894 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
895 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
896 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
897 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
898 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
899 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
900 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
901 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
902 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
903 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
904 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
905 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
906 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
907 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
908 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
909 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
910 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
911 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
912 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
913 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
914 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
915 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
916 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
917 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
918 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
919 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
920 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
921 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
922 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
923 {0x93, 0x00},
924};
925
Joe Perches58aa68c2009-09-02 01:12:13 -0300926static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300927 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
928 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
929 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
930 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
931 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
932 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
933 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
934 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
935 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
936 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
937 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
938 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
939 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
940 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
941 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
942 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
943 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
944 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
945 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
946 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
947 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
948 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
949 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
950 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
951 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
952 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
953 {0xaa, 0x92}, {0xab, 0x0a},
954};
955
Joe Perches58aa68c2009-09-02 01:12:13 -0300956static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300957 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
958 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
959 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
960 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
961 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
962 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
963 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
964 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
965 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
966 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
967 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
968 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
969 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
970 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
971 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
972 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300973 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300974 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
975 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300976 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300977 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
978 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
979 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
980 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300981};
982
Joe Perches58aa68c2009-09-02 01:12:13 -0300983static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300984 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
985 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
986 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
987 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
988 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
989 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
990 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
991 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
992 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
993 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
994 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
995 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
996 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
997 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
998 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
999 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1000};
1001
Joe Perches58aa68c2009-09-02 01:12:13 -03001002static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001003 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -03001004 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1005 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1006 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1007 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1008 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1009 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -03001010};
1011
Joe Perches58aa68c2009-09-02 01:12:13 -03001012static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001013 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1014 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1015 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1016 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1017 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1018 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1019 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1020 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1021 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1022 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1023 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1024 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1025 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1026 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1027 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1028 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1029 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1030 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1031 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1032 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1033 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1034 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1035 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1036 {0x06, 0x0029}, {0x05, 0x0009},
1037};
1038
Joe Perches58aa68c2009-09-02 01:12:13 -03001039static struct i2c_reg_u16 mt9m001_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001040 {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
1041 {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
1042 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
1043 {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
1044 {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
1045 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
1046 {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
1047 {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
1048 {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
1049 {0x2e, 0x0029}, {0x07, 0x0002},
1050};
1051
Joe Perches58aa68c2009-09-02 01:12:13 -03001052static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001053 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1054 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001055 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1056 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001057};
1058
Brian Johnsone99ac542010-03-16 13:58:28 -03001059static struct i2c_reg_u16 mt9m112_init[] = {
1060 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1061 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1062 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1063 {0xf0, 0x0000},
1064};
1065
Joe Perches58aa68c2009-09-02 01:12:13 -03001066static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001067 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1068 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1069 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1070 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1071 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1072 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1073 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1074 {0x23, 0x09}, {0x01, 0x08},
1075};
1076
Joe Perches58aa68c2009-09-02 01:12:13 -03001077static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001078{
1079 struct usb_device *dev = gspca_dev->dev;
1080 int result;
1081 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1082 0x00,
1083 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1084 reg,
1085 0x00,
1086 gspca_dev->usb_buf,
1087 length,
1088 500);
1089 if (unlikely(result < 0 || result != length)) {
1090 err("Read register failed 0x%02X", reg);
1091 return -EIO;
1092 }
1093 return 0;
1094}
1095
Joe Perches58aa68c2009-09-02 01:12:13 -03001096static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1097 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001098{
1099 struct usb_device *dev = gspca_dev->dev;
1100 int result;
1101 memcpy(gspca_dev->usb_buf, buffer, length);
1102 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1103 0x08,
1104 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1105 reg,
1106 0x00,
1107 gspca_dev->usb_buf,
1108 length,
1109 500);
1110 if (unlikely(result < 0 || result != length)) {
1111 err("Write register failed index 0x%02X", reg);
1112 return -EIO;
1113 }
1114 return 0;
1115}
1116
Joe Perches58aa68c2009-09-02 01:12:13 -03001117static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001118{
1119 u8 data[1] = {value};
1120 return reg_w(gspca_dev, reg, data, 1);
1121}
1122
Joe Perches58aa68c2009-09-02 01:12:13 -03001123static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001124{
1125 int i;
1126 reg_w(gspca_dev, 0x10c0, buffer, 8);
1127 for (i = 0; i < 5; i++) {
1128 reg_r(gspca_dev, 0x10c0, 1);
1129 if (gspca_dev->usb_buf[0] & 0x04) {
1130 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001131 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001132 return 0;
1133 }
1134 msleep(1);
1135 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001136 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001137}
1138
Joe Perches58aa68c2009-09-02 01:12:13 -03001139static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142
1143 u8 row[8];
1144
1145 /*
1146 * from the point of view of the bridge, the length
1147 * includes the address
1148 */
1149 row[0] = 0x81 | (2 << 4);
1150 row[1] = sd->i2c_addr;
1151 row[2] = reg;
1152 row[3] = val;
1153 row[4] = 0x00;
1154 row[5] = 0x00;
1155 row[6] = 0x00;
1156 row[7] = 0x10;
1157
1158 return i2c_w(gspca_dev, row);
1159}
1160
Joe Perches58aa68c2009-09-02 01:12:13 -03001161static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001162{
1163 struct sd *sd = (struct sd *) gspca_dev;
1164 u8 row[8];
1165
1166 /*
1167 * from the point of view of the bridge, the length
1168 * includes the address
1169 */
1170 row[0] = 0x81 | (3 << 4);
1171 row[1] = sd->i2c_addr;
1172 row[2] = reg;
1173 row[3] = (val >> 8) & 0xff;
1174 row[4] = val & 0xff;
1175 row[5] = 0x00;
1176 row[6] = 0x00;
1177 row[7] = 0x10;
1178
1179 return i2c_w(gspca_dev, row);
1180}
1181
Jean-Francois Moine83955552009-12-12 06:58:01 -03001182static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001183{
1184 struct sd *sd = (struct sd *) gspca_dev;
1185 u8 row[8];
1186
Brian Johnson00b581e2009-07-23 05:55:43 -03001187 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001188 row[1] = sd->i2c_addr;
1189 row[2] = reg;
1190 row[3] = 0;
1191 row[4] = 0;
1192 row[5] = 0;
1193 row[6] = 0;
1194 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001195 if (i2c_w(gspca_dev, row) < 0)
1196 return -EIO;
1197 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001198 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001199 if (i2c_w(gspca_dev, row) < 0)
1200 return -EIO;
1201 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1202 return -EIO;
1203 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001204 return 0;
1205}
1206
Jean-Francois Moine83955552009-12-12 06:58:01 -03001207static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001208{
1209 struct sd *sd = (struct sd *) gspca_dev;
1210 u8 row[8];
1211
Brian Johnson00b581e2009-07-23 05:55:43 -03001212 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001213 row[1] = sd->i2c_addr;
1214 row[2] = reg;
1215 row[3] = 0;
1216 row[4] = 0;
1217 row[5] = 0;
1218 row[6] = 0;
1219 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001220 if (i2c_w(gspca_dev, row) < 0)
1221 return -EIO;
1222 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001223 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001224 if (i2c_w(gspca_dev, row) < 0)
1225 return -EIO;
1226 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1227 return -EIO;
1228 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001229 return 0;
1230}
1231
1232static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1233{
1234 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001235 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001236 struct sd *sd = (struct sd *) gspca_dev;
1237
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001238 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1239 return -EINVAL;
1240
1241 if (id != 0x7fa2) {
1242 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1243 return -ENODEV;
1244 }
1245
Brian Johnson26e744b2009-07-19 05:52:58 -03001246 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001247 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1248 ov9650_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001249 err("OV9650 sensor initialization failed");
1250 return -ENODEV;
1251 }
1252 }
1253 sd->hstart = 1;
1254 sd->vstart = 7;
1255 return 0;
1256}
1257
1258static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1259{
1260 int i;
1261 struct sd *sd = (struct sd *) gspca_dev;
1262
1263 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001264 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1265 ov9655_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001266 err("OV9655 sensor initialization failed");
1267 return -ENODEV;
1268 }
1269 }
1270 /* disable hflip and vflip */
1271 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001272 sd->hstart = 1;
1273 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001274 return 0;
1275}
1276
1277static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1278{
1279 int i;
1280 struct sd *sd = (struct sd *) gspca_dev;
1281
1282 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001283 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1284 soi968_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001285 err("SOI968 sensor initialization failed");
1286 return -ENODEV;
1287 }
1288 }
1289 /* disable hflip and vflip */
Jean-François Moine780e3122010-10-19 04:29:10 -03001290 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1291 | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001292 sd->hstart = 60;
1293 sd->vstart = 11;
1294 return 0;
1295}
1296
1297static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1298{
1299 int i;
1300 struct sd *sd = (struct sd *) gspca_dev;
1301
1302 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001303 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1304 ov7660_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001305 err("OV7660 sensor initialization failed");
1306 return -ENODEV;
1307 }
1308 }
1309 /* disable hflip and vflip */
1310 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1311 sd->hstart = 1;
1312 sd->vstart = 1;
1313 return 0;
1314}
1315
1316static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1317{
1318 int i;
1319 struct sd *sd = (struct sd *) gspca_dev;
1320
1321 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001322 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1323 ov7670_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001324 err("OV7670 sensor initialization failed");
1325 return -ENODEV;
1326 }
1327 }
1328 /* disable hflip and vflip */
1329 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1330 sd->hstart = 0;
1331 sd->vstart = 1;
1332 return 0;
1333}
1334
1335static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1336{
1337 struct sd *sd = (struct sd *) gspca_dev;
1338 int i;
1339 u16 value;
1340 int ret;
1341
1342 sd->i2c_addr = 0x5d;
1343 ret = i2c_r2(gspca_dev, 0xff, &value);
1344 if ((ret == 0) && (value == 0x8243)) {
1345 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001346 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1347 mt9v011_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001348 err("MT9V011 sensor initialization failed");
1349 return -ENODEV;
1350 }
1351 }
1352 sd->hstart = 2;
1353 sd->vstart = 2;
1354 sd->sensor = SENSOR_MT9V011;
1355 info("MT9V011 sensor detected");
1356 return 0;
1357 }
1358
1359 sd->i2c_addr = 0x5c;
1360 i2c_w2(gspca_dev, 0x01, 0x0004);
1361 ret = i2c_r2(gspca_dev, 0xff, &value);
1362 if ((ret == 0) && (value == 0x823a)) {
1363 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001364 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1365 mt9v111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001366 err("MT9V111 sensor initialization failed");
1367 return -ENODEV;
1368 }
1369 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001370 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1371 | (1 << AUTOGAIN_IDX)
1372 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001373 sd->hstart = 2;
1374 sd->vstart = 2;
1375 sd->sensor = SENSOR_MT9V111;
1376 info("MT9V111 sensor detected");
1377 return 0;
1378 }
1379
1380 sd->i2c_addr = 0x5d;
1381 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1382 if (ret < 0) {
1383 sd->i2c_addr = 0x48;
1384 i2c_w2(gspca_dev, 0xf0, 0x0000);
1385 }
1386 ret = i2c_r2(gspca_dev, 0x00, &value);
1387 if ((ret == 0) && (value == 0x1229)) {
1388 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001389 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1390 mt9v112_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001391 err("MT9V112 sensor initialization failed");
1392 return -ENODEV;
1393 }
1394 }
1395 sd->hstart = 6;
1396 sd->vstart = 2;
1397 sd->sensor = SENSOR_MT9V112;
1398 info("MT9V112 sensor detected");
1399 return 0;
1400 }
1401
1402 return -ENODEV;
1403}
1404
Brian Johnsone99ac542010-03-16 13:58:28 -03001405static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1406{
1407 struct sd *sd = (struct sd *) gspca_dev;
1408 int i;
1409 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1410 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1411 mt9m112_init[i].val) < 0) {
1412 err("MT9M112 sensor initialization failed");
1413 return -ENODEV;
1414 }
1415 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001416 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1417 | (1 << GAIN_IDX);
Brian Johnsone99ac542010-03-16 13:58:28 -03001418 sd->hstart = 0;
1419 sd->vstart = 2;
1420 return 0;
1421}
1422
Brian Johnson26e744b2009-07-19 05:52:58 -03001423static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1424{
1425 struct sd *sd = (struct sd *) gspca_dev;
1426 int i;
1427 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001428 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1429 mt9m111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001430 err("MT9M111 sensor initialization failed");
1431 return -ENODEV;
1432 }
1433 }
Jean-François Moine780e3122010-10-19 04:29:10 -03001434 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1435 | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001436 sd->hstart = 0;
1437 sd->vstart = 2;
1438 return 0;
1439}
1440
1441static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444 int i;
1445 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001446 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1447 mt9m001_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001448 err("MT9M001 sensor initialization failed");
1449 return -ENODEV;
1450 }
1451 }
1452 /* disable hflip and vflip */
1453 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1454 sd->hstart = 2;
1455 sd->vstart = 2;
1456 return 0;
1457}
1458
1459static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1460{
1461 int i;
1462 struct sd *sd = (struct sd *) gspca_dev;
1463
1464 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001465 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1466 hv7131r_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001467 err("HV7131R Sensor initialization failed");
1468 return -ENODEV;
1469 }
1470 }
1471 sd->hstart = 0;
1472 sd->vstart = 1;
1473 return 0;
1474}
1475
Brian Johnson26e744b2009-07-19 05:52:58 -03001476static int set_cmatrix(struct gspca_dev *gspca_dev)
1477{
1478 struct sd *sd = (struct sd *) gspca_dev;
1479 s32 hue_coord, hue_index = 180 + sd->hue;
1480 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001481
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001482 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001483 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1484 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1485 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1486 cmatrix[18] = sd->brightness - 0x80;
1487
1488 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001489 cmatrix[6] = hue_coord;
1490 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001491
1492 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001493 cmatrix[8] = hue_coord;
1494 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001495
1496 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001497 cmatrix[10] = hue_coord;
1498 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001499
1500 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001501 cmatrix[12] = hue_coord;
1502 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001503
1504 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001505 cmatrix[14] = hue_coord;
1506 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001507
1508 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001509 cmatrix[16] = hue_coord;
1510 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001511
1512 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1513}
1514
1515static int set_gamma(struct gspca_dev *gspca_dev)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518 u8 gamma[17];
1519 u8 gval = sd->gamma * 0xb8 / 0x100;
1520
1521
1522 gamma[0] = 0x0a;
1523 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1524 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1525 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1526 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1527 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1528 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1529 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1530 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1531 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1532 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1533 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1534 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1535 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1536 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1537 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1538 gamma[16] = 0xf5;
1539
1540 return reg_w(gspca_dev, 0x1190, gamma, 17);
1541}
1542
1543static int set_redblue(struct gspca_dev *gspca_dev)
1544{
1545 struct sd *sd = (struct sd *) gspca_dev;
1546 reg_w1(gspca_dev, 0x118c, sd->red);
1547 reg_w1(gspca_dev, 0x118f, sd->blue);
1548 return 0;
1549}
1550
1551static int set_hvflip(struct gspca_dev *gspca_dev)
1552{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001553 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001554 u16 value2;
1555 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001556
1557 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1558 hflip = !sd->hflip;
1559 vflip = !sd->vflip;
1560 } else {
1561 hflip = sd->hflip;
1562 vflip = sd->vflip;
1563 }
1564
Brian Johnson26e744b2009-07-19 05:52:58 -03001565 switch (sd->sensor) {
1566 case SENSOR_OV9650:
1567 i2c_r1(gspca_dev, 0x1e, &value);
1568 value &= ~0x30;
1569 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001570 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001571 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001572 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001573 value |= 0x10;
1574 tslb = 0x49;
1575 }
1576 i2c_w1(gspca_dev, 0x1e, value);
1577 i2c_w1(gspca_dev, 0x3a, tslb);
1578 break;
1579 case SENSOR_MT9V111:
1580 case SENSOR_MT9V011:
1581 i2c_r2(gspca_dev, 0x20, &value2);
1582 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001583 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001584 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001585 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001586 value2 |= 0x4020;
1587 i2c_w2(gspca_dev, 0x20, value2);
1588 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001589 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001590 case SENSOR_MT9M111:
1591 case SENSOR_MT9V112:
1592 i2c_r2(gspca_dev, 0x20, &value2);
1593 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001594 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001595 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001596 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001597 value2 |= 0x0001;
1598 i2c_w2(gspca_dev, 0x20, value2);
1599 break;
1600 case SENSOR_HV7131R:
1601 i2c_r1(gspca_dev, 0x01, &value);
1602 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001603 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001604 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001605 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001606 value |= 0x02;
1607 i2c_w1(gspca_dev, 0x01, value);
1608 break;
1609 }
1610 return 0;
1611}
1612
1613static int set_exposure(struct gspca_dev *gspca_dev)
1614{
1615 struct sd *sd = (struct sd *) gspca_dev;
1616 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1617 switch (sd->sensor) {
1618 case SENSOR_OV7660:
1619 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001620 case SENSOR_OV9655:
1621 case SENSOR_OV9650:
1622 exp[0] |= (3 << 4);
1623 exp[2] = 0x2d;
1624 exp[3] = sd->exposure & 0xff;
1625 exp[4] = sd->exposure >> 8;
1626 break;
1627 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001628 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001629 case SENSOR_MT9V011:
1630 exp[0] |= (3 << 4);
1631 exp[2] = 0x09;
1632 exp[3] = sd->exposure >> 8;
1633 exp[4] = sd->exposure & 0xff;
1634 break;
1635 case SENSOR_HV7131R:
1636 exp[0] |= (4 << 4);
1637 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001638 exp[3] = (sd->exposure >> 5) & 0xff;
1639 exp[4] = (sd->exposure << 3) & 0xff;
1640 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001641 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001642 default:
1643 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001644 }
1645 i2c_w(gspca_dev, exp);
1646 return 0;
1647}
1648
1649static int set_gain(struct gspca_dev *gspca_dev)
1650{
1651 struct sd *sd = (struct sd *) gspca_dev;
1652 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1653 switch (sd->sensor) {
1654 case SENSOR_OV7660:
1655 case SENSOR_OV7670:
1656 case SENSOR_SOI968:
1657 case SENSOR_OV9655:
1658 case SENSOR_OV9650:
1659 gain[0] |= (2 << 4);
1660 gain[3] = ov_gain[sd->gain];
1661 break;
1662 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001663 gain[0] |= (3 << 4);
1664 gain[2] = 0x35;
1665 gain[3] = micron1_gain[sd->gain] >> 8;
1666 gain[4] = micron1_gain[sd->gain] & 0xff;
1667 break;
1668 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001669 gain[0] |= (3 << 4);
1670 gain[2] = 0x2f;
1671 gain[3] = micron1_gain[sd->gain] >> 8;
1672 gain[4] = micron1_gain[sd->gain] & 0xff;
1673 break;
1674 case SENSOR_MT9M001:
1675 gain[0] |= (3 << 4);
1676 gain[2] = 0x2f;
1677 gain[3] = micron2_gain[sd->gain] >> 8;
1678 gain[4] = micron2_gain[sd->gain] & 0xff;
1679 break;
1680 case SENSOR_HV7131R:
1681 gain[0] |= (2 << 4);
1682 gain[2] = 0x30;
1683 gain[3] = hv7131r_gain[sd->gain];
1684 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001685 default:
1686 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001687 }
1688 i2c_w(gspca_dev, gain);
1689 return 0;
1690}
1691
1692static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1693{
1694 struct sd *sd = (struct sd *) gspca_dev;
1695
1696 sd->brightness = val;
1697 if (gspca_dev->streaming)
1698 return set_cmatrix(gspca_dev);
1699 return 0;
1700}
1701
1702static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1703{
1704 struct sd *sd = (struct sd *) gspca_dev;
1705 *val = sd->brightness;
1706 return 0;
1707}
1708
1709
1710static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1711{
1712 struct sd *sd = (struct sd *) gspca_dev;
1713
1714 sd->contrast = val;
1715 if (gspca_dev->streaming)
1716 return set_cmatrix(gspca_dev);
1717 return 0;
1718}
1719
1720static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1721{
1722 struct sd *sd = (struct sd *) gspca_dev;
1723 *val = sd->contrast;
1724 return 0;
1725}
1726
1727static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1728{
1729 struct sd *sd = (struct sd *) gspca_dev;
1730
1731 sd->saturation = val;
1732 if (gspca_dev->streaming)
1733 return set_cmatrix(gspca_dev);
1734 return 0;
1735}
1736
1737static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1738{
1739 struct sd *sd = (struct sd *) gspca_dev;
1740 *val = sd->saturation;
1741 return 0;
1742}
1743
1744static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1745{
1746 struct sd *sd = (struct sd *) gspca_dev;
1747
1748 sd->hue = val;
1749 if (gspca_dev->streaming)
1750 return set_cmatrix(gspca_dev);
1751 return 0;
1752}
1753
1754static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1755{
1756 struct sd *sd = (struct sd *) gspca_dev;
1757 *val = sd->hue;
1758 return 0;
1759}
1760
1761static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1762{
1763 struct sd *sd = (struct sd *) gspca_dev;
1764
1765 sd->gamma = val;
1766 if (gspca_dev->streaming)
1767 return set_gamma(gspca_dev);
1768 return 0;
1769}
1770
1771static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1772{
1773 struct sd *sd = (struct sd *) gspca_dev;
1774 *val = sd->gamma;
1775 return 0;
1776}
1777
1778static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1779{
1780 struct sd *sd = (struct sd *) gspca_dev;
1781
1782 sd->red = val;
1783 if (gspca_dev->streaming)
1784 return set_redblue(gspca_dev);
1785 return 0;
1786}
1787
1788static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1789{
1790 struct sd *sd = (struct sd *) gspca_dev;
1791 *val = sd->red;
1792 return 0;
1793}
1794
1795static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1796{
1797 struct sd *sd = (struct sd *) gspca_dev;
1798
1799 sd->blue = val;
1800 if (gspca_dev->streaming)
1801 return set_redblue(gspca_dev);
1802 return 0;
1803}
1804
1805static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1806{
1807 struct sd *sd = (struct sd *) gspca_dev;
1808 *val = sd->blue;
1809 return 0;
1810}
1811
1812static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1813{
1814 struct sd *sd = (struct sd *) gspca_dev;
1815
1816 sd->hflip = val;
1817 if (gspca_dev->streaming)
1818 return set_hvflip(gspca_dev);
1819 return 0;
1820}
1821
1822static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1823{
1824 struct sd *sd = (struct sd *) gspca_dev;
1825 *val = sd->hflip;
1826 return 0;
1827}
1828
1829static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1830{
1831 struct sd *sd = (struct sd *) gspca_dev;
1832
1833 sd->vflip = val;
1834 if (gspca_dev->streaming)
1835 return set_hvflip(gspca_dev);
1836 return 0;
1837}
1838
1839static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1840{
1841 struct sd *sd = (struct sd *) gspca_dev;
1842 *val = sd->vflip;
1843 return 0;
1844}
1845
1846static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1847{
1848 struct sd *sd = (struct sd *) gspca_dev;
1849
1850 sd->exposure = val;
1851 if (gspca_dev->streaming)
1852 return set_exposure(gspca_dev);
1853 return 0;
1854}
1855
1856static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1857{
1858 struct sd *sd = (struct sd *) gspca_dev;
1859 *val = sd->exposure;
1860 return 0;
1861}
1862
1863static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1864{
1865 struct sd *sd = (struct sd *) gspca_dev;
1866
1867 sd->gain = val;
1868 if (gspca_dev->streaming)
1869 return set_gain(gspca_dev);
1870 return 0;
1871}
1872
1873static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1874{
1875 struct sd *sd = (struct sd *) gspca_dev;
1876 *val = sd->gain;
1877 return 0;
1878}
1879
1880static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1881{
1882 struct sd *sd = (struct sd *) gspca_dev;
1883 sd->auto_exposure = val;
1884 return 0;
1885}
1886
1887static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1888{
1889 struct sd *sd = (struct sd *) gspca_dev;
1890 *val = sd->auto_exposure;
1891 return 0;
1892}
1893
1894#ifdef CONFIG_VIDEO_ADV_DEBUG
1895static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1896 struct v4l2_dbg_register *reg)
1897{
1898 struct sd *sd = (struct sd *) gspca_dev;
1899 switch (reg->match.type) {
1900 case V4L2_CHIP_MATCH_HOST:
1901 if (reg->match.addr != 0)
1902 return -EINVAL;
1903 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1904 return -EINVAL;
1905 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1906 return -EINVAL;
1907 reg->val = gspca_dev->usb_buf[0];
1908 return 0;
1909 case V4L2_CHIP_MATCH_I2C_ADDR:
1910 if (reg->match.addr != sd->i2c_addr)
1911 return -EINVAL;
1912 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001913 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001914 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1915 return -EINVAL;
1916 } else {
1917 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1918 return -EINVAL;
1919 }
1920 return 0;
1921 }
1922 return -EINVAL;
1923}
1924
1925static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1926 struct v4l2_dbg_register *reg)
1927{
1928 struct sd *sd = (struct sd *) gspca_dev;
1929 switch (reg->match.type) {
1930 case V4L2_CHIP_MATCH_HOST:
1931 if (reg->match.addr != 0)
1932 return -EINVAL;
1933 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1934 return -EINVAL;
1935 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1936 return -EINVAL;
1937 return 0;
1938 case V4L2_CHIP_MATCH_I2C_ADDR:
1939 if (reg->match.addr != sd->i2c_addr)
1940 return -EINVAL;
1941 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001942 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001943 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1944 return -EINVAL;
1945 } else {
1946 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1947 return -EINVAL;
1948 }
1949 return 0;
1950 }
1951 return -EINVAL;
1952}
1953#endif
1954
1955static int sd_chip_ident(struct gspca_dev *gspca_dev,
1956 struct v4l2_dbg_chip_ident *chip)
1957{
1958 struct sd *sd = (struct sd *) gspca_dev;
1959
1960 switch (chip->match.type) {
1961 case V4L2_CHIP_MATCH_HOST:
1962 if (chip->match.addr != 0)
1963 return -EINVAL;
1964 chip->revision = 0;
1965 chip->ident = V4L2_IDENT_SN9C20X;
1966 return 0;
1967 case V4L2_CHIP_MATCH_I2C_ADDR:
1968 if (chip->match.addr != sd->i2c_addr)
1969 return -EINVAL;
1970 chip->revision = 0;
1971 chip->ident = i2c_ident[sd->sensor];
1972 return 0;
1973 }
1974 return -EINVAL;
1975}
1976
1977static int sd_config(struct gspca_dev *gspca_dev,
1978 const struct usb_device_id *id)
1979{
1980 struct sd *sd = (struct sd *) gspca_dev;
1981 struct cam *cam;
1982
1983 cam = &gspca_dev->cam;
1984
1985 sd->sensor = (id->driver_info >> 8) & 0xff;
1986 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001987 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001988
1989 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001990 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001991 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001992 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001993 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001994 cam->cam_mode = sxga_mode;
1995 cam->nmodes = ARRAY_SIZE(sxga_mode);
1996 break;
1997 default:
1998 cam->cam_mode = vga_mode;
1999 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002000 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002001 }
2002
2003 sd->old_step = 0;
2004 sd->older_step = 0;
2005 sd->exposure_step = 16;
2006
2007 sd->brightness = BRIGHTNESS_DEFAULT;
2008 sd->contrast = CONTRAST_DEFAULT;
2009 sd->saturation = SATURATION_DEFAULT;
2010 sd->hue = HUE_DEFAULT;
2011 sd->gamma = GAMMA_DEFAULT;
2012 sd->red = RED_DEFAULT;
2013 sd->blue = BLUE_DEFAULT;
2014
2015 sd->hflip = HFLIP_DEFAULT;
2016 sd->vflip = VFLIP_DEFAULT;
2017 sd->exposure = EXPOSURE_DEFAULT;
2018 sd->gain = GAIN_DEFAULT;
2019 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2020
2021 sd->quality = 95;
2022
Brian Johnson26e744b2009-07-19 05:52:58 -03002023 return 0;
2024}
2025
2026static int sd_init(struct gspca_dev *gspca_dev)
2027{
2028 struct sd *sd = (struct sd *) gspca_dev;
2029 int i;
2030 u8 value;
2031 u8 i2c_init[9] =
2032 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2033
2034 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2035 value = bridge_init[i][1];
2036 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2037 err("Device initialization failed");
2038 return -ENODEV;
2039 }
2040 }
2041
Brian Johnson0c045eb2010-03-16 13:58:27 -03002042 if (sd->flags & LED_REVERSE)
2043 reg_w1(gspca_dev, 0x1006, 0x00);
2044 else
2045 reg_w1(gspca_dev, 0x1006, 0x20);
2046
Brian Johnson26e744b2009-07-19 05:52:58 -03002047 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2048 err("Device initialization failed");
2049 return -ENODEV;
2050 }
2051
2052 switch (sd->sensor) {
2053 case SENSOR_OV9650:
2054 if (ov9650_init_sensor(gspca_dev) < 0)
2055 return -ENODEV;
2056 info("OV9650 sensor detected");
2057 break;
2058 case SENSOR_OV9655:
2059 if (ov9655_init_sensor(gspca_dev) < 0)
2060 return -ENODEV;
2061 info("OV9655 sensor detected");
2062 break;
2063 case SENSOR_SOI968:
2064 if (soi968_init_sensor(gspca_dev) < 0)
2065 return -ENODEV;
2066 info("SOI968 sensor detected");
2067 break;
2068 case SENSOR_OV7660:
2069 if (ov7660_init_sensor(gspca_dev) < 0)
2070 return -ENODEV;
2071 info("OV7660 sensor detected");
2072 break;
2073 case SENSOR_OV7670:
2074 if (ov7670_init_sensor(gspca_dev) < 0)
2075 return -ENODEV;
2076 info("OV7670 sensor detected");
2077 break;
2078 case SENSOR_MT9VPRB:
2079 if (mt9v_init_sensor(gspca_dev) < 0)
2080 return -ENODEV;
2081 break;
2082 case SENSOR_MT9M111:
2083 if (mt9m111_init_sensor(gspca_dev) < 0)
2084 return -ENODEV;
2085 info("MT9M111 sensor detected");
2086 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002087 case SENSOR_MT9M112:
2088 if (mt9m112_init_sensor(gspca_dev) < 0)
2089 return -ENODEV;
2090 info("MT9M112 sensor detected");
2091 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002092 case SENSOR_MT9M001:
2093 if (mt9m001_init_sensor(gspca_dev) < 0)
2094 return -ENODEV;
2095 info("MT9M001 sensor detected");
2096 break;
2097 case SENSOR_HV7131R:
2098 if (hv7131r_init_sensor(gspca_dev) < 0)
2099 return -ENODEV;
2100 info("HV7131R sensor detected");
2101 break;
2102 default:
2103 info("Unsupported Sensor");
2104 return -ENODEV;
2105 }
2106
2107 return 0;
2108}
2109
2110static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2111{
2112 struct sd *sd = (struct sd *) gspca_dev;
2113 u8 value;
2114 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002115 case SENSOR_SOI968:
2116 if (mode & MODE_SXGA) {
2117 i2c_w1(gspca_dev, 0x17, 0x1d);
2118 i2c_w1(gspca_dev, 0x18, 0xbd);
2119 i2c_w1(gspca_dev, 0x19, 0x01);
2120 i2c_w1(gspca_dev, 0x1a, 0x81);
2121 i2c_w1(gspca_dev, 0x12, 0x00);
2122 sd->hstart = 140;
2123 sd->vstart = 19;
2124 } else {
2125 i2c_w1(gspca_dev, 0x17, 0x13);
2126 i2c_w1(gspca_dev, 0x18, 0x63);
2127 i2c_w1(gspca_dev, 0x19, 0x01);
2128 i2c_w1(gspca_dev, 0x1a, 0x79);
2129 i2c_w1(gspca_dev, 0x12, 0x40);
2130 sd->hstart = 60;
2131 sd->vstart = 11;
2132 }
2133 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002134 case SENSOR_OV9650:
2135 if (mode & MODE_SXGA) {
2136 i2c_w1(gspca_dev, 0x17, 0x1b);
2137 i2c_w1(gspca_dev, 0x18, 0xbc);
2138 i2c_w1(gspca_dev, 0x19, 0x01);
2139 i2c_w1(gspca_dev, 0x1a, 0x82);
2140 i2c_r1(gspca_dev, 0x12, &value);
2141 i2c_w1(gspca_dev, 0x12, value & 0x07);
2142 } else {
2143 i2c_w1(gspca_dev, 0x17, 0x24);
2144 i2c_w1(gspca_dev, 0x18, 0xc5);
2145 i2c_w1(gspca_dev, 0x19, 0x00);
2146 i2c_w1(gspca_dev, 0x1a, 0x3c);
2147 i2c_r1(gspca_dev, 0x12, &value);
2148 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2149 }
2150 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002151 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002152 case SENSOR_MT9M111:
2153 if (mode & MODE_SXGA) {
2154 i2c_w2(gspca_dev, 0xf0, 0x0002);
2155 i2c_w2(gspca_dev, 0xc8, 0x970b);
2156 i2c_w2(gspca_dev, 0xf0, 0x0000);
2157 } else {
2158 i2c_w2(gspca_dev, 0xf0, 0x0002);
2159 i2c_w2(gspca_dev, 0xc8, 0x8000);
2160 i2c_w2(gspca_dev, 0xf0, 0x0000);
2161 }
2162 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002163 }
2164}
2165
2166#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002167((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002168(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2169(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2170
2171#define CLR_WIN(width, height) \
2172((const u8 [])\
2173{0, width >> 2, 0, height >> 1,\
2174((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2175
2176static int sd_start(struct gspca_dev *gspca_dev)
2177{
2178 struct sd *sd = (struct sd *) gspca_dev;
2179 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2180 int width = gspca_dev->width;
2181 int height = gspca_dev->height;
2182 u8 fmt, scale = 0;
2183
Brian Johnson26e744b2009-07-19 05:52:58 -03002184 jpeg_define(sd->jpeg_hdr, height, width,
2185 0x21);
2186 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2187
2188 if (mode & MODE_RAW)
2189 fmt = 0x2d;
2190 else if (mode & MODE_JPEG)
2191 fmt = 0x2c;
2192 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002193 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002194
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002195 switch (mode & SCALE_MASK) {
2196 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002197 scale = 0xc0;
2198 info("Set 1280x1024");
2199 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002200 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002201 scale = 0x80;
2202 info("Set 640x480");
2203 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002204 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002205 scale = 0x90;
2206 info("Set 320x240");
2207 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002208 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002209 scale = 0xa0;
2210 info("Set 160x120");
2211 break;
2212 }
2213
2214 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002215 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2216 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002217 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2218 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2219 reg_w1(gspca_dev, 0x1189, scale);
2220 reg_w1(gspca_dev, 0x10e0, fmt);
2221
2222 set_cmatrix(gspca_dev);
2223 set_gamma(gspca_dev);
2224 set_redblue(gspca_dev);
2225 set_gain(gspca_dev);
2226 set_exposure(gspca_dev);
2227 set_hvflip(gspca_dev);
2228
Brian Johnson0c045eb2010-03-16 13:58:27 -03002229 reg_w1(gspca_dev, 0x1007, 0x20);
2230
Brian Johnson26e744b2009-07-19 05:52:58 -03002231 reg_r(gspca_dev, 0x1061, 1);
2232 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2233 return 0;
2234}
2235
2236static void sd_stopN(struct gspca_dev *gspca_dev)
2237{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002238 reg_w1(gspca_dev, 0x1007, 0x00);
2239
Brian Johnson26e744b2009-07-19 05:52:58 -03002240 reg_r(gspca_dev, 0x1061, 1);
2241 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2242}
2243
Brian Johnsone1430472009-09-02 12:39:41 -03002244static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002245{
2246 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002247 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002248
2249 /*
2250 * some hardcoded values are present
2251 * like those for maximal/minimal exposure
2252 * and exposure steps
2253 */
2254 if (avg_lum < MIN_AVG_LUM) {
2255 if (sd->exposure > 0x1770)
2256 return;
2257
2258 new_exp = sd->exposure + sd->exposure_step;
2259 if (new_exp > 0x1770)
2260 new_exp = 0x1770;
2261 if (new_exp < 0x10)
2262 new_exp = 0x10;
2263 sd->exposure = new_exp;
2264 set_exposure(gspca_dev);
2265
2266 sd->older_step = sd->old_step;
2267 sd->old_step = 1;
2268
2269 if (sd->old_step ^ sd->older_step)
2270 sd->exposure_step /= 2;
2271 else
2272 sd->exposure_step += 2;
2273 }
2274 if (avg_lum > MAX_AVG_LUM) {
2275 if (sd->exposure < 0x10)
2276 return;
2277 new_exp = sd->exposure - sd->exposure_step;
2278 if (new_exp > 0x1700)
2279 new_exp = 0x1770;
2280 if (new_exp < 0x10)
2281 new_exp = 0x10;
2282 sd->exposure = new_exp;
2283 set_exposure(gspca_dev);
2284 sd->older_step = sd->old_step;
2285 sd->old_step = 0;
2286
2287 if (sd->old_step ^ sd->older_step)
2288 sd->exposure_step /= 2;
2289 else
2290 sd->exposure_step += 2;
2291 }
2292}
2293
Brian Johnsone1430472009-09-02 12:39:41 -03002294static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2295{
2296 struct sd *sd = (struct sd *) gspca_dev;
2297
2298 if (avg_lum < MIN_AVG_LUM) {
2299 if (sd->gain + 1 <= 28) {
2300 sd->gain++;
2301 set_gain(gspca_dev);
2302 }
2303 }
2304 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002305 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002306 sd->gain--;
2307 set_gain(gspca_dev);
2308 }
2309 }
2310}
2311
2312static void sd_dqcallback(struct gspca_dev *gspca_dev)
2313{
2314 struct sd *sd = (struct sd *) gspca_dev;
2315 int avg_lum;
2316
2317 if (!sd->auto_exposure)
2318 return;
2319
2320 avg_lum = atomic_read(&sd->avg_lum);
2321 if (sd->sensor == SENSOR_SOI968)
2322 do_autogain(gspca_dev, avg_lum);
2323 else
2324 do_autoexposure(gspca_dev, avg_lum);
2325}
2326
Jean-François Moine28566432010-10-01 07:33:26 -03002327#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002328static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2329 u8 *data, /* interrupt packet */
2330 int len) /* interrupt packet length */
2331{
2332 struct sd *sd = (struct sd *) gspca_dev;
2333 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002334 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002335 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2336 input_sync(gspca_dev->input_dev);
2337 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2338 input_sync(gspca_dev->input_dev);
2339 ret = 0;
2340 }
2341 return ret;
2342}
2343#endif
2344
Brian Johnson26e744b2009-07-19 05:52:58 -03002345static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002346 u8 *data, /* isoc packet */
2347 int len) /* iso packet length */
2348{
2349 struct sd *sd = (struct sd *) gspca_dev;
2350 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002351 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002352 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2353 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2354 avg_lum = ((data[35] >> 2) & 3) |
2355 (data[20] << 2) |
2356 (data[19] << 10);
2357 avg_lum += ((data[35] >> 4) & 3) |
2358 (data[22] << 2) |
2359 (data[21] << 10);
2360 avg_lum += ((data[35] >> 6) & 3) |
2361 (data[24] << 2) |
2362 (data[23] << 10);
2363 avg_lum += (data[36] & 3) |
2364 (data[26] << 2) |
2365 (data[25] << 10);
2366 avg_lum += ((data[36] >> 2) & 3) |
2367 (data[28] << 2) |
2368 (data[27] << 10);
2369 avg_lum += ((data[36] >> 4) & 3) |
2370 (data[30] << 2) |
2371 (data[29] << 10);
2372 avg_lum += ((data[36] >> 6) & 3) |
2373 (data[32] << 2) |
2374 (data[31] << 10);
2375 avg_lum += ((data[44] >> 4) & 3) |
2376 (data[34] << 2) |
2377 (data[33] << 10);
2378 avg_lum >>= 9;
2379 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002380 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Brian Johnson26e744b2009-07-19 05:52:58 -03002381 return;
2382 }
2383 if (gspca_dev->last_packet_type == LAST_PACKET) {
2384 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2385 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002386 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002387 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002388 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002389 data, len);
2390 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002391 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002392 data, len);
2393 }
2394 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002395 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002396 }
2397}
2398
2399/* sub-driver description */
2400static const struct sd_desc sd_desc = {
2401 .name = MODULE_NAME,
2402 .ctrls = sd_ctrls,
2403 .nctrls = ARRAY_SIZE(sd_ctrls),
2404 .config = sd_config,
2405 .init = sd_init,
2406 .start = sd_start,
2407 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002408 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002409#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002410 .int_pkt_scan = sd_int_pkt_scan,
2411#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002412 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002413#ifdef CONFIG_VIDEO_ADV_DEBUG
2414 .set_register = sd_dbg_s_register,
2415 .get_register = sd_dbg_g_register,
2416#endif
2417 .get_chip_ident = sd_chip_ident,
2418};
2419
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002420#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002421 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002422 | (SENSOR_ ## sensor << 8) \
2423 | (i2c_addr)
2424
2425static const __devinitdata struct usb_device_id device_table[] = {
2426 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2427 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2428 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002429 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002430 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2431 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2432 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002433 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2434 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2435 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2436 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2437 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
2438 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2439 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2440 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2441 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002442 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002443 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002444 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2445 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2446 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2447 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2448 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002449 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002450 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2451 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2452 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2453 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002454 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2455 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002456 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2457 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2458 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2459 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002460 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002461 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2462 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2463 {}
2464};
2465MODULE_DEVICE_TABLE(usb, device_table);
2466
2467/* -- device connect -- */
2468static int sd_probe(struct usb_interface *intf,
2469 const struct usb_device_id *id)
2470{
2471 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2472 THIS_MODULE);
2473}
2474
Brian Johnson26e744b2009-07-19 05:52:58 -03002475static struct usb_driver sd_driver = {
2476 .name = MODULE_NAME,
2477 .id_table = device_table,
2478 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002479 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002480#ifdef CONFIG_PM
2481 .suspend = gspca_suspend,
2482 .resume = gspca_resume,
2483 .reset_resume = gspca_resume,
2484#endif
2485};
2486
2487/* -- module insert / remove -- */
2488static int __init sd_mod_init(void)
2489{
Jean-François Moine54826432010-09-13 04:53:03 -03002490 return usb_register(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002491}
2492static void __exit sd_mod_exit(void)
2493{
2494 usb_deregister(&sd_driver);
Brian Johnson26e744b2009-07-19 05:52:58 -03002495}
2496
2497module_init(sd_mod_init);
2498module_exit(sd_mod_exit);