blob: 45092eed8fc7d7083151a7ac1c565837fbaee4bb [file] [log] [blame]
Brian Johnson26e744b2009-07-19 05:52:58 -03001/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Joe Perches91f58422011-08-21 19:56:55 -030021#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
Brian Johnson26e744b2009-07-19 05:52:58 -030023#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030024
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030025#include "gspca.h"
26#include "jpeg.h"
27
28#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030029#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030030
Brian Johnson26e744b2009-07-19 05:52:58 -030031MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
32 "microdia project <microdia@googlegroups.com>");
33MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
34MODULE_LICENSE("GPL");
35
36#define MODULE_NAME "sn9c20x"
37
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -030038/*
39 * Pixel format private data
40 */
41#define SCALE_MASK 0x0f
42#define SCALE_160x120 0
43#define SCALE_320x240 1
44#define SCALE_640x480 2
45#define SCALE_1280x1024 3
Brian Johnson26e744b2009-07-19 05:52:58 -030046#define MODE_RAW 0x10
47#define MODE_JPEG 0x20
48#define MODE_SXGA 0x80
49
50#define SENSOR_OV9650 0
51#define SENSOR_OV9655 1
52#define SENSOR_SOI968 2
53#define SENSOR_OV7660 3
54#define SENSOR_OV7670 4
55#define SENSOR_MT9V011 5
56#define SENSOR_MT9V111 6
57#define SENSOR_MT9V112 7
58#define SENSOR_MT9M001 8
59#define SENSOR_MT9M111 9
Brian Johnsone99ac542010-03-16 13:58:28 -030060#define SENSOR_MT9M112 10
61#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030062#define SENSOR_MT9VPRB 20
63
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030064/* camera flags */
Brian Johnson33ddc162010-04-18 21:42:40 -030065#define HAS_NO_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030066#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030067#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030068
Jean-François Moinec5224d82012-03-19 04:30:07 -030069enum e_ctrl {
70 BRIGHTNESS,
71 CONTRAST,
72 SATURATION,
73 HUE,
74 GAMMA,
75 BLUE,
76 RED,
77 VFLIP,
78 HFLIP,
79 EXPOSURE,
80 GAIN,
81 AUTOGAIN,
82 NCTRLS /* number of controls */
83};
84
Brian Johnson26e744b2009-07-19 05:52:58 -030085/* specific webcam descriptor */
86struct sd {
87 struct gspca_dev gspca_dev;
88
Jean-François Moinec5224d82012-03-19 04:30:07 -030089 struct gspca_ctrl ctrls[NCTRLS];
90
Brian Johnson26e744b2009-07-19 05:52:58 -030091#define MIN_AVG_LUM 80
92#define MAX_AVG_LUM 130
93 atomic_t avg_lum;
94 u8 old_step;
95 u8 older_step;
96 u8 exposure_step;
97
Brian Johnson26e744b2009-07-19 05:52:58 -030098 u8 i2c_addr;
99 u8 sensor;
100 u8 hstart;
101 u8 vstart;
102
Jean-François Moine9a731a32010-06-04 05:26:42 -0300103 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300104 u8 quality;
105
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300106 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300107};
108
Joe Perches58aa68c2009-09-02 01:12:13 -0300109struct i2c_reg_u8 {
110 u8 reg;
111 u8 val;
112};
113
114struct i2c_reg_u16 {
115 u8 reg;
116 u16 val;
117};
118
Brian Johnson7ddaac72010-03-16 13:58:27 -0300119static const struct dmi_system_id flip_dmi_table[] = {
120 {
121 .ident = "MSI MS-1034",
122 .matches = {
123 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
124 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
125 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
126 }
127 },
128 {
129 .ident = "MSI MS-1632",
130 .matches = {
131 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
132 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
133 }
134 },
Brian Johnsone077f862010-04-05 20:52:52 -0300135 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300136 .ident = "MSI MS-1633X",
137 .matches = {
138 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
139 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
140 }
141 },
142 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300143 .ident = "MSI MS-1635X",
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
146 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
147 }
148 },
149 {
Brian Johnsone077f862010-04-05 20:52:52 -0300150 .ident = "ASUSTeK W7J",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
153 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
154 }
155 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300156 {}
157};
158
Jean-François Moinec5224d82012-03-19 04:30:07 -0300159static void set_cmatrix(struct gspca_dev *gspca_dev);
160static void set_gamma(struct gspca_dev *gspca_dev);
161static void set_redblue(struct gspca_dev *gspca_dev);
162static void set_hvflip(struct gspca_dev *gspca_dev);
163static void set_exposure(struct gspca_dev *gspca_dev);
164static void set_gain(struct gspca_dev *gspca_dev);
165
166static const struct ctrl sd_ctrls[NCTRLS] = {
167[BRIGHTNESS] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300168 {
169 .id = V4L2_CID_BRIGHTNESS,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "Brightness",
172 .minimum = 0,
173 .maximum = 0xff,
174 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300175 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300176 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300177 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300178 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300179[CONTRAST] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300180 {
181 .id = V4L2_CID_CONTRAST,
182 .type = V4L2_CTRL_TYPE_INTEGER,
183 .name = "Contrast",
184 .minimum = 0,
185 .maximum = 0xff,
186 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300187 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300188 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300189 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300190 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300191[SATURATION] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300192 {
193 .id = V4L2_CID_SATURATION,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Saturation",
196 .minimum = 0,
197 .maximum = 0xff,
198 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300199 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300200 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300201 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300202 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300203[HUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300204 {
205 .id = V4L2_CID_HUE,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Hue",
208 .minimum = -180,
209 .maximum = 180,
210 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300211 .default_value = 0
Brian Johnson26e744b2009-07-19 05:52:58 -0300212 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300213 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300214 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300215[GAMMA] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300216 {
217 .id = V4L2_CID_GAMMA,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 .name = "Gamma",
220 .minimum = 0,
221 .maximum = 0xff,
222 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300223 .default_value = 0x10
Brian Johnson26e744b2009-07-19 05:52:58 -0300224 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300225 .set_control = set_gamma
Brian Johnson26e744b2009-07-19 05:52:58 -0300226 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300227[BLUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300228 {
229 .id = V4L2_CID_BLUE_BALANCE,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Blue Balance",
232 .minimum = 0,
233 .maximum = 0x7f,
234 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300235 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300236 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300237 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300238 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300239[RED] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300240 {
241 .id = V4L2_CID_RED_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Red Balance",
244 .minimum = 0,
245 .maximum = 0x7f,
246 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300247 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300248 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300249 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300250 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300251[HFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300252 {
253 .id = V4L2_CID_HFLIP,
254 .type = V4L2_CTRL_TYPE_BOOLEAN,
255 .name = "Horizontal Flip",
256 .minimum = 0,
257 .maximum = 1,
258 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300259 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300260 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300261 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300262 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300263[VFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300264 {
265 .id = V4L2_CID_VFLIP,
266 .type = V4L2_CTRL_TYPE_BOOLEAN,
267 .name = "Vertical Flip",
268 .minimum = 0,
269 .maximum = 1,
270 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300271 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300272 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300273 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300274 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300275[EXPOSURE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300276 {
277 .id = V4L2_CID_EXPOSURE,
278 .type = V4L2_CTRL_TYPE_INTEGER,
279 .name = "Exposure",
280 .minimum = 0,
281 .maximum = 0x1780,
282 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300283 .default_value = 0x33,
Brian Johnson26e744b2009-07-19 05:52:58 -0300284 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300285 .set_control = set_exposure
Brian Johnson26e744b2009-07-19 05:52:58 -0300286 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300287[GAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300288 {
289 .id = V4L2_CID_GAIN,
290 .type = V4L2_CTRL_TYPE_INTEGER,
291 .name = "Gain",
292 .minimum = 0,
293 .maximum = 28,
294 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300295 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300296 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300297 .set_control = set_gain
Brian Johnson26e744b2009-07-19 05:52:58 -0300298 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300299[AUTOGAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300300 {
301 .id = V4L2_CID_AUTOGAIN,
302 .type = V4L2_CTRL_TYPE_BOOLEAN,
303 .name = "Auto Exposure",
304 .minimum = 0,
305 .maximum = 1,
306 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300307 .default_value = 1,
Brian Johnson26e744b2009-07-19 05:52:58 -0300308 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300309 },
310};
311
312static const struct v4l2_pix_format vga_mode[] = {
313 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300314 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300315 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300316 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300317 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300318 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
319 .bytesperline = 160,
320 .sizeimage = 160 * 120,
321 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300322 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300323 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300324 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300325 .sizeimage = 240 * 120,
326 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300327 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300328 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300329 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300330 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300331 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300332 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300333 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
334 .bytesperline = 320,
335 .sizeimage = 320 * 240 ,
336 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300337 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300338 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300339 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300340 .sizeimage = 480 * 240 ,
341 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300342 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300343 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300344 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300345 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300346 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300347 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300348 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
349 .bytesperline = 640,
350 .sizeimage = 640 * 480,
351 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300352 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300353 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300354 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300355 .sizeimage = 960 * 480,
356 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300357 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300358};
359
360static const struct v4l2_pix_format sxga_mode[] = {
361 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300362 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300363 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300364 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300365 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300366 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
367 .bytesperline = 160,
368 .sizeimage = 160 * 120,
369 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300370 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300371 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300372 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300373 .sizeimage = 240 * 120,
374 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300375 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300376 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300377 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300378 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300379 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300380 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300381 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
382 .bytesperline = 320,
383 .sizeimage = 320 * 240 ,
384 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300385 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300386 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300387 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300388 .sizeimage = 480 * 240 ,
389 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300390 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300391 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300392 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300393 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300394 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300395 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300396 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
397 .bytesperline = 640,
398 .sizeimage = 640 * 480,
399 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300400 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300401 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300402 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300403 .sizeimage = 960 * 480,
404 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300405 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
407 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300408 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300409 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300410 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300411};
412
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300413static const struct v4l2_pix_format mono_mode[] = {
414 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
415 .bytesperline = 160,
416 .sizeimage = 160 * 120,
417 .colorspace = V4L2_COLORSPACE_SRGB,
418 .priv = SCALE_160x120 | MODE_RAW},
419 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
420 .bytesperline = 320,
421 .sizeimage = 320 * 240 ,
422 .colorspace = V4L2_COLORSPACE_SRGB,
423 .priv = SCALE_320x240 | MODE_RAW},
424 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
425 .bytesperline = 640,
426 .sizeimage = 640 * 480,
427 .colorspace = V4L2_COLORSPACE_SRGB,
428 .priv = SCALE_640x480 | MODE_RAW},
429 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
430 .bytesperline = 1280,
431 .sizeimage = 1280 * 1024,
432 .colorspace = V4L2_COLORSPACE_SRGB,
433 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
434};
435
Joe Perches58aa68c2009-09-02 01:12:13 -0300436static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300437 41, 44, 46, 48, 50, 52, 54, 56,
438 58, 60, 62, 64, 66, 68, 70, 72,
439 74, 76, 78, 80, 81, 83, 85, 87,
440 88, 90, 92, 93, 95, 97, 98, 100,
441 101, 102, 104, 105, 107, 108, 109, 110,
442 112, 113, 114, 115, 116, 117, 118, 119,
443 120, 121, 122, 123, 123, 124, 125, 125,
444 126, 127, 127, 128, 128, 129, 129, 129,
445 130, 130, 130, 130, 131, 131, 131, 131,
446 131, 131, 131, 131, 130, 130, 130, 130,
447 129, 129, 129, 128, 128, 127, 127, 126,
448 125, 125, 124, 123, 122, 122, 121, 120,
449 119, 118, 117, 116, 115, 114, 112, 111,
450 110, 109, 107, 106, 105, 103, 102, 101,
451 99, 98, 96, 94, 93, 91, 90, 88,
452 86, 84, 83, 81, 79, 77, 75, 74,
453 72, 70, 68, 66, 64, 62, 60, 58,
454 56, 54, 52, 49, 47, 45, 43, 41,
455 39, 36, 34, 32, 30, 28, 25, 23,
456 21, 19, 16, 14, 12, 9, 7, 5,
457 3, 0, -1, -3, -6, -8, -10, -12,
458 -15, -17, -19, -22, -24, -26, -28, -30,
459 -33, -35, -37, -39, -41, -44, -46, -48,
460 -50, -52, -54, -56, -58, -60, -62, -64,
461 -66, -68, -70, -72, -74, -76, -78, -80,
462 -81, -83, -85, -87, -88, -90, -92, -93,
463 -95, -97, -98, -100, -101, -102, -104, -105,
464 -107, -108, -109, -110, -112, -113, -114, -115,
465 -116, -117, -118, -119, -120, -121, -122, -123,
466 -123, -124, -125, -125, -126, -127, -127, -128,
467 -128, -128, -128, -128, -128, -128, -128, -128,
468 -128, -128, -128, -128, -128, -128, -128, -128,
469 -128, -128, -128, -128, -128, -128, -128, -128,
470 -128, -127, -127, -126, -125, -125, -124, -123,
471 -122, -122, -121, -120, -119, -118, -117, -116,
472 -115, -114, -112, -111, -110, -109, -107, -106,
473 -105, -103, -102, -101, -99, -98, -96, -94,
474 -93, -91, -90, -88, -86, -84, -83, -81,
475 -79, -77, -75, -74, -72, -70, -68, -66,
476 -64, -62, -60, -58, -56, -54, -52, -49,
477 -47, -45, -43, -41, -39, -36, -34, -32,
478 -30, -28, -25, -23, -21, -19, -16, -14,
479 -12, -9, -7, -5, -3, 0, 1, 3,
480 6, 8, 10, 12, 15, 17, 19, 22,
481 24, 26, 28, 30, 33, 35, 37, 39, 41
482};
483
Joe Perches58aa68c2009-09-02 01:12:13 -0300484static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300485 82, 80, 78, 76, 74, 73, 71, 69,
486 67, 65, 63, 61, 58, 56, 54, 52,
487 50, 48, 46, 44, 41, 39, 37, 35,
488 32, 30, 28, 26, 23, 21, 19, 16,
489 14, 12, 10, 7, 5, 3, 0, -1,
490 -3, -6, -8, -10, -13, -15, -17, -19,
491 -22, -24, -26, -29, -31, -33, -35, -38,
492 -40, -42, -44, -46, -48, -51, -53, -55,
493 -57, -59, -61, -63, -65, -67, -69, -71,
494 -73, -75, -77, -79, -81, -82, -84, -86,
495 -88, -89, -91, -93, -94, -96, -98, -99,
496 -101, -102, -104, -105, -106, -108, -109, -110,
497 -112, -113, -114, -115, -116, -117, -119, -120,
498 -120, -121, -122, -123, -124, -125, -126, -126,
499 -127, -128, -128, -128, -128, -128, -128, -128,
500 -128, -128, -128, -128, -128, -128, -128, -128,
501 -128, -128, -128, -128, -128, -128, -128, -128,
502 -128, -128, -128, -128, -128, -128, -128, -128,
503 -127, -127, -126, -125, -125, -124, -123, -122,
504 -121, -120, -119, -118, -117, -116, -115, -114,
505 -113, -111, -110, -109, -107, -106, -105, -103,
506 -102, -100, -99, -97, -96, -94, -92, -91,
507 -89, -87, -85, -84, -82, -80, -78, -76,
508 -74, -73, -71, -69, -67, -65, -63, -61,
509 -58, -56, -54, -52, -50, -48, -46, -44,
510 -41, -39, -37, -35, -32, -30, -28, -26,
511 -23, -21, -19, -16, -14, -12, -10, -7,
512 -5, -3, 0, 1, 3, 6, 8, 10,
513 13, 15, 17, 19, 22, 24, 26, 29,
514 31, 33, 35, 38, 40, 42, 44, 46,
515 48, 51, 53, 55, 57, 59, 61, 63,
516 65, 67, 69, 71, 73, 75, 77, 79,
517 81, 82, 84, 86, 88, 89, 91, 93,
518 94, 96, 98, 99, 101, 102, 104, 105,
519 106, 108, 109, 110, 112, 113, 114, 115,
520 116, 117, 119, 120, 120, 121, 122, 123,
521 124, 125, 126, 126, 127, 128, 128, 129,
522 129, 130, 130, 131, 131, 131, 131, 132,
523 132, 132, 132, 132, 132, 132, 132, 132,
524 132, 132, 132, 131, 131, 131, 130, 130,
525 130, 129, 129, 128, 127, 127, 126, 125,
526 125, 124, 123, 122, 121, 120, 119, 118,
527 117, 116, 115, 114, 113, 111, 110, 109,
528 107, 106, 105, 103, 102, 100, 99, 97,
529 96, 94, 92, 91, 89, 87, 85, 84, 82
530};
531
Joe Perches58aa68c2009-09-02 01:12:13 -0300532static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300533 -124, -124, -125, -125, -125, -125, -125, -125,
534 -125, -126, -126, -125, -125, -125, -125, -125,
535 -125, -124, -124, -124, -123, -123, -122, -122,
536 -121, -121, -120, -120, -119, -118, -117, -117,
537 -116, -115, -114, -113, -112, -111, -110, -109,
538 -108, -107, -105, -104, -103, -102, -100, -99,
539 -98, -96, -95, -93, -92, -91, -89, -87,
540 -86, -84, -83, -81, -79, -77, -76, -74,
541 -72, -70, -69, -67, -65, -63, -61, -59,
542 -57, -55, -53, -51, -49, -47, -45, -43,
543 -41, -39, -37, -35, -33, -30, -28, -26,
544 -24, -22, -20, -18, -15, -13, -11, -9,
545 -7, -4, -2, 0, 1, 3, 6, 8,
546 10, 12, 14, 17, 19, 21, 23, 25,
547 27, 29, 32, 34, 36, 38, 40, 42,
548 44, 46, 48, 50, 52, 54, 56, 58,
549 60, 62, 64, 66, 68, 70, 71, 73,
550 75, 77, 78, 80, 82, 83, 85, 87,
551 88, 90, 91, 93, 94, 96, 97, 98,
552 100, 101, 102, 104, 105, 106, 107, 108,
553 109, 111, 112, 113, 113, 114, 115, 116,
554 117, 118, 118, 119, 120, 120, 121, 122,
555 122, 123, 123, 124, 124, 124, 125, 125,
556 125, 125, 125, 125, 125, 126, 126, 125,
557 125, 125, 125, 125, 125, 124, 124, 124,
558 123, 123, 122, 122, 121, 121, 120, 120,
559 119, 118, 117, 117, 116, 115, 114, 113,
560 112, 111, 110, 109, 108, 107, 105, 104,
561 103, 102, 100, 99, 98, 96, 95, 93,
562 92, 91, 89, 87, 86, 84, 83, 81,
563 79, 77, 76, 74, 72, 70, 69, 67,
564 65, 63, 61, 59, 57, 55, 53, 51,
565 49, 47, 45, 43, 41, 39, 37, 35,
566 33, 30, 28, 26, 24, 22, 20, 18,
567 15, 13, 11, 9, 7, 4, 2, 0,
568 -1, -3, -6, -8, -10, -12, -14, -17,
569 -19, -21, -23, -25, -27, -29, -32, -34,
570 -36, -38, -40, -42, -44, -46, -48, -50,
571 -52, -54, -56, -58, -60, -62, -64, -66,
572 -68, -70, -71, -73, -75, -77, -78, -80,
573 -82, -83, -85, -87, -88, -90, -91, -93,
574 -94, -96, -97, -98, -100, -101, -102, -104,
575 -105, -106, -107, -108, -109, -111, -112, -113,
576 -113, -114, -115, -116, -117, -118, -118, -119,
577 -120, -120, -121, -122, -122, -123, -123, -124, -124
578};
579
Joe Perches58aa68c2009-09-02 01:12:13 -0300580static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300581 -100, -99, -98, -97, -95, -94, -93, -91,
582 -90, -89, -87, -86, -84, -83, -81, -80,
583 -78, -76, -75, -73, -71, -70, -68, -66,
584 -64, -63, -61, -59, -57, -55, -53, -51,
585 -49, -48, -46, -44, -42, -40, -38, -36,
586 -34, -32, -30, -27, -25, -23, -21, -19,
587 -17, -15, -13, -11, -9, -7, -4, -2,
588 0, 1, 3, 5, 7, 9, 11, 14,
589 16, 18, 20, 22, 24, 26, 28, 30,
590 32, 34, 36, 38, 40, 42, 44, 46,
591 48, 50, 52, 54, 56, 58, 59, 61,
592 63, 65, 67, 68, 70, 72, 74, 75,
593 77, 78, 80, 82, 83, 85, 86, 88,
594 89, 90, 92, 93, 95, 96, 97, 98,
595 100, 101, 102, 103, 104, 105, 106, 107,
596 108, 109, 110, 111, 112, 112, 113, 114,
597 115, 115, 116, 116, 117, 117, 118, 118,
598 119, 119, 119, 120, 120, 120, 120, 120,
599 121, 121, 121, 121, 121, 121, 120, 120,
600 120, 120, 120, 119, 119, 119, 118, 118,
601 117, 117, 116, 116, 115, 114, 114, 113,
602 112, 111, 111, 110, 109, 108, 107, 106,
603 105, 104, 103, 102, 100, 99, 98, 97,
604 95, 94, 93, 91, 90, 89, 87, 86,
605 84, 83, 81, 80, 78, 76, 75, 73,
606 71, 70, 68, 66, 64, 63, 61, 59,
607 57, 55, 53, 51, 49, 48, 46, 44,
608 42, 40, 38, 36, 34, 32, 30, 27,
609 25, 23, 21, 19, 17, 15, 13, 11,
610 9, 7, 4, 2, 0, -1, -3, -5,
611 -7, -9, -11, -14, -16, -18, -20, -22,
612 -24, -26, -28, -30, -32, -34, -36, -38,
613 -40, -42, -44, -46, -48, -50, -52, -54,
614 -56, -58, -59, -61, -63, -65, -67, -68,
615 -70, -72, -74, -75, -77, -78, -80, -82,
616 -83, -85, -86, -88, -89, -90, -92, -93,
617 -95, -96, -97, -98, -100, -101, -102, -103,
618 -104, -105, -106, -107, -108, -109, -110, -111,
619 -112, -112, -113, -114, -115, -115, -116, -116,
620 -117, -117, -118, -118, -119, -119, -119, -120,
621 -120, -120, -120, -120, -121, -121, -121, -121,
622 -121, -121, -120, -120, -120, -120, -120, -119,
623 -119, -119, -118, -118, -117, -117, -116, -116,
624 -115, -114, -114, -113, -112, -111, -111, -110,
625 -109, -108, -107, -106, -105, -104, -103, -102, -100
626};
627
Joe Perches58aa68c2009-09-02 01:12:13 -0300628static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300629 112, 113, 114, 114, 115, 116, 117, 117,
630 118, 118, 119, 119, 120, 120, 120, 121,
631 121, 121, 122, 122, 122, 122, 122, 122,
632 122, 122, 122, 122, 122, 122, 121, 121,
633 121, 120, 120, 120, 119, 119, 118, 118,
634 117, 116, 116, 115, 114, 113, 113, 112,
635 111, 110, 109, 108, 107, 106, 105, 104,
636 103, 102, 100, 99, 98, 97, 95, 94,
637 93, 91, 90, 88, 87, 85, 84, 82,
638 80, 79, 77, 76, 74, 72, 70, 69,
639 67, 65, 63, 61, 60, 58, 56, 54,
640 52, 50, 48, 46, 44, 42, 40, 38,
641 36, 34, 32, 30, 28, 26, 24, 22,
642 19, 17, 15, 13, 11, 9, 7, 5,
643 2, 0, -1, -3, -5, -7, -9, -12,
644 -14, -16, -18, -20, -22, -24, -26, -28,
645 -31, -33, -35, -37, -39, -41, -43, -45,
646 -47, -49, -51, -53, -54, -56, -58, -60,
647 -62, -64, -66, -67, -69, -71, -73, -74,
648 -76, -78, -79, -81, -83, -84, -86, -87,
649 -89, -90, -92, -93, -94, -96, -97, -98,
650 -99, -101, -102, -103, -104, -105, -106, -107,
651 -108, -109, -110, -111, -112, -113, -114, -114,
652 -115, -116, -117, -117, -118, -118, -119, -119,
653 -120, -120, -120, -121, -121, -121, -122, -122,
654 -122, -122, -122, -122, -122, -122, -122, -122,
655 -122, -122, -121, -121, -121, -120, -120, -120,
656 -119, -119, -118, -118, -117, -116, -116, -115,
657 -114, -113, -113, -112, -111, -110, -109, -108,
658 -107, -106, -105, -104, -103, -102, -100, -99,
659 -98, -97, -95, -94, -93, -91, -90, -88,
660 -87, -85, -84, -82, -80, -79, -77, -76,
661 -74, -72, -70, -69, -67, -65, -63, -61,
662 -60, -58, -56, -54, -52, -50, -48, -46,
663 -44, -42, -40, -38, -36, -34, -32, -30,
664 -28, -26, -24, -22, -19, -17, -15, -13,
665 -11, -9, -7, -5, -2, 0, 1, 3,
666 5, 7, 9, 12, 14, 16, 18, 20,
667 22, 24, 26, 28, 31, 33, 35, 37,
668 39, 41, 43, 45, 47, 49, 51, 53,
669 54, 56, 58, 60, 62, 64, 66, 67,
670 69, 71, 73, 74, 76, 78, 79, 81,
671 83, 84, 86, 87, 89, 90, 92, 93,
672 94, 96, 97, 98, 99, 101, 102, 103,
673 104, 105, 106, 107, 108, 109, 110, 111, 112
674};
675
Joe Perches58aa68c2009-09-02 01:12:13 -0300676static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300677 -11, -13, -15, -17, -19, -21, -23, -25,
678 -27, -29, -31, -33, -35, -37, -39, -41,
679 -43, -45, -46, -48, -50, -52, -54, -55,
680 -57, -59, -61, -62, -64, -66, -67, -69,
681 -71, -72, -74, -75, -77, -78, -80, -81,
682 -83, -84, -86, -87, -88, -90, -91, -92,
683 -93, -95, -96, -97, -98, -99, -100, -101,
684 -102, -103, -104, -105, -106, -106, -107, -108,
685 -109, -109, -110, -111, -111, -112, -112, -113,
686 -113, -114, -114, -114, -115, -115, -115, -115,
687 -116, -116, -116, -116, -116, -116, -116, -116,
688 -116, -115, -115, -115, -115, -114, -114, -114,
689 -113, -113, -112, -112, -111, -111, -110, -110,
690 -109, -108, -108, -107, -106, -105, -104, -103,
691 -102, -101, -100, -99, -98, -97, -96, -95,
692 -94, -93, -91, -90, -89, -88, -86, -85,
693 -84, -82, -81, -79, -78, -76, -75, -73,
694 -71, -70, -68, -67, -65, -63, -62, -60,
695 -58, -56, -55, -53, -51, -49, -47, -45,
696 -44, -42, -40, -38, -36, -34, -32, -30,
697 -28, -26, -24, -22, -20, -18, -16, -14,
698 -12, -10, -8, -6, -4, -2, 0, 1,
699 3, 5, 7, 9, 11, 13, 15, 17,
700 19, 21, 23, 25, 27, 29, 31, 33,
701 35, 37, 39, 41, 43, 45, 46, 48,
702 50, 52, 54, 55, 57, 59, 61, 62,
703 64, 66, 67, 69, 71, 72, 74, 75,
704 77, 78, 80, 81, 83, 84, 86, 87,
705 88, 90, 91, 92, 93, 95, 96, 97,
706 98, 99, 100, 101, 102, 103, 104, 105,
707 106, 106, 107, 108, 109, 109, 110, 111,
708 111, 112, 112, 113, 113, 114, 114, 114,
709 115, 115, 115, 115, 116, 116, 116, 116,
710 116, 116, 116, 116, 116, 115, 115, 115,
711 115, 114, 114, 114, 113, 113, 112, 112,
712 111, 111, 110, 110, 109, 108, 108, 107,
713 106, 105, 104, 103, 102, 101, 100, 99,
714 98, 97, 96, 95, 94, 93, 91, 90,
715 89, 88, 86, 85, 84, 82, 81, 79,
716 78, 76, 75, 73, 71, 70, 68, 67,
717 65, 63, 62, 60, 58, 56, 55, 53,
718 51, 49, 47, 45, 44, 42, 40, 38,
719 36, 34, 32, 30, 28, 26, 24, 22,
720 20, 18, 16, 14, 12, 10, 8, 6,
721 4, 2, 0, -1, -3, -5, -7, -9, -11
722};
723
724static u16 i2c_ident[] = {
725 V4L2_IDENT_OV9650,
726 V4L2_IDENT_OV9655,
727 V4L2_IDENT_SOI968,
728 V4L2_IDENT_OV7660,
729 V4L2_IDENT_OV7670,
730 V4L2_IDENT_MT9V011,
731 V4L2_IDENT_MT9V111,
732 V4L2_IDENT_MT9V112,
733 V4L2_IDENT_MT9M001C12ST,
734 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300735 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300736 V4L2_IDENT_HV7131R,
737};
738
739static u16 bridge_init[][2] = {
740 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
741 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
742 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
743 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
744 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
745 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
746 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
747 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
748 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
749 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
750 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
751 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
752 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
753 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
754 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
755 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
756 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
757 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300758 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
759 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300760};
761
762/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
763static u8 ov_gain[] = {
764 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
765 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
766 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
767 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
768 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
769 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
770 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
771 0x70 /* 8x */
772};
773
774/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
775static u16 micron1_gain[] = {
776 /* 1x 1.25x 1.5x 1.75x */
777 0x0020, 0x0028, 0x0030, 0x0038,
778 /* 2x 2.25x 2.5x 2.75x */
779 0x00a0, 0x00a4, 0x00a8, 0x00ac,
780 /* 3x 3.25x 3.5x 3.75x */
781 0x00b0, 0x00b4, 0x00b8, 0x00bc,
782 /* 4x 4.25x 4.5x 4.75x */
783 0x00c0, 0x00c4, 0x00c8, 0x00cc,
784 /* 5x 5.25x 5.5x 5.75x */
785 0x00d0, 0x00d4, 0x00d8, 0x00dc,
786 /* 6x 6.25x 6.5x 6.75x */
787 0x00e0, 0x00e4, 0x00e8, 0x00ec,
788 /* 7x 7.25x 7.5x 7.75x */
789 0x00f0, 0x00f4, 0x00f8, 0x00fc,
790 /* 8x */
791 0x01c0
792};
793
794/* mt9m001 sensor uses a different gain formula then other micron sensors */
795/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
796static u16 micron2_gain[] = {
797 /* 1x 1.25x 1.5x 1.75x */
798 0x0008, 0x000a, 0x000c, 0x000e,
799 /* 2x 2.25x 2.5x 2.75x */
800 0x0010, 0x0012, 0x0014, 0x0016,
801 /* 3x 3.25x 3.5x 3.75x */
802 0x0018, 0x001a, 0x001c, 0x001e,
803 /* 4x 4.25x 4.5x 4.75x */
804 0x0020, 0x0051, 0x0052, 0x0053,
805 /* 5x 5.25x 5.5x 5.75x */
806 0x0054, 0x0055, 0x0056, 0x0057,
807 /* 6x 6.25x 6.5x 6.75x */
808 0x0058, 0x0059, 0x005a, 0x005b,
809 /* 7x 7.25x 7.5x 7.75x */
810 0x005c, 0x005d, 0x005e, 0x005f,
811 /* 8x */
812 0x0060
813};
814
815/* Gain = .5 + bit[7:0] / 16 */
816static u8 hv7131r_gain[] = {
817 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
818 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
819 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
820 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
821 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
822 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
823 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
824 0x78 /* 8x */
825};
826
Joe Perches58aa68c2009-09-02 01:12:13 -0300827static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300828 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
829 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
830 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
831 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
832 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
833 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300834 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300835 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
836 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
837 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
838 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
839};
840
Joe Perches58aa68c2009-09-02 01:12:13 -0300841static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300842 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
843 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
844 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300845 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
846 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
847 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300848 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
849 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
850 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
851};
852
Joe Perches58aa68c2009-09-02 01:12:13 -0300853static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300854 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
855 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
856 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
857 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
858 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
859 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
860 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
861 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
862 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
863 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
864 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
865 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
866 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
867 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
868 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
869 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
870 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
871 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
872 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
873 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
874 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
875 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
876 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
877 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
878 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
879 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
880 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
881 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
882 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
883 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
884 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
885 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
886 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
887 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
888 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
889 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
890 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
891 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
892 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
893 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
894 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
895 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
896 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
897 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
898 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
899 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
900 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
901 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
902 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
903 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
904 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
905 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
906 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
907 {0x93, 0x00},
908};
909
Joe Perches58aa68c2009-09-02 01:12:13 -0300910static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300911 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
912 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
913 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
914 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
915 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
916 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
917 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
918 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
919 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
920 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
921 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
922 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
923 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
924 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
925 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
926 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
927 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
928 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
929 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
930 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
931 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
932 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
933 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
934 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
935 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
936 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
937 {0xaa, 0x92}, {0xab, 0x0a},
938};
939
Joe Perches58aa68c2009-09-02 01:12:13 -0300940static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300941 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
942 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
943 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
944 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
945 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
946 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
947 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
948 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
949 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
950 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
951 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
952 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
953 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
954 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
955 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
956 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300957 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300958 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
959 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300960 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300961 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
962 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
963 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
964 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300965};
966
Joe Perches58aa68c2009-09-02 01:12:13 -0300967static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300968 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
969 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
970 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
971 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
972 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
973 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
974 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
975 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
976 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
977 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
978 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
979 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
980 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
981 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
982 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
983 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
984};
985
Joe Perches58aa68c2009-09-02 01:12:13 -0300986static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300987 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -0300988 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
989 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
990 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
991 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
992 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
993 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -0300994};
995
Joe Perches58aa68c2009-09-02 01:12:13 -0300996static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300997 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
998 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
999 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1000 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1001 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1002 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1003 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1004 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1005 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1006 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1007 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1008 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1009 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1010 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1011 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1012 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1013 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1014 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1015 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1016 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1017 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1018 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1019 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1020 {0x06, 0x0029}, {0x05, 0x0009},
1021};
1022
Joe Perches58aa68c2009-09-02 01:12:13 -03001023static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001024 {0x0d, 0x0001},
1025 {0x0d, 0x0000},
1026 {0x04, 0x0500}, /* hres = 1280 */
1027 {0x03, 0x0400}, /* vres = 1024 */
1028 {0x20, 0x1100},
1029 {0x06, 0x0010},
1030 {0x2b, 0x0024},
1031 {0x2e, 0x0024},
1032 {0x35, 0x0024},
1033 {0x2d, 0x0020},
1034 {0x2c, 0x0020},
1035 {0x09, 0x0ad4},
1036 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001037};
1038
Joe Perches58aa68c2009-09-02 01:12:13 -03001039static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001040 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1041 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001042 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1043 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001044};
1045
Brian Johnsone99ac542010-03-16 13:58:28 -03001046static struct i2c_reg_u16 mt9m112_init[] = {
1047 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1048 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1049 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1050 {0xf0, 0x0000},
1051};
1052
Joe Perches58aa68c2009-09-02 01:12:13 -03001053static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001054 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1055 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1056 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1057 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1058 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1059 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1060 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1061 {0x23, 0x09}, {0x01, 0x08},
1062};
1063
Joe Perches58aa68c2009-09-02 01:12:13 -03001064static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001065{
1066 struct usb_device *dev = gspca_dev->dev;
1067 int result;
1068 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1069 0x00,
1070 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1071 reg,
1072 0x00,
1073 gspca_dev->usb_buf,
1074 length,
1075 500);
1076 if (unlikely(result < 0 || result != length)) {
Joe Perches91f58422011-08-21 19:56:55 -03001077 pr_err("Read register failed 0x%02X\n", reg);
Brian Johnson26e744b2009-07-19 05:52:58 -03001078 return -EIO;
1079 }
1080 return 0;
1081}
1082
Joe Perches58aa68c2009-09-02 01:12:13 -03001083static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1084 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001085{
1086 struct usb_device *dev = gspca_dev->dev;
1087 int result;
1088 memcpy(gspca_dev->usb_buf, buffer, length);
1089 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1090 0x08,
1091 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1092 reg,
1093 0x00,
1094 gspca_dev->usb_buf,
1095 length,
1096 500);
1097 if (unlikely(result < 0 || result != length)) {
Joe Perches91f58422011-08-21 19:56:55 -03001098 pr_err("Write register failed index 0x%02X\n", reg);
Brian Johnson26e744b2009-07-19 05:52:58 -03001099 return -EIO;
1100 }
1101 return 0;
1102}
1103
Joe Perches58aa68c2009-09-02 01:12:13 -03001104static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001105{
1106 u8 data[1] = {value};
1107 return reg_w(gspca_dev, reg, data, 1);
1108}
1109
Joe Perches58aa68c2009-09-02 01:12:13 -03001110static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001111{
1112 int i;
1113 reg_w(gspca_dev, 0x10c0, buffer, 8);
1114 for (i = 0; i < 5; i++) {
1115 reg_r(gspca_dev, 0x10c0, 1);
1116 if (gspca_dev->usb_buf[0] & 0x04) {
1117 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001118 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001119 return 0;
1120 }
1121 msleep(1);
1122 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001123 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001124}
1125
Joe Perches58aa68c2009-09-02 01:12:13 -03001126static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001127{
1128 struct sd *sd = (struct sd *) gspca_dev;
1129
1130 u8 row[8];
1131
1132 /*
1133 * from the point of view of the bridge, the length
1134 * includes the address
1135 */
1136 row[0] = 0x81 | (2 << 4);
1137 row[1] = sd->i2c_addr;
1138 row[2] = reg;
1139 row[3] = val;
1140 row[4] = 0x00;
1141 row[5] = 0x00;
1142 row[6] = 0x00;
1143 row[7] = 0x10;
1144
1145 return i2c_w(gspca_dev, row);
1146}
1147
Joe Perches58aa68c2009-09-02 01:12:13 -03001148static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001149{
1150 struct sd *sd = (struct sd *) gspca_dev;
1151 u8 row[8];
1152
1153 /*
1154 * from the point of view of the bridge, the length
1155 * includes the address
1156 */
1157 row[0] = 0x81 | (3 << 4);
1158 row[1] = sd->i2c_addr;
1159 row[2] = reg;
1160 row[3] = (val >> 8) & 0xff;
1161 row[4] = val & 0xff;
1162 row[5] = 0x00;
1163 row[6] = 0x00;
1164 row[7] = 0x10;
1165
1166 return i2c_w(gspca_dev, row);
1167}
1168
Jean-Francois Moine83955552009-12-12 06:58:01 -03001169static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001170{
1171 struct sd *sd = (struct sd *) gspca_dev;
1172 u8 row[8];
1173
Brian Johnson00b581e2009-07-23 05:55:43 -03001174 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001175 row[1] = sd->i2c_addr;
1176 row[2] = reg;
1177 row[3] = 0;
1178 row[4] = 0;
1179 row[5] = 0;
1180 row[6] = 0;
1181 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001182 if (i2c_w(gspca_dev, row) < 0)
1183 return -EIO;
1184 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001185 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001186 if (i2c_w(gspca_dev, row) < 0)
1187 return -EIO;
1188 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1189 return -EIO;
1190 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001191 return 0;
1192}
1193
Jean-Francois Moine83955552009-12-12 06:58:01 -03001194static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197 u8 row[8];
1198
Brian Johnson00b581e2009-07-23 05:55:43 -03001199 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001200 row[1] = sd->i2c_addr;
1201 row[2] = reg;
1202 row[3] = 0;
1203 row[4] = 0;
1204 row[5] = 0;
1205 row[6] = 0;
1206 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001207 if (i2c_w(gspca_dev, row) < 0)
1208 return -EIO;
1209 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001210 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001211 if (i2c_w(gspca_dev, row) < 0)
1212 return -EIO;
1213 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1214 return -EIO;
1215 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001216 return 0;
1217}
1218
1219static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1220{
1221 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001222 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001223 struct sd *sd = (struct sd *) gspca_dev;
1224
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001225 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1226 return -EINVAL;
1227
1228 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001229 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001230 return -ENODEV;
1231 }
1232
Brian Johnson26e744b2009-07-19 05:52:58 -03001233 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001234 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1235 ov9650_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001236 pr_err("OV9650 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001237 return -ENODEV;
1238 }
1239 }
1240 sd->hstart = 1;
1241 sd->vstart = 7;
1242 return 0;
1243}
1244
1245static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1246{
1247 int i;
1248 struct sd *sd = (struct sd *) gspca_dev;
1249
1250 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001251 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1252 ov9655_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001253 pr_err("OV9655 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001254 return -ENODEV;
1255 }
1256 }
1257 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001258 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001259 sd->hstart = 1;
1260 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001261 return 0;
1262}
1263
1264static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1265{
1266 int i;
1267 struct sd *sd = (struct sd *) gspca_dev;
1268
1269 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001270 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1271 soi968_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001272 pr_err("SOI968 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001273 return -ENODEV;
1274 }
1275 }
1276 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001277 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1278 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001279 sd->hstart = 60;
1280 sd->vstart = 11;
1281 return 0;
1282}
1283
1284static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1285{
1286 int i;
1287 struct sd *sd = (struct sd *) gspca_dev;
1288
1289 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001290 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1291 ov7660_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001292 pr_err("OV7660 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001293 return -ENODEV;
1294 }
1295 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001296 sd->hstart = 3;
1297 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001298 return 0;
1299}
1300
1301static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1302{
1303 int i;
1304 struct sd *sd = (struct sd *) gspca_dev;
1305
1306 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001307 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1308 ov7670_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001309 pr_err("OV7670 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001310 return -ENODEV;
1311 }
1312 }
1313 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001314 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001315 sd->hstart = 0;
1316 sd->vstart = 1;
1317 return 0;
1318}
1319
1320static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1321{
1322 struct sd *sd = (struct sd *) gspca_dev;
1323 int i;
1324 u16 value;
1325 int ret;
1326
1327 sd->i2c_addr = 0x5d;
1328 ret = i2c_r2(gspca_dev, 0xff, &value);
1329 if ((ret == 0) && (value == 0x8243)) {
1330 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001331 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1332 mt9v011_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001333 pr_err("MT9V011 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001334 return -ENODEV;
1335 }
1336 }
1337 sd->hstart = 2;
1338 sd->vstart = 2;
1339 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001340 pr_info("MT9V011 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001341 return 0;
1342 }
1343
1344 sd->i2c_addr = 0x5c;
1345 i2c_w2(gspca_dev, 0x01, 0x0004);
1346 ret = i2c_r2(gspca_dev, 0xff, &value);
1347 if ((ret == 0) && (value == 0x823a)) {
1348 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001349 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1350 mt9v111_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001351 pr_err("MT9V111 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001352 return -ENODEV;
1353 }
1354 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001355 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1356 | (1 << AUTOGAIN)
1357 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001358 sd->hstart = 2;
1359 sd->vstart = 2;
1360 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001361 pr_info("MT9V111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001362 return 0;
1363 }
1364
1365 sd->i2c_addr = 0x5d;
1366 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1367 if (ret < 0) {
1368 sd->i2c_addr = 0x48;
1369 i2c_w2(gspca_dev, 0xf0, 0x0000);
1370 }
1371 ret = i2c_r2(gspca_dev, 0x00, &value);
1372 if ((ret == 0) && (value == 0x1229)) {
1373 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001374 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1375 mt9v112_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001376 pr_err("MT9V112 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001377 return -ENODEV;
1378 }
1379 }
1380 sd->hstart = 6;
1381 sd->vstart = 2;
1382 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001383 pr_info("MT9V112 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001384 return 0;
1385 }
1386
1387 return -ENODEV;
1388}
1389
Brian Johnsone99ac542010-03-16 13:58:28 -03001390static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1391{
1392 struct sd *sd = (struct sd *) gspca_dev;
1393 int i;
1394 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1395 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1396 mt9m112_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001397 pr_err("MT9M112 sensor initialization failed\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001398 return -ENODEV;
1399 }
1400 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001401 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1402 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001403 sd->hstart = 0;
1404 sd->vstart = 2;
1405 return 0;
1406}
1407
Brian Johnson26e744b2009-07-19 05:52:58 -03001408static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1409{
1410 struct sd *sd = (struct sd *) gspca_dev;
1411 int i;
1412 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001413 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1414 mt9m111_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001415 pr_err("MT9M111 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001416 return -ENODEV;
1417 }
1418 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001419 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1420 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001421 sd->hstart = 0;
1422 sd->vstart = 2;
1423 return 0;
1424}
1425
1426static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1427{
1428 struct sd *sd = (struct sd *) gspca_dev;
1429 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001430 u16 id;
1431
1432 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1433 return -EINVAL;
1434
1435 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1436 switch (id) {
1437 case 0x8411:
1438 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001439 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001440 break;
1441 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001442 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001443 break;
1444 default:
Joe Perches91f58422011-08-21 19:56:55 -03001445 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001446 return -ENODEV;
1447 }
1448
Brian Johnson26e744b2009-07-19 05:52:58 -03001449 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001450 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1451 mt9m001_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001452 pr_err("MT9M001 sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001453 return -ENODEV;
1454 }
1455 }
1456 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001457 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001458 sd->hstart = 1;
1459 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001460 return 0;
1461}
1462
1463static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1464{
1465 int i;
1466 struct sd *sd = (struct sd *) gspca_dev;
1467
1468 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001469 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1470 hv7131r_init[i].val) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001471 pr_err("HV7131R Sensor initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001472 return -ENODEV;
1473 }
1474 }
1475 sd->hstart = 0;
1476 sd->vstart = 1;
1477 return 0;
1478}
1479
Jean-François Moinec5224d82012-03-19 04:30:07 -03001480static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001481{
1482 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001483 int satur;
1484 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001485 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001486
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001487 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001488 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001489 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1490 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001491 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001492
Jean-François Moinec5224d82012-03-19 04:30:07 -03001493 satur = sd->ctrls[SATURATION].val;
1494 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001495 cmatrix[6] = hue_coord;
1496 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001497
Jean-François Moinec5224d82012-03-19 04:30:07 -03001498 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001499 cmatrix[8] = hue_coord;
1500 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501
Jean-François Moinec5224d82012-03-19 04:30:07 -03001502 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001503 cmatrix[10] = hue_coord;
1504 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001505
Jean-François Moinec5224d82012-03-19 04:30:07 -03001506 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001507 cmatrix[12] = hue_coord;
1508 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001509
Jean-François Moinec5224d82012-03-19 04:30:07 -03001510 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001511 cmatrix[14] = hue_coord;
1512 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001513
Jean-François Moinec5224d82012-03-19 04:30:07 -03001514 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001515 cmatrix[16] = hue_coord;
1516 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001517
Jean-François Moinec5224d82012-03-19 04:30:07 -03001518 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001519}
1520
Jean-François Moinec5224d82012-03-19 04:30:07 -03001521static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001522{
1523 struct sd *sd = (struct sd *) gspca_dev;
1524 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001525 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001526
1527 gamma[0] = 0x0a;
1528 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1529 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1530 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1531 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1532 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1533 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1534 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1535 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1536 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1537 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1538 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1539 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1540 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1541 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1542 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1543 gamma[16] = 0xf5;
1544
Jean-François Moinec5224d82012-03-19 04:30:07 -03001545 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001546}
1547
Jean-François Moinec5224d82012-03-19 04:30:07 -03001548static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001549{
1550 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001551
1552 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1553 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001554}
1555
Jean-François Moinec5224d82012-03-19 04:30:07 -03001556static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001557{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001558 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001559 u16 value2;
1560 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001561
1562 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001563 hflip = !sd->ctrls[HFLIP].val;
1564 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001565 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001566 hflip = sd->ctrls[HFLIP].val;
1567 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001568 }
1569
Brian Johnson26e744b2009-07-19 05:52:58 -03001570 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001571 case SENSOR_OV7660:
1572 value = 0x01;
1573 if (hflip)
1574 value |= 0x20;
1575 if (vflip) {
1576 value |= 0x10;
1577 sd->vstart = 2;
1578 } else
1579 sd->vstart = 3;
1580 reg_w1(gspca_dev, 0x1182, sd->vstart);
1581 i2c_w1(gspca_dev, 0x1e, value);
1582 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001583 case SENSOR_OV9650:
1584 i2c_r1(gspca_dev, 0x1e, &value);
1585 value &= ~0x30;
1586 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001587 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001588 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001589 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001590 value |= 0x10;
1591 tslb = 0x49;
1592 }
1593 i2c_w1(gspca_dev, 0x1e, value);
1594 i2c_w1(gspca_dev, 0x3a, tslb);
1595 break;
1596 case SENSOR_MT9V111:
1597 case SENSOR_MT9V011:
1598 i2c_r2(gspca_dev, 0x20, &value2);
1599 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001600 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001601 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001602 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001603 value2 |= 0x4020;
1604 i2c_w2(gspca_dev, 0x20, value2);
1605 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001606 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001607 case SENSOR_MT9M111:
1608 case SENSOR_MT9V112:
1609 i2c_r2(gspca_dev, 0x20, &value2);
1610 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001611 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001612 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001613 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001614 value2 |= 0x0001;
1615 i2c_w2(gspca_dev, 0x20, value2);
1616 break;
1617 case SENSOR_HV7131R:
1618 i2c_r1(gspca_dev, 0x01, &value);
1619 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001620 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001621 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001622 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001623 value |= 0x02;
1624 i2c_w1(gspca_dev, 0x01, value);
1625 break;
1626 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001627}
1628
Jean-François Moinec5224d82012-03-19 04:30:07 -03001629static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001630{
1631 struct sd *sd = (struct sd *) gspca_dev;
1632 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001633 int expo;
1634
1635 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001636 switch (sd->sensor) {
1637 case SENSOR_OV7660:
1638 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001639 case SENSOR_OV9655:
1640 case SENSOR_OV9650:
1641 exp[0] |= (3 << 4);
1642 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001643 exp[3] = expo;
1644 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001645 break;
1646 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001647 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001648 case SENSOR_MT9V011:
1649 exp[0] |= (3 << 4);
1650 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001651 exp[3] = expo >> 8;
1652 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001653 break;
1654 case SENSOR_HV7131R:
1655 exp[0] |= (4 << 4);
1656 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001657 exp[3] = expo >> 5;
1658 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001659 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001660 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001661 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001662 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001663 }
1664 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001665}
1666
Jean-François Moinec5224d82012-03-19 04:30:07 -03001667static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001668{
1669 struct sd *sd = (struct sd *) gspca_dev;
1670 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001671 int g;
1672
1673 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001674 switch (sd->sensor) {
1675 case SENSOR_OV7660:
1676 case SENSOR_OV7670:
1677 case SENSOR_SOI968:
1678 case SENSOR_OV9655:
1679 case SENSOR_OV9650:
1680 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001681 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001682 break;
1683 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001684 gain[0] |= (3 << 4);
1685 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001686 gain[3] = micron1_gain[g] >> 8;
1687 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001688 break;
1689 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001690 gain[0] |= (3 << 4);
1691 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001692 gain[3] = micron1_gain[g] >> 8;
1693 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001694 break;
1695 case SENSOR_MT9M001:
1696 gain[0] |= (3 << 4);
1697 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001698 gain[3] = micron2_gain[g] >> 8;
1699 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001700 break;
1701 case SENSOR_HV7131R:
1702 gain[0] |= (2 << 4);
1703 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001704 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001705 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001706 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001707 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001708 }
1709 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001710}
1711
1712#ifdef CONFIG_VIDEO_ADV_DEBUG
1713static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1714 struct v4l2_dbg_register *reg)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717 switch (reg->match.type) {
1718 case V4L2_CHIP_MATCH_HOST:
1719 if (reg->match.addr != 0)
1720 return -EINVAL;
1721 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1722 return -EINVAL;
1723 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1724 return -EINVAL;
1725 reg->val = gspca_dev->usb_buf[0];
1726 return 0;
1727 case V4L2_CHIP_MATCH_I2C_ADDR:
1728 if (reg->match.addr != sd->i2c_addr)
1729 return -EINVAL;
1730 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001731 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001732 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1733 return -EINVAL;
1734 } else {
1735 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1736 return -EINVAL;
1737 }
1738 return 0;
1739 }
1740 return -EINVAL;
1741}
1742
1743static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1744 struct v4l2_dbg_register *reg)
1745{
1746 struct sd *sd = (struct sd *) gspca_dev;
1747 switch (reg->match.type) {
1748 case V4L2_CHIP_MATCH_HOST:
1749 if (reg->match.addr != 0)
1750 return -EINVAL;
1751 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1752 return -EINVAL;
1753 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1754 return -EINVAL;
1755 return 0;
1756 case V4L2_CHIP_MATCH_I2C_ADDR:
1757 if (reg->match.addr != sd->i2c_addr)
1758 return -EINVAL;
1759 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001760 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001761 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1762 return -EINVAL;
1763 } else {
1764 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1765 return -EINVAL;
1766 }
1767 return 0;
1768 }
1769 return -EINVAL;
1770}
1771#endif
1772
1773static int sd_chip_ident(struct gspca_dev *gspca_dev,
1774 struct v4l2_dbg_chip_ident *chip)
1775{
1776 struct sd *sd = (struct sd *) gspca_dev;
1777
1778 switch (chip->match.type) {
1779 case V4L2_CHIP_MATCH_HOST:
1780 if (chip->match.addr != 0)
1781 return -EINVAL;
1782 chip->revision = 0;
1783 chip->ident = V4L2_IDENT_SN9C20X;
1784 return 0;
1785 case V4L2_CHIP_MATCH_I2C_ADDR:
1786 if (chip->match.addr != sd->i2c_addr)
1787 return -EINVAL;
1788 chip->revision = 0;
1789 chip->ident = i2c_ident[sd->sensor];
1790 return 0;
1791 }
1792 return -EINVAL;
1793}
1794
1795static int sd_config(struct gspca_dev *gspca_dev,
1796 const struct usb_device_id *id)
1797{
1798 struct sd *sd = (struct sd *) gspca_dev;
1799 struct cam *cam;
1800
1801 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001802 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001803
1804 sd->sensor = (id->driver_info >> 8) & 0xff;
1805 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001806 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001807
1808 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001809 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001810 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001811 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001812 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001813 cam->cam_mode = sxga_mode;
1814 cam->nmodes = ARRAY_SIZE(sxga_mode);
1815 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001816 case SENSOR_MT9M001:
1817 cam->cam_mode = mono_mode;
1818 cam->nmodes = ARRAY_SIZE(mono_mode);
1819 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001820 default:
1821 cam->cam_mode = vga_mode;
1822 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001823 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001824 }
1825
1826 sd->old_step = 0;
1827 sd->older_step = 0;
1828 sd->exposure_step = 16;
1829
Jean-François Moinec5224d82012-03-19 04:30:07 -03001830 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001831
1832 sd->quality = 95;
1833
Brian Johnson26e744b2009-07-19 05:52:58 -03001834 return 0;
1835}
1836
1837static int sd_init(struct gspca_dev *gspca_dev)
1838{
1839 struct sd *sd = (struct sd *) gspca_dev;
1840 int i;
1841 u8 value;
1842 u8 i2c_init[9] =
1843 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1844
1845 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1846 value = bridge_init[i][1];
1847 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001848 pr_err("Device initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001849 return -ENODEV;
1850 }
1851 }
1852
Brian Johnson0c045eb2010-03-16 13:58:27 -03001853 if (sd->flags & LED_REVERSE)
1854 reg_w1(gspca_dev, 0x1006, 0x00);
1855 else
1856 reg_w1(gspca_dev, 0x1006, 0x20);
1857
Brian Johnson26e744b2009-07-19 05:52:58 -03001858 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001859 pr_err("Device initialization failed\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001860 return -ENODEV;
1861 }
1862
1863 switch (sd->sensor) {
1864 case SENSOR_OV9650:
1865 if (ov9650_init_sensor(gspca_dev) < 0)
1866 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001867 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001868 break;
1869 case SENSOR_OV9655:
1870 if (ov9655_init_sensor(gspca_dev) < 0)
1871 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001872 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001873 break;
1874 case SENSOR_SOI968:
1875 if (soi968_init_sensor(gspca_dev) < 0)
1876 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001877 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001878 break;
1879 case SENSOR_OV7660:
1880 if (ov7660_init_sensor(gspca_dev) < 0)
1881 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001882 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001883 break;
1884 case SENSOR_OV7670:
1885 if (ov7670_init_sensor(gspca_dev) < 0)
1886 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001887 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001888 break;
1889 case SENSOR_MT9VPRB:
1890 if (mt9v_init_sensor(gspca_dev) < 0)
1891 return -ENODEV;
1892 break;
1893 case SENSOR_MT9M111:
1894 if (mt9m111_init_sensor(gspca_dev) < 0)
1895 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001896 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001897 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001898 case SENSOR_MT9M112:
1899 if (mt9m112_init_sensor(gspca_dev) < 0)
1900 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001901 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001902 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001903 case SENSOR_MT9M001:
1904 if (mt9m001_init_sensor(gspca_dev) < 0)
1905 return -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001906 break;
1907 case SENSOR_HV7131R:
1908 if (hv7131r_init_sensor(gspca_dev) < 0)
1909 return -ENODEV;
Joe Perches91f58422011-08-21 19:56:55 -03001910 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001911 break;
1912 default:
Joe Perches91f58422011-08-21 19:56:55 -03001913 pr_info("Unsupported Sensor\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001914 return -ENODEV;
1915 }
1916
1917 return 0;
1918}
1919
1920static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1921{
1922 struct sd *sd = (struct sd *) gspca_dev;
1923 u8 value;
1924 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001925 case SENSOR_SOI968:
1926 if (mode & MODE_SXGA) {
1927 i2c_w1(gspca_dev, 0x17, 0x1d);
1928 i2c_w1(gspca_dev, 0x18, 0xbd);
1929 i2c_w1(gspca_dev, 0x19, 0x01);
1930 i2c_w1(gspca_dev, 0x1a, 0x81);
1931 i2c_w1(gspca_dev, 0x12, 0x00);
1932 sd->hstart = 140;
1933 sd->vstart = 19;
1934 } else {
1935 i2c_w1(gspca_dev, 0x17, 0x13);
1936 i2c_w1(gspca_dev, 0x18, 0x63);
1937 i2c_w1(gspca_dev, 0x19, 0x01);
1938 i2c_w1(gspca_dev, 0x1a, 0x79);
1939 i2c_w1(gspca_dev, 0x12, 0x40);
1940 sd->hstart = 60;
1941 sd->vstart = 11;
1942 }
1943 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001944 case SENSOR_OV9650:
1945 if (mode & MODE_SXGA) {
1946 i2c_w1(gspca_dev, 0x17, 0x1b);
1947 i2c_w1(gspca_dev, 0x18, 0xbc);
1948 i2c_w1(gspca_dev, 0x19, 0x01);
1949 i2c_w1(gspca_dev, 0x1a, 0x82);
1950 i2c_r1(gspca_dev, 0x12, &value);
1951 i2c_w1(gspca_dev, 0x12, value & 0x07);
1952 } else {
1953 i2c_w1(gspca_dev, 0x17, 0x24);
1954 i2c_w1(gspca_dev, 0x18, 0xc5);
1955 i2c_w1(gspca_dev, 0x19, 0x00);
1956 i2c_w1(gspca_dev, 0x1a, 0x3c);
1957 i2c_r1(gspca_dev, 0x12, &value);
1958 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1959 }
1960 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001961 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001962 case SENSOR_MT9M111:
1963 if (mode & MODE_SXGA) {
1964 i2c_w2(gspca_dev, 0xf0, 0x0002);
1965 i2c_w2(gspca_dev, 0xc8, 0x970b);
1966 i2c_w2(gspca_dev, 0xf0, 0x0000);
1967 } else {
1968 i2c_w2(gspca_dev, 0xf0, 0x0002);
1969 i2c_w2(gspca_dev, 0xc8, 0x8000);
1970 i2c_w2(gspca_dev, 0xf0, 0x0000);
1971 }
1972 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001973 }
1974}
1975
Hans de Goeded80dd5d2012-01-01 16:03:37 -03001976static int sd_isoc_init(struct gspca_dev *gspca_dev)
1977{
1978 struct usb_interface *intf;
1979 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
1980
1981 /*
1982 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
1983 * than our regular bandwidth calculations reserve, so we force the
1984 * use of a specific altsetting when using the SN9C20X_I420 fmt.
1985 */
1986 if (!(flags & (MODE_RAW | MODE_JPEG))) {
1987 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
1988
1989 if (intf->num_altsetting != 9) {
1990 pr_warn("sn9c20x camera with unknown number of alt "
1991 "settings (%d), please report!\n",
1992 intf->num_altsetting);
1993 gspca_dev->alt = intf->num_altsetting;
1994 return 0;
1995 }
1996
1997 switch (gspca_dev->width) {
1998 case 160: /* 160x120 */
1999 gspca_dev->alt = 2;
2000 break;
2001 case 320: /* 320x240 */
2002 gspca_dev->alt = 6;
2003 break;
2004 default: /* >= 640x480 */
2005 gspca_dev->alt = 9;
2006 }
2007 }
2008
2009 return 0;
2010}
2011
Brian Johnson26e744b2009-07-19 05:52:58 -03002012#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002013((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002014(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2015(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2016
2017#define CLR_WIN(width, height) \
2018((const u8 [])\
2019{0, width >> 2, 0, height >> 1,\
2020((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2021
2022static int sd_start(struct gspca_dev *gspca_dev)
2023{
2024 struct sd *sd = (struct sd *) gspca_dev;
2025 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2026 int width = gspca_dev->width;
2027 int height = gspca_dev->height;
2028 u8 fmt, scale = 0;
2029
Brian Johnson26e744b2009-07-19 05:52:58 -03002030 jpeg_define(sd->jpeg_hdr, height, width,
2031 0x21);
2032 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2033
2034 if (mode & MODE_RAW)
2035 fmt = 0x2d;
2036 else if (mode & MODE_JPEG)
2037 fmt = 0x2c;
2038 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002039 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002040
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002041 switch (mode & SCALE_MASK) {
2042 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002043 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002044 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002045 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002046 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002047 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002048 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002049 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002050 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002051 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002052 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002053 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002054 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002055 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002056 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002057 break;
2058 }
2059
2060 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002061 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2062 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002063 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2064 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2065 reg_w1(gspca_dev, 0x1189, scale);
2066 reg_w1(gspca_dev, 0x10e0, fmt);
2067
2068 set_cmatrix(gspca_dev);
2069 set_gamma(gspca_dev);
2070 set_redblue(gspca_dev);
2071 set_gain(gspca_dev);
2072 set_exposure(gspca_dev);
2073 set_hvflip(gspca_dev);
2074
Brian Johnson0c045eb2010-03-16 13:58:27 -03002075 reg_w1(gspca_dev, 0x1007, 0x20);
2076
Brian Johnson26e744b2009-07-19 05:52:58 -03002077 reg_r(gspca_dev, 0x1061, 1);
2078 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2079 return 0;
2080}
2081
2082static void sd_stopN(struct gspca_dev *gspca_dev)
2083{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002084 reg_w1(gspca_dev, 0x1007, 0x00);
2085
Brian Johnson26e744b2009-07-19 05:52:58 -03002086 reg_r(gspca_dev, 0x1061, 1);
2087 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2088}
2089
Brian Johnsone1430472009-09-02 12:39:41 -03002090static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002091{
2092 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002093 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002094
2095 /*
2096 * some hardcoded values are present
2097 * like those for maximal/minimal exposure
2098 * and exposure steps
2099 */
2100 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002101 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002102 return;
2103
Jean-François Moinec5224d82012-03-19 04:30:07 -03002104 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002105 if (new_exp > 0x1770)
2106 new_exp = 0x1770;
2107 if (new_exp < 0x10)
2108 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002109 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002110 set_exposure(gspca_dev);
2111
2112 sd->older_step = sd->old_step;
2113 sd->old_step = 1;
2114
2115 if (sd->old_step ^ sd->older_step)
2116 sd->exposure_step /= 2;
2117 else
2118 sd->exposure_step += 2;
2119 }
2120 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002121 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002122 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002123 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002124 if (new_exp > 0x1700)
2125 new_exp = 0x1770;
2126 if (new_exp < 0x10)
2127 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002128 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002129 set_exposure(gspca_dev);
2130 sd->older_step = sd->old_step;
2131 sd->old_step = 0;
2132
2133 if (sd->old_step ^ sd->older_step)
2134 sd->exposure_step /= 2;
2135 else
2136 sd->exposure_step += 2;
2137 }
2138}
2139
Brian Johnsone1430472009-09-02 12:39:41 -03002140static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2141{
2142 struct sd *sd = (struct sd *) gspca_dev;
2143
2144 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002145 if (sd->ctrls[GAIN].val + 1 <= 28) {
2146 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002147 set_gain(gspca_dev);
2148 }
2149 }
2150 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002151 if (sd->ctrls[GAIN].val > 0) {
2152 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002153 set_gain(gspca_dev);
2154 }
2155 }
2156}
2157
2158static void sd_dqcallback(struct gspca_dev *gspca_dev)
2159{
2160 struct sd *sd = (struct sd *) gspca_dev;
2161 int avg_lum;
2162
Jean-François Moinec5224d82012-03-19 04:30:07 -03002163 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002164 return;
2165
2166 avg_lum = atomic_read(&sd->avg_lum);
2167 if (sd->sensor == SENSOR_SOI968)
2168 do_autogain(gspca_dev, avg_lum);
2169 else
2170 do_autoexposure(gspca_dev, avg_lum);
2171}
2172
Jean-François Moine28566432010-10-01 07:33:26 -03002173#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002174static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2175 u8 *data, /* interrupt packet */
2176 int len) /* interrupt packet length */
2177{
2178 struct sd *sd = (struct sd *) gspca_dev;
2179 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002180 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002181 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2182 input_sync(gspca_dev->input_dev);
2183 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2184 input_sync(gspca_dev->input_dev);
2185 ret = 0;
2186 }
2187 return ret;
2188}
2189#endif
2190
Brian Johnson26e744b2009-07-19 05:52:58 -03002191static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002192 u8 *data, /* isoc packet */
2193 int len) /* iso packet length */
2194{
2195 struct sd *sd = (struct sd *) gspca_dev;
2196 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002197 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002198 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002199 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002200 avg_lum = ((data[35] >> 2) & 3) |
2201 (data[20] << 2) |
2202 (data[19] << 10);
2203 avg_lum += ((data[35] >> 4) & 3) |
2204 (data[22] << 2) |
2205 (data[21] << 10);
2206 avg_lum += ((data[35] >> 6) & 3) |
2207 (data[24] << 2) |
2208 (data[23] << 10);
2209 avg_lum += (data[36] & 3) |
2210 (data[26] << 2) |
2211 (data[25] << 10);
2212 avg_lum += ((data[36] >> 2) & 3) |
2213 (data[28] << 2) |
2214 (data[27] << 10);
2215 avg_lum += ((data[36] >> 4) & 3) |
2216 (data[30] << 2) |
2217 (data[29] << 10);
2218 avg_lum += ((data[36] >> 6) & 3) |
2219 (data[32] << 2) |
2220 (data[31] << 10);
2221 avg_lum += ((data[44] >> 4) & 3) |
2222 (data[34] << 2) |
2223 (data[33] << 10);
2224 avg_lum >>= 9;
2225 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002226 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002227 len -= 64;
2228 if (len == 0)
2229 return;
2230 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002231 }
2232 if (gspca_dev->last_packet_type == LAST_PACKET) {
2233 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2234 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002235 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002236 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002237 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002238 data, len);
2239 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002240 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002241 data, len);
2242 }
2243 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002244 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002245 }
2246}
2247
2248/* sub-driver description */
2249static const struct sd_desc sd_desc = {
2250 .name = MODULE_NAME,
2251 .ctrls = sd_ctrls,
2252 .nctrls = ARRAY_SIZE(sd_ctrls),
2253 .config = sd_config,
2254 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002255 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002256 .start = sd_start,
2257 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002258 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002259#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002260 .int_pkt_scan = sd_int_pkt_scan,
2261#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002262 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002263#ifdef CONFIG_VIDEO_ADV_DEBUG
2264 .set_register = sd_dbg_s_register,
2265 .get_register = sd_dbg_g_register,
2266#endif
2267 .get_chip_ident = sd_chip_ident,
2268};
2269
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002270#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002271 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002272 | (SENSOR_ ## sensor << 8) \
2273 | (i2c_addr)
2274
Jean-François Moine95c967c2011-01-13 05:20:29 -03002275static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002276 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2277 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2278 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002279 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002280 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2281 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2282 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002283 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2284 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2285 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2286 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002287 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002288 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2289 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2290 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2291 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002292 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002293 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002294 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2295 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2296 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2297 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002298 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002299 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002300 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2301 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2302 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2303 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002304 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2305 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002306 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2307 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2308 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2309 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002310 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002311 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2312 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2313 {}
2314};
2315MODULE_DEVICE_TABLE(usb, device_table);
2316
2317/* -- device connect -- */
2318static int sd_probe(struct usb_interface *intf,
2319 const struct usb_device_id *id)
2320{
2321 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2322 THIS_MODULE);
2323}
2324
Brian Johnson26e744b2009-07-19 05:52:58 -03002325static struct usb_driver sd_driver = {
2326 .name = MODULE_NAME,
2327 .id_table = device_table,
2328 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002329 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002330#ifdef CONFIG_PM
2331 .suspend = gspca_suspend,
2332 .resume = gspca_resume,
2333 .reset_resume = gspca_resume,
2334#endif
2335};
2336
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002337module_usb_driver(sd_driver);