blob: 97c653f9f98349a9d7b8922b980c6719146a7669 [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[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300828 {0x0c, 0x00}, {0x0f, 0x1f},
Brian Johnson26e744b2009-07-19 05:52:58 -0300829 {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[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300854 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300855 {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[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300911 {0x00, 0x00}, {0x01, 0x78},
Brian Johnson26e744b2009-07-19 05:52:58 -0300912 {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[] = {
Jean-François Moine92884f82012-03-19 04:33:30 -0300941 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300942 {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
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001064static void 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;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001068
1069 if (gspca_dev->usb_err < 0)
1070 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001071 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1072 0x00,
1073 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1074 reg,
1075 0x00,
1076 gspca_dev->usb_buf,
1077 length,
1078 500);
1079 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001080 pr_err("Read register %02x failed %d\n", reg, result);
1081 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001082 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001083}
1084
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001085static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
Joe Perches58aa68c2009-09-02 01:12:13 -03001086 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001087{
1088 struct usb_device *dev = gspca_dev->dev;
1089 int result;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001090
1091 if (gspca_dev->usb_err < 0)
1092 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001093 memcpy(gspca_dev->usb_buf, buffer, length);
1094 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1095 0x08,
1096 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1097 reg,
1098 0x00,
1099 gspca_dev->usb_buf,
1100 length,
1101 500);
1102 if (unlikely(result < 0 || result != length)) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001103 pr_err("Write register %02x failed %d\n", reg, result);
1104 gspca_dev->usb_err = result;
Brian Johnson26e744b2009-07-19 05:52:58 -03001105 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001106}
1107
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001108static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001109{
1110 u8 data[1] = {value};
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001111 reg_w(gspca_dev, reg, data, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001112}
1113
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001114static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001115{
1116 int i;
1117 reg_w(gspca_dev, 0x10c0, buffer, 8);
1118 for (i = 0; i < 5; i++) {
1119 reg_r(gspca_dev, 0x10c0, 1);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001120 if (gspca_dev->usb_err < 0)
1121 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001122 if (gspca_dev->usb_buf[0] & 0x04) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001123 if (gspca_dev->usb_buf[0] & 0x08) {
1124 pr_err("i2c_w error\n");
1125 gspca_dev->usb_err = -EIO;
1126 }
1127 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001128 }
1129 msleep(1);
1130 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001131 pr_err("i2c_w reg %02x no response\n", buffer[2]);
1132/* gspca_dev->usb_err = -EIO; fixme: may occur */
Brian Johnson26e744b2009-07-19 05:52:58 -03001133}
1134
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001135static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001136{
1137 struct sd *sd = (struct sd *) gspca_dev;
1138
1139 u8 row[8];
1140
1141 /*
1142 * from the point of view of the bridge, the length
1143 * includes the address
1144 */
1145 row[0] = 0x81 | (2 << 4);
1146 row[1] = sd->i2c_addr;
1147 row[2] = reg;
1148 row[3] = val;
1149 row[4] = 0x00;
1150 row[5] = 0x00;
1151 row[6] = 0x00;
1152 row[7] = 0x10;
1153
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001154 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001155}
1156
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001157static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001158{
1159 struct sd *sd = (struct sd *) gspca_dev;
1160 u8 row[8];
1161
1162 /*
1163 * from the point of view of the bridge, the length
1164 * includes the address
1165 */
1166 row[0] = 0x81 | (3 << 4);
1167 row[1] = sd->i2c_addr;
1168 row[2] = reg;
1169 row[3] = (val >> 8) & 0xff;
1170 row[4] = val & 0xff;
1171 row[5] = 0x00;
1172 row[6] = 0x00;
1173 row[7] = 0x10;
1174
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001175 i2c_w(gspca_dev, row);
Brian Johnson26e744b2009-07-19 05:52:58 -03001176}
1177
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001178static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001179{
1180 struct sd *sd = (struct sd *) gspca_dev;
1181 u8 row[8];
1182
Brian Johnson00b581e2009-07-23 05:55:43 -03001183 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001184 row[1] = sd->i2c_addr;
1185 row[2] = reg;
1186 row[3] = 0;
1187 row[4] = 0;
1188 row[5] = 0;
1189 row[6] = 0;
1190 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001191 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001192 row[0] = 0x81 | (1 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001193 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001194 i2c_w(gspca_dev, row);
1195 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001196 *val = gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001197}
1198
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001199static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001200{
1201 struct sd *sd = (struct sd *) gspca_dev;
1202 u8 row[8];
1203
Brian Johnson00b581e2009-07-23 05:55:43 -03001204 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001205 row[1] = sd->i2c_addr;
1206 row[2] = reg;
1207 row[3] = 0;
1208 row[4] = 0;
1209 row[5] = 0;
1210 row[6] = 0;
1211 row[7] = 0x10;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001212 i2c_w(gspca_dev, row);
Brian Johnson00b581e2009-07-23 05:55:43 -03001213 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001214 row[2] = 0;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001215 i2c_w(gspca_dev, row);
1216 reg_r(gspca_dev, 0x10c2, 5);
Brian Johnson00b581e2009-07-23 05:55:43 -03001217 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001218}
1219
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001220static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001221{
1222 int i;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001223 u16 id;
Brian Johnson26e744b2009-07-19 05:52:58 -03001224 struct sd *sd = (struct sd *) gspca_dev;
1225
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001226 i2c_r2(gspca_dev, 0x1c, &id);
1227 if (gspca_dev->usb_err < 0)
1228 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001229
1230 if (id != 0x7fa2) {
Joe Perches91f58422011-08-21 19:56:55 -03001231 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001232 gspca_dev->usb_err = -ENODEV;
1233 return;
Mauro Carvalho Chehabe78567d2010-12-06 06:53:05 -03001234 }
1235
Jean-François Moine92884f82012-03-19 04:33:30 -03001236 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1237 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001238 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001239 i2c_w1(gspca_dev, ov9650_init[i].reg,
1240 ov9650_init[i].val);
1241 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001242 pr_err("OV9650 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001243 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001244 }
1245 }
1246 sd->hstart = 1;
1247 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001248}
1249
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001250static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001251{
1252 int i;
1253 struct sd *sd = (struct sd *) gspca_dev;
1254
Jean-François Moine92884f82012-03-19 04:33:30 -03001255 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1256 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001257 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001258 i2c_w1(gspca_dev, ov9655_init[i].reg,
1259 ov9655_init[i].val);
1260 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001261 pr_err("OV9655 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001262 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001263 }
1264 }
1265 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001266 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001267 sd->hstart = 1;
1268 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001269}
1270
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001271static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001272{
1273 int i;
1274 struct sd *sd = (struct sd *) gspca_dev;
1275
Jean-François Moine92884f82012-03-19 04:33:30 -03001276 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1277 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001278 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001279 i2c_w1(gspca_dev, soi968_init[i].reg,
1280 soi968_init[i].val);
1281 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001282 pr_err("SOI968 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001283 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001284 }
1285 }
1286 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001287 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1288 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001289 sd->hstart = 60;
1290 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001291}
1292
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001293static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001294{
1295 int i;
1296 struct sd *sd = (struct sd *) gspca_dev;
1297
Jean-François Moine92884f82012-03-19 04:33:30 -03001298 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1299 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001300 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001301 i2c_w1(gspca_dev, ov7660_init[i].reg,
1302 ov7660_init[i].val);
1303 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001304 pr_err("OV7660 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001305 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001306 }
1307 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001308 sd->hstart = 3;
1309 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001310}
1311
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001312static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001313{
1314 int i;
1315 struct sd *sd = (struct sd *) gspca_dev;
1316
Jean-François Moine92884f82012-03-19 04:33:30 -03001317 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1318 msleep(200);
Brian Johnson26e744b2009-07-19 05:52:58 -03001319 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001320 i2c_w1(gspca_dev, ov7670_init[i].reg,
1321 ov7670_init[i].val);
1322 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001323 pr_err("OV7670 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001324 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001325 }
1326 }
1327 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001328 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001329 sd->hstart = 0;
1330 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001331}
1332
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001333static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001334{
1335 struct sd *sd = (struct sd *) gspca_dev;
1336 int i;
1337 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001338
1339 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001340 i2c_r2(gspca_dev, 0xff, &value);
1341 if (gspca_dev->usb_err >= 0
1342 && value == 0x8243) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001343 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001344 i2c_w2(gspca_dev, mt9v011_init[i].reg,
1345 mt9v011_init[i].val);
1346 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001347 pr_err("MT9V011 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001348 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001349 }
1350 }
1351 sd->hstart = 2;
1352 sd->vstart = 2;
1353 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001354 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001355 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001356 }
1357
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001358 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001359 sd->i2c_addr = 0x5c;
1360 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001361 i2c_r2(gspca_dev, 0xff, &value);
1362 if (gspca_dev->usb_err >= 0
1363 && value == 0x823a) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001364 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001365 i2c_w2(gspca_dev, mt9v111_init[i].reg,
1366 mt9v111_init[i].val);
1367 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001368 pr_err("MT9V111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001369 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001370 }
1371 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001372 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1373 | (1 << AUTOGAIN)
1374 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001375 sd->hstart = 2;
1376 sd->vstart = 2;
1377 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001378 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001379 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001380 }
1381
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001382 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001383 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001384 i2c_w2(gspca_dev, 0xf0, 0x0000);
1385 if (gspca_dev->usb_err < 0) {
1386 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001387 sd->i2c_addr = 0x48;
1388 i2c_w2(gspca_dev, 0xf0, 0x0000);
1389 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001390 i2c_r2(gspca_dev, 0x00, &value);
1391 if (gspca_dev->usb_err >= 0
1392 && value == 0x1229) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001393 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001394 i2c_w2(gspca_dev, mt9v112_init[i].reg,
1395 mt9v112_init[i].val);
1396 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001397 pr_err("MT9V112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001398 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001399 }
1400 }
1401 sd->hstart = 6;
1402 sd->vstart = 2;
1403 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001404 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001405 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001406 }
1407
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001408 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001409}
1410
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001411static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001412{
1413 struct sd *sd = (struct sd *) gspca_dev;
1414 int i;
1415 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001416 i2c_w2(gspca_dev, mt9m112_init[i].reg,
1417 mt9m112_init[i].val);
1418 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001419 pr_err("MT9M112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001420 return;
Brian Johnsone99ac542010-03-16 13:58:28 -03001421 }
1422 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001423 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1424 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001425 sd->hstart = 0;
1426 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001427}
1428
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001429static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001430{
1431 struct sd *sd = (struct sd *) gspca_dev;
1432 int i;
1433 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001434 i2c_w2(gspca_dev, mt9m111_init[i].reg,
1435 mt9m111_init[i].val);
1436 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001437 pr_err("MT9M111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001438 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001439 }
1440 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001441 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1442 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001443 sd->hstart = 0;
1444 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001445}
1446
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001447static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001448{
1449 struct sd *sd = (struct sd *) gspca_dev;
1450 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001451 u16 id;
1452
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001453 i2c_r2(gspca_dev, 0x00, &id);
1454 if (gspca_dev->usb_err < 0)
1455 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001456
1457 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1458 switch (id) {
1459 case 0x8411:
1460 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001461 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001462 break;
1463 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001464 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001465 break;
1466 default:
Joe Perches91f58422011-08-21 19:56:55 -03001467 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001468 gspca_dev->usb_err = -ENODEV;
1469 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001470 }
1471
Brian Johnson26e744b2009-07-19 05:52:58 -03001472 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001473 i2c_w2(gspca_dev, mt9m001_init[i].reg,
1474 mt9m001_init[i].val);
1475 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001476 pr_err("MT9M001 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001477 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001478 }
1479 }
1480 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001481 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001482 sd->hstart = 1;
1483 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001484}
1485
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001486static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001487{
1488 int i;
1489 struct sd *sd = (struct sd *) gspca_dev;
1490
1491 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001492 i2c_w1(gspca_dev, hv7131r_init[i].reg,
1493 hv7131r_init[i].val);
1494 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001495 pr_err("HV7131R Sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001496 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001497 }
1498 }
1499 sd->hstart = 0;
1500 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501}
1502
Jean-François Moinec5224d82012-03-19 04:30:07 -03001503static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001504{
1505 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001506 int satur;
1507 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001508 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001509
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001510 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001511 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001512 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1513 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001514 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001515
Jean-François Moinec5224d82012-03-19 04:30:07 -03001516 satur = sd->ctrls[SATURATION].val;
1517 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001518 cmatrix[6] = hue_coord;
1519 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001520
Jean-François Moinec5224d82012-03-19 04:30:07 -03001521 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001522 cmatrix[8] = hue_coord;
1523 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001524
Jean-François Moinec5224d82012-03-19 04:30:07 -03001525 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001526 cmatrix[10] = hue_coord;
1527 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001528
Jean-François Moinec5224d82012-03-19 04:30:07 -03001529 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001530 cmatrix[12] = hue_coord;
1531 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001532
Jean-François Moinec5224d82012-03-19 04:30:07 -03001533 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001534 cmatrix[14] = hue_coord;
1535 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001536
Jean-François Moinec5224d82012-03-19 04:30:07 -03001537 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001538 cmatrix[16] = hue_coord;
1539 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001540
Jean-François Moinec5224d82012-03-19 04:30:07 -03001541 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001542}
1543
Jean-François Moinec5224d82012-03-19 04:30:07 -03001544static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001545{
1546 struct sd *sd = (struct sd *) gspca_dev;
1547 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001548 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001549
1550 gamma[0] = 0x0a;
1551 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1552 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1553 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1554 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1555 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1556 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1557 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1558 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1559 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1560 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1561 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1562 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1563 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1564 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1565 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1566 gamma[16] = 0xf5;
1567
Jean-François Moinec5224d82012-03-19 04:30:07 -03001568 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001569}
1570
Jean-François Moinec5224d82012-03-19 04:30:07 -03001571static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001572{
1573 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001574
1575 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1576 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001577}
1578
Jean-François Moinec5224d82012-03-19 04:30:07 -03001579static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001580{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001581 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001582 u16 value2;
1583 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001584
1585 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001586 hflip = !sd->ctrls[HFLIP].val;
1587 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001588 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001589 hflip = sd->ctrls[HFLIP].val;
1590 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001591 }
1592
Brian Johnson26e744b2009-07-19 05:52:58 -03001593 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001594 case SENSOR_OV7660:
1595 value = 0x01;
1596 if (hflip)
1597 value |= 0x20;
1598 if (vflip) {
1599 value |= 0x10;
1600 sd->vstart = 2;
1601 } else
1602 sd->vstart = 3;
1603 reg_w1(gspca_dev, 0x1182, sd->vstart);
1604 i2c_w1(gspca_dev, 0x1e, value);
1605 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001606 case SENSOR_OV9650:
1607 i2c_r1(gspca_dev, 0x1e, &value);
1608 value &= ~0x30;
1609 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001610 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001611 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001612 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001613 value |= 0x10;
1614 tslb = 0x49;
1615 }
1616 i2c_w1(gspca_dev, 0x1e, value);
1617 i2c_w1(gspca_dev, 0x3a, tslb);
1618 break;
1619 case SENSOR_MT9V111:
1620 case SENSOR_MT9V011:
1621 i2c_r2(gspca_dev, 0x20, &value2);
1622 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001623 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001624 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001625 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001626 value2 |= 0x4020;
1627 i2c_w2(gspca_dev, 0x20, value2);
1628 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001629 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001630 case SENSOR_MT9M111:
1631 case SENSOR_MT9V112:
1632 i2c_r2(gspca_dev, 0x20, &value2);
1633 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001634 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001635 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001636 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001637 value2 |= 0x0001;
1638 i2c_w2(gspca_dev, 0x20, value2);
1639 break;
1640 case SENSOR_HV7131R:
1641 i2c_r1(gspca_dev, 0x01, &value);
1642 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001643 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001644 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001645 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001646 value |= 0x02;
1647 i2c_w1(gspca_dev, 0x01, value);
1648 break;
1649 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001650}
1651
Jean-François Moinec5224d82012-03-19 04:30:07 -03001652static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001653{
1654 struct sd *sd = (struct sd *) gspca_dev;
1655 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001656 int expo;
1657
1658 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001659 switch (sd->sensor) {
1660 case SENSOR_OV7660:
1661 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001662 case SENSOR_OV9655:
1663 case SENSOR_OV9650:
1664 exp[0] |= (3 << 4);
1665 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001666 exp[3] = expo;
1667 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001668 break;
1669 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001670 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001671 case SENSOR_MT9V011:
1672 exp[0] |= (3 << 4);
1673 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001674 exp[3] = expo >> 8;
1675 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001676 break;
1677 case SENSOR_HV7131R:
1678 exp[0] |= (4 << 4);
1679 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001680 exp[3] = expo >> 5;
1681 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001682 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001683 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001684 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001685 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001686 }
1687 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001688}
1689
Jean-François Moinec5224d82012-03-19 04:30:07 -03001690static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001691{
1692 struct sd *sd = (struct sd *) gspca_dev;
1693 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001694 int g;
1695
1696 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001697 switch (sd->sensor) {
1698 case SENSOR_OV7660:
1699 case SENSOR_OV7670:
1700 case SENSOR_SOI968:
1701 case SENSOR_OV9655:
1702 case SENSOR_OV9650:
1703 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001704 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001705 break;
1706 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001707 gain[0] |= (3 << 4);
1708 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001709 gain[3] = micron1_gain[g] >> 8;
1710 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001711 break;
1712 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001713 gain[0] |= (3 << 4);
1714 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001715 gain[3] = micron1_gain[g] >> 8;
1716 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001717 break;
1718 case SENSOR_MT9M001:
1719 gain[0] |= (3 << 4);
1720 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001721 gain[3] = micron2_gain[g] >> 8;
1722 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001723 break;
1724 case SENSOR_HV7131R:
1725 gain[0] |= (2 << 4);
1726 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001727 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001728 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001729 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001730 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001731 }
1732 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001733}
1734
1735#ifdef CONFIG_VIDEO_ADV_DEBUG
1736static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1737 struct v4l2_dbg_register *reg)
1738{
1739 struct sd *sd = (struct sd *) gspca_dev;
1740 switch (reg->match.type) {
1741 case V4L2_CHIP_MATCH_HOST:
1742 if (reg->match.addr != 0)
1743 return -EINVAL;
1744 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1745 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001746 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001747 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001748 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001749 case V4L2_CHIP_MATCH_I2C_ADDR:
1750 if (reg->match.addr != sd->i2c_addr)
1751 return -EINVAL;
1752 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001753 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001754 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001755 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001756 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001757 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001758 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001759 }
1760 return -EINVAL;
1761}
1762
1763static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1764 struct v4l2_dbg_register *reg)
1765{
1766 struct sd *sd = (struct sd *) gspca_dev;
1767 switch (reg->match.type) {
1768 case V4L2_CHIP_MATCH_HOST:
1769 if (reg->match.addr != 0)
1770 return -EINVAL;
1771 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1772 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001773 reg_w1(gspca_dev, reg->reg, reg->val);
1774 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001775 case V4L2_CHIP_MATCH_I2C_ADDR:
1776 if (reg->match.addr != sd->i2c_addr)
1777 return -EINVAL;
1778 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001779 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001780 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001781 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001782 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001783 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001784 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001785 }
1786 return -EINVAL;
1787}
1788#endif
1789
1790static int sd_chip_ident(struct gspca_dev *gspca_dev,
1791 struct v4l2_dbg_chip_ident *chip)
1792{
1793 struct sd *sd = (struct sd *) gspca_dev;
1794
1795 switch (chip->match.type) {
1796 case V4L2_CHIP_MATCH_HOST:
1797 if (chip->match.addr != 0)
1798 return -EINVAL;
1799 chip->revision = 0;
1800 chip->ident = V4L2_IDENT_SN9C20X;
1801 return 0;
1802 case V4L2_CHIP_MATCH_I2C_ADDR:
1803 if (chip->match.addr != sd->i2c_addr)
1804 return -EINVAL;
1805 chip->revision = 0;
1806 chip->ident = i2c_ident[sd->sensor];
1807 return 0;
1808 }
1809 return -EINVAL;
1810}
1811
1812static int sd_config(struct gspca_dev *gspca_dev,
1813 const struct usb_device_id *id)
1814{
1815 struct sd *sd = (struct sd *) gspca_dev;
1816 struct cam *cam;
1817
1818 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001819 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001820
1821 sd->sensor = (id->driver_info >> 8) & 0xff;
1822 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001823 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001824
1825 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001826 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001827 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001828 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001829 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001830 cam->cam_mode = sxga_mode;
1831 cam->nmodes = ARRAY_SIZE(sxga_mode);
1832 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001833 case SENSOR_MT9M001:
1834 cam->cam_mode = mono_mode;
1835 cam->nmodes = ARRAY_SIZE(mono_mode);
1836 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001837 default:
1838 cam->cam_mode = vga_mode;
1839 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001840 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001841 }
1842
1843 sd->old_step = 0;
1844 sd->older_step = 0;
1845 sd->exposure_step = 16;
1846
Jean-François Moinec5224d82012-03-19 04:30:07 -03001847 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001848
1849 sd->quality = 95;
1850
Brian Johnson26e744b2009-07-19 05:52:58 -03001851 return 0;
1852}
1853
1854static int sd_init(struct gspca_dev *gspca_dev)
1855{
1856 struct sd *sd = (struct sd *) gspca_dev;
1857 int i;
1858 u8 value;
1859 u8 i2c_init[9] =
1860 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1861
1862 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1863 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001864 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1865 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001866 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001867 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001868 }
1869 }
1870
Brian Johnson0c045eb2010-03-16 13:58:27 -03001871 if (sd->flags & LED_REVERSE)
1872 reg_w1(gspca_dev, 0x1006, 0x00);
1873 else
1874 reg_w1(gspca_dev, 0x1006, 0x20);
1875
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001876 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1877 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001878 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001879 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001880 }
1881
1882 switch (sd->sensor) {
1883 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001884 ov9650_init_sensor(gspca_dev);
1885 if (gspca_dev->usb_err < 0)
1886 break;
Joe Perches91f58422011-08-21 19:56:55 -03001887 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001888 break;
1889 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001890 ov9655_init_sensor(gspca_dev);
1891 if (gspca_dev->usb_err < 0)
1892 break;
Joe Perches91f58422011-08-21 19:56:55 -03001893 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001894 break;
1895 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001896 soi968_init_sensor(gspca_dev);
1897 if (gspca_dev->usb_err < 0)
1898 break;
Joe Perches91f58422011-08-21 19:56:55 -03001899 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001900 break;
1901 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001902 ov7660_init_sensor(gspca_dev);
1903 if (gspca_dev->usb_err < 0)
1904 break;
Joe Perches91f58422011-08-21 19:56:55 -03001905 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001906 break;
1907 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001908 ov7670_init_sensor(gspca_dev);
1909 if (gspca_dev->usb_err < 0)
1910 break;
Joe Perches91f58422011-08-21 19:56:55 -03001911 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001912 break;
1913 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001914 mt9v_init_sensor(gspca_dev);
1915 if (gspca_dev->usb_err < 0)
1916 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001917 break;
1918 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001919 mt9m111_init_sensor(gspca_dev);
1920 if (gspca_dev->usb_err < 0)
1921 break;
Joe Perches91f58422011-08-21 19:56:55 -03001922 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001923 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001924 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001925 mt9m112_init_sensor(gspca_dev);
1926 if (gspca_dev->usb_err < 0)
1927 break;
Joe Perches91f58422011-08-21 19:56:55 -03001928 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001929 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001930 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001931 mt9m001_init_sensor(gspca_dev);
1932 if (gspca_dev->usb_err < 0)
1933 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001934 break;
1935 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001936 hv7131r_init_sensor(gspca_dev);
1937 if (gspca_dev->usb_err < 0)
1938 break;
Joe Perches91f58422011-08-21 19:56:55 -03001939 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001940 break;
1941 default:
Joe Perches91f58422011-08-21 19:56:55 -03001942 pr_info("Unsupported Sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001943 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001944 }
1945
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001946 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001947}
1948
1949static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1950{
1951 struct sd *sd = (struct sd *) gspca_dev;
1952 u8 value;
1953 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001954 case SENSOR_SOI968:
1955 if (mode & MODE_SXGA) {
1956 i2c_w1(gspca_dev, 0x17, 0x1d);
1957 i2c_w1(gspca_dev, 0x18, 0xbd);
1958 i2c_w1(gspca_dev, 0x19, 0x01);
1959 i2c_w1(gspca_dev, 0x1a, 0x81);
1960 i2c_w1(gspca_dev, 0x12, 0x00);
1961 sd->hstart = 140;
1962 sd->vstart = 19;
1963 } else {
1964 i2c_w1(gspca_dev, 0x17, 0x13);
1965 i2c_w1(gspca_dev, 0x18, 0x63);
1966 i2c_w1(gspca_dev, 0x19, 0x01);
1967 i2c_w1(gspca_dev, 0x1a, 0x79);
1968 i2c_w1(gspca_dev, 0x12, 0x40);
1969 sd->hstart = 60;
1970 sd->vstart = 11;
1971 }
1972 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001973 case SENSOR_OV9650:
1974 if (mode & MODE_SXGA) {
1975 i2c_w1(gspca_dev, 0x17, 0x1b);
1976 i2c_w1(gspca_dev, 0x18, 0xbc);
1977 i2c_w1(gspca_dev, 0x19, 0x01);
1978 i2c_w1(gspca_dev, 0x1a, 0x82);
1979 i2c_r1(gspca_dev, 0x12, &value);
1980 i2c_w1(gspca_dev, 0x12, value & 0x07);
1981 } else {
1982 i2c_w1(gspca_dev, 0x17, 0x24);
1983 i2c_w1(gspca_dev, 0x18, 0xc5);
1984 i2c_w1(gspca_dev, 0x19, 0x00);
1985 i2c_w1(gspca_dev, 0x1a, 0x3c);
1986 i2c_r1(gspca_dev, 0x12, &value);
1987 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1988 }
1989 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001990 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001991 case SENSOR_MT9M111:
1992 if (mode & MODE_SXGA) {
1993 i2c_w2(gspca_dev, 0xf0, 0x0002);
1994 i2c_w2(gspca_dev, 0xc8, 0x970b);
1995 i2c_w2(gspca_dev, 0xf0, 0x0000);
1996 } else {
1997 i2c_w2(gspca_dev, 0xf0, 0x0002);
1998 i2c_w2(gspca_dev, 0xc8, 0x8000);
1999 i2c_w2(gspca_dev, 0xf0, 0x0000);
2000 }
2001 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002002 }
2003}
2004
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002005static int sd_isoc_init(struct gspca_dev *gspca_dev)
2006{
2007 struct usb_interface *intf;
2008 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
2009
2010 /*
2011 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2012 * than our regular bandwidth calculations reserve, so we force the
2013 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2014 */
2015 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2016 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2017
2018 if (intf->num_altsetting != 9) {
2019 pr_warn("sn9c20x camera with unknown number of alt "
2020 "settings (%d), please report!\n",
2021 intf->num_altsetting);
2022 gspca_dev->alt = intf->num_altsetting;
2023 return 0;
2024 }
2025
2026 switch (gspca_dev->width) {
2027 case 160: /* 160x120 */
2028 gspca_dev->alt = 2;
2029 break;
2030 case 320: /* 320x240 */
2031 gspca_dev->alt = 6;
2032 break;
2033 default: /* >= 640x480 */
2034 gspca_dev->alt = 9;
2035 }
2036 }
2037
2038 return 0;
2039}
2040
Brian Johnson26e744b2009-07-19 05:52:58 -03002041#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002042((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002043(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2044(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2045
2046#define CLR_WIN(width, height) \
2047((const u8 [])\
2048{0, width >> 2, 0, height >> 1,\
2049((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2050
2051static int sd_start(struct gspca_dev *gspca_dev)
2052{
2053 struct sd *sd = (struct sd *) gspca_dev;
2054 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2055 int width = gspca_dev->width;
2056 int height = gspca_dev->height;
2057 u8 fmt, scale = 0;
2058
Brian Johnson26e744b2009-07-19 05:52:58 -03002059 jpeg_define(sd->jpeg_hdr, height, width,
2060 0x21);
2061 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2062
2063 if (mode & MODE_RAW)
2064 fmt = 0x2d;
2065 else if (mode & MODE_JPEG)
2066 fmt = 0x2c;
2067 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002068 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002069
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002070 switch (mode & SCALE_MASK) {
2071 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002072 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002073 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002074 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002075 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002076 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002077 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002078 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002079 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002080 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002081 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002082 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002083 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002084 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002085 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002086 break;
2087 }
2088
2089 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002090 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2091 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002092 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2093 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2094 reg_w1(gspca_dev, 0x1189, scale);
2095 reg_w1(gspca_dev, 0x10e0, fmt);
2096
2097 set_cmatrix(gspca_dev);
2098 set_gamma(gspca_dev);
2099 set_redblue(gspca_dev);
2100 set_gain(gspca_dev);
2101 set_exposure(gspca_dev);
2102 set_hvflip(gspca_dev);
2103
Brian Johnson0c045eb2010-03-16 13:58:27 -03002104 reg_w1(gspca_dev, 0x1007, 0x20);
2105
Brian Johnson26e744b2009-07-19 05:52:58 -03002106 reg_r(gspca_dev, 0x1061, 1);
2107 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002108 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002109}
2110
2111static void sd_stopN(struct gspca_dev *gspca_dev)
2112{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002113 reg_w1(gspca_dev, 0x1007, 0x00);
2114
Brian Johnson26e744b2009-07-19 05:52:58 -03002115 reg_r(gspca_dev, 0x1061, 1);
2116 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2117}
2118
Brian Johnsone1430472009-09-02 12:39:41 -03002119static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002120{
2121 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002122 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002123
2124 /*
2125 * some hardcoded values are present
2126 * like those for maximal/minimal exposure
2127 * and exposure steps
2128 */
2129 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002130 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002131 return;
2132
Jean-François Moinec5224d82012-03-19 04:30:07 -03002133 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002134 if (new_exp > 0x1770)
2135 new_exp = 0x1770;
2136 if (new_exp < 0x10)
2137 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002138 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002139 set_exposure(gspca_dev);
2140
2141 sd->older_step = sd->old_step;
2142 sd->old_step = 1;
2143
2144 if (sd->old_step ^ sd->older_step)
2145 sd->exposure_step /= 2;
2146 else
2147 sd->exposure_step += 2;
2148 }
2149 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002150 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002151 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002152 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002153 if (new_exp > 0x1700)
2154 new_exp = 0x1770;
2155 if (new_exp < 0x10)
2156 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002157 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002158 set_exposure(gspca_dev);
2159 sd->older_step = sd->old_step;
2160 sd->old_step = 0;
2161
2162 if (sd->old_step ^ sd->older_step)
2163 sd->exposure_step /= 2;
2164 else
2165 sd->exposure_step += 2;
2166 }
2167}
2168
Brian Johnsone1430472009-09-02 12:39:41 -03002169static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2170{
2171 struct sd *sd = (struct sd *) gspca_dev;
2172
2173 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002174 if (sd->ctrls[GAIN].val + 1 <= 28) {
2175 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002176 set_gain(gspca_dev);
2177 }
2178 }
2179 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002180 if (sd->ctrls[GAIN].val > 0) {
2181 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002182 set_gain(gspca_dev);
2183 }
2184 }
2185}
2186
2187static void sd_dqcallback(struct gspca_dev *gspca_dev)
2188{
2189 struct sd *sd = (struct sd *) gspca_dev;
2190 int avg_lum;
2191
Jean-François Moinec5224d82012-03-19 04:30:07 -03002192 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002193 return;
2194
2195 avg_lum = atomic_read(&sd->avg_lum);
2196 if (sd->sensor == SENSOR_SOI968)
2197 do_autogain(gspca_dev, avg_lum);
2198 else
2199 do_autoexposure(gspca_dev, avg_lum);
2200}
2201
Jean-François Moine28566432010-10-01 07:33:26 -03002202#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002203static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2204 u8 *data, /* interrupt packet */
2205 int len) /* interrupt packet length */
2206{
2207 struct sd *sd = (struct sd *) gspca_dev;
2208 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002209 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002210 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2211 input_sync(gspca_dev->input_dev);
2212 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2213 input_sync(gspca_dev->input_dev);
2214 ret = 0;
2215 }
2216 return ret;
2217}
2218#endif
2219
Brian Johnson26e744b2009-07-19 05:52:58 -03002220static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002221 u8 *data, /* isoc packet */
2222 int len) /* iso packet length */
2223{
2224 struct sd *sd = (struct sd *) gspca_dev;
2225 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002226 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002227 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002228 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002229 avg_lum = ((data[35] >> 2) & 3) |
2230 (data[20] << 2) |
2231 (data[19] << 10);
2232 avg_lum += ((data[35] >> 4) & 3) |
2233 (data[22] << 2) |
2234 (data[21] << 10);
2235 avg_lum += ((data[35] >> 6) & 3) |
2236 (data[24] << 2) |
2237 (data[23] << 10);
2238 avg_lum += (data[36] & 3) |
2239 (data[26] << 2) |
2240 (data[25] << 10);
2241 avg_lum += ((data[36] >> 2) & 3) |
2242 (data[28] << 2) |
2243 (data[27] << 10);
2244 avg_lum += ((data[36] >> 4) & 3) |
2245 (data[30] << 2) |
2246 (data[29] << 10);
2247 avg_lum += ((data[36] >> 6) & 3) |
2248 (data[32] << 2) |
2249 (data[31] << 10);
2250 avg_lum += ((data[44] >> 4) & 3) |
2251 (data[34] << 2) |
2252 (data[33] << 10);
2253 avg_lum >>= 9;
2254 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002255 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002256 len -= 64;
2257 if (len == 0)
2258 return;
2259 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002260 }
2261 if (gspca_dev->last_packet_type == LAST_PACKET) {
2262 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2263 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002264 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002265 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002266 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002267 data, len);
2268 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002269 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002270 data, len);
2271 }
2272 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002273 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002274 }
2275}
2276
2277/* sub-driver description */
2278static const struct sd_desc sd_desc = {
2279 .name = MODULE_NAME,
2280 .ctrls = sd_ctrls,
2281 .nctrls = ARRAY_SIZE(sd_ctrls),
2282 .config = sd_config,
2283 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002284 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002285 .start = sd_start,
2286 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002287 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002288#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002289 .int_pkt_scan = sd_int_pkt_scan,
2290#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002291 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002292#ifdef CONFIG_VIDEO_ADV_DEBUG
2293 .set_register = sd_dbg_s_register,
2294 .get_register = sd_dbg_g_register,
2295#endif
2296 .get_chip_ident = sd_chip_ident,
2297};
2298
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002299#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002300 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002301 | (SENSOR_ ## sensor << 8) \
2302 | (i2c_addr)
2303
Jean-François Moine95c967c2011-01-13 05:20:29 -03002304static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002305 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2306 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2307 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002308 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002309 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2310 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2311 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002312 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2313 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2314 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2315 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002316 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002317 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2318 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2319 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2320 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002321 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002322 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002323 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2324 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2325 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2326 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002327 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002328 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002329 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2330 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2331 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2332 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002333 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2334 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002335 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2336 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2337 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2338 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002339 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002340 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2341 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2342 {}
2343};
2344MODULE_DEVICE_TABLE(usb, device_table);
2345
2346/* -- device connect -- */
2347static int sd_probe(struct usb_interface *intf,
2348 const struct usb_device_id *id)
2349{
2350 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2351 THIS_MODULE);
2352}
2353
Brian Johnson26e744b2009-07-19 05:52:58 -03002354static struct usb_driver sd_driver = {
2355 .name = MODULE_NAME,
2356 .id_table = device_table,
2357 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002358 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002359#ifdef CONFIG_PM
2360 .suspend = gspca_suspend,
2361 .resume = gspca_resume,
2362 .reset_resume = gspca_resume,
2363#endif
2364};
2365
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002366module_usb_driver(sd_driver);