blob: 15c371e4f8d6888ecd9c72832cc2e1c7b2a2c06d [file] [log] [blame]
Brian Johnson26e744b2009-07-19 05:52:58 -03001/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Joe Perches91f58422011-08-21 19:56:55 -030021#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
Brian Johnson26e744b2009-07-19 05:52:58 -030023#include <linux/input.h>
Brian Johnson26e744b2009-07-19 05:52:58 -030024
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030025#include "gspca.h"
26#include "jpeg.h"
27
28#include <media/v4l2-chip-ident.h>
Brian Johnson7ddaac72010-03-16 13:58:27 -030029#include <linux/dmi.h>
Mauro Carvalho Chehabc15b95e2009-07-19 18:03:23 -030030
Brian Johnson26e744b2009-07-19 05:52:58 -030031MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
32 "microdia project <microdia@googlegroups.com>");
33MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
34MODULE_LICENSE("GPL");
35
36#define MODULE_NAME "sn9c20x"
37
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -030038/*
39 * Pixel format private data
40 */
41#define SCALE_MASK 0x0f
42#define SCALE_160x120 0
43#define SCALE_320x240 1
44#define SCALE_640x480 2
45#define SCALE_1280x1024 3
Brian Johnson26e744b2009-07-19 05:52:58 -030046#define MODE_RAW 0x10
47#define MODE_JPEG 0x20
48#define MODE_SXGA 0x80
49
50#define SENSOR_OV9650 0
51#define SENSOR_OV9655 1
52#define SENSOR_SOI968 2
53#define SENSOR_OV7660 3
54#define SENSOR_OV7670 4
55#define SENSOR_MT9V011 5
56#define SENSOR_MT9V111 6
57#define SENSOR_MT9V112 7
58#define SENSOR_MT9M001 8
59#define SENSOR_MT9M111 9
Brian Johnsone99ac542010-03-16 13:58:28 -030060#define SENSOR_MT9M112 10
61#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030062#define SENSOR_MT9VPRB 20
63
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030064/* camera flags */
Brian Johnson33ddc162010-04-18 21:42:40 -030065#define HAS_NO_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030066#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030067#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030068
Jean-François Moinec5224d82012-03-19 04:30:07 -030069enum e_ctrl {
70 BRIGHTNESS,
71 CONTRAST,
72 SATURATION,
73 HUE,
74 GAMMA,
75 BLUE,
76 RED,
77 VFLIP,
78 HFLIP,
79 EXPOSURE,
80 GAIN,
81 AUTOGAIN,
82 NCTRLS /* number of controls */
83};
84
Brian Johnson26e744b2009-07-19 05:52:58 -030085/* specific webcam descriptor */
86struct sd {
87 struct gspca_dev gspca_dev;
88
Jean-François Moinec5224d82012-03-19 04:30:07 -030089 struct gspca_ctrl ctrls[NCTRLS];
90
Brian Johnson26e744b2009-07-19 05:52:58 -030091#define MIN_AVG_LUM 80
92#define MAX_AVG_LUM 130
93 atomic_t avg_lum;
94 u8 old_step;
95 u8 older_step;
96 u8 exposure_step;
97
Brian Johnson26e744b2009-07-19 05:52:58 -030098 u8 i2c_addr;
99 u8 sensor;
100 u8 hstart;
101 u8 vstart;
102
Jean-François Moine9a731a32010-06-04 05:26:42 -0300103 u8 jpeg_hdr[JPEG_HDR_SZ];
Brian Johnson26e744b2009-07-19 05:52:58 -0300104 u8 quality;
105
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -0300106 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -0300107};
108
Joe Perches58aa68c2009-09-02 01:12:13 -0300109struct i2c_reg_u8 {
110 u8 reg;
111 u8 val;
112};
113
114struct i2c_reg_u16 {
115 u8 reg;
116 u16 val;
117};
118
Brian Johnson7ddaac72010-03-16 13:58:27 -0300119static const struct dmi_system_id flip_dmi_table[] = {
120 {
121 .ident = "MSI MS-1034",
122 .matches = {
123 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
124 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
125 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
126 }
127 },
128 {
129 .ident = "MSI MS-1632",
130 .matches = {
131 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
132 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
133 }
134 },
Brian Johnsone077f862010-04-05 20:52:52 -0300135 {
Hans de Goedebcc6f662011-02-17 06:27:57 -0300136 .ident = "MSI MS-1633X",
137 .matches = {
138 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
139 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
140 }
141 },
142 {
Brian Johnson5d26ed92010-04-10 02:12:46 -0300143 .ident = "MSI MS-1635X",
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
146 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
147 }
148 },
149 {
Brian Johnsone077f862010-04-05 20:52:52 -0300150 .ident = "ASUSTeK W7J",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
153 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
154 }
155 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300156 {}
157};
158
Jean-François Moinec5224d82012-03-19 04:30:07 -0300159static void set_cmatrix(struct gspca_dev *gspca_dev);
160static void set_gamma(struct gspca_dev *gspca_dev);
161static void set_redblue(struct gspca_dev *gspca_dev);
162static void set_hvflip(struct gspca_dev *gspca_dev);
163static void set_exposure(struct gspca_dev *gspca_dev);
164static void set_gain(struct gspca_dev *gspca_dev);
165
166static const struct ctrl sd_ctrls[NCTRLS] = {
167[BRIGHTNESS] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300168 {
169 .id = V4L2_CID_BRIGHTNESS,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "Brightness",
172 .minimum = 0,
173 .maximum = 0xff,
174 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300175 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300176 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300177 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300178 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300179[CONTRAST] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300180 {
181 .id = V4L2_CID_CONTRAST,
182 .type = V4L2_CTRL_TYPE_INTEGER,
183 .name = "Contrast",
184 .minimum = 0,
185 .maximum = 0xff,
186 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300187 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300188 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300189 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300190 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300191[SATURATION] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300192 {
193 .id = V4L2_CID_SATURATION,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Saturation",
196 .minimum = 0,
197 .maximum = 0xff,
198 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300199 .default_value = 0x7f
Brian Johnson26e744b2009-07-19 05:52:58 -0300200 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300201 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300202 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300203[HUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300204 {
205 .id = V4L2_CID_HUE,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Hue",
208 .minimum = -180,
209 .maximum = 180,
210 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300211 .default_value = 0
Brian Johnson26e744b2009-07-19 05:52:58 -0300212 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300213 .set_control = set_cmatrix
Brian Johnson26e744b2009-07-19 05:52:58 -0300214 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300215[GAMMA] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300216 {
217 .id = V4L2_CID_GAMMA,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 .name = "Gamma",
220 .minimum = 0,
221 .maximum = 0xff,
222 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300223 .default_value = 0x10
Brian Johnson26e744b2009-07-19 05:52:58 -0300224 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300225 .set_control = set_gamma
Brian Johnson26e744b2009-07-19 05:52:58 -0300226 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300227[BLUE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300228 {
229 .id = V4L2_CID_BLUE_BALANCE,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Blue Balance",
232 .minimum = 0,
233 .maximum = 0x7f,
234 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300235 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300236 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300237 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300238 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300239[RED] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300240 {
241 .id = V4L2_CID_RED_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Red Balance",
244 .minimum = 0,
245 .maximum = 0x7f,
246 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300247 .default_value = 0x28
Brian Johnson26e744b2009-07-19 05:52:58 -0300248 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300249 .set_control = set_redblue
Brian Johnson26e744b2009-07-19 05:52:58 -0300250 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300251[HFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300252 {
253 .id = V4L2_CID_HFLIP,
254 .type = V4L2_CTRL_TYPE_BOOLEAN,
255 .name = "Horizontal Flip",
256 .minimum = 0,
257 .maximum = 1,
258 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300259 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300260 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300261 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300262 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300263[VFLIP] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300264 {
265 .id = V4L2_CID_VFLIP,
266 .type = V4L2_CTRL_TYPE_BOOLEAN,
267 .name = "Vertical Flip",
268 .minimum = 0,
269 .maximum = 1,
270 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300271 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300272 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300273 .set_control = set_hvflip
Brian Johnson26e744b2009-07-19 05:52:58 -0300274 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300275[EXPOSURE] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300276 {
277 .id = V4L2_CID_EXPOSURE,
278 .type = V4L2_CTRL_TYPE_INTEGER,
279 .name = "Exposure",
280 .minimum = 0,
281 .maximum = 0x1780,
282 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300283 .default_value = 0x33,
Brian Johnson26e744b2009-07-19 05:52:58 -0300284 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300285 .set_control = set_exposure
Brian Johnson26e744b2009-07-19 05:52:58 -0300286 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300287[GAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300288 {
289 .id = V4L2_CID_GAIN,
290 .type = V4L2_CTRL_TYPE_INTEGER,
291 .name = "Gain",
292 .minimum = 0,
293 .maximum = 28,
294 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300295 .default_value = 0,
Brian Johnson26e744b2009-07-19 05:52:58 -0300296 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300297 .set_control = set_gain
Brian Johnson26e744b2009-07-19 05:52:58 -0300298 },
Jean-François Moinec5224d82012-03-19 04:30:07 -0300299[AUTOGAIN] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300300 {
301 .id = V4L2_CID_AUTOGAIN,
302 .type = V4L2_CTRL_TYPE_BOOLEAN,
303 .name = "Auto Exposure",
304 .minimum = 0,
305 .maximum = 1,
306 .step = 1,
Jean-François Moinec5224d82012-03-19 04:30:07 -0300307 .default_value = 1,
Brian Johnson26e744b2009-07-19 05:52:58 -0300308 },
Brian Johnson26e744b2009-07-19 05:52:58 -0300309 },
310};
311
312static const struct v4l2_pix_format vga_mode[] = {
313 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300314 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300315 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300316 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300317 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300318 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
319 .bytesperline = 160,
320 .sizeimage = 160 * 120,
321 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300322 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300323 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300324 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300325 .sizeimage = 240 * 120,
326 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300327 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300328 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300329 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300330 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300331 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300332 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300333 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
334 .bytesperline = 320,
335 .sizeimage = 320 * 240 ,
336 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300337 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300338 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300339 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300340 .sizeimage = 480 * 240 ,
341 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300342 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300343 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300344 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300345 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300346 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300347 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300348 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
349 .bytesperline = 640,
350 .sizeimage = 640 * 480,
351 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300352 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300353 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300354 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300355 .sizeimage = 960 * 480,
356 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300357 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300358};
359
360static const struct v4l2_pix_format sxga_mode[] = {
361 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300362 .bytesperline = 160,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300363 .sizeimage = 160 * 120 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300364 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300365 .priv = SCALE_160x120 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300366 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
367 .bytesperline = 160,
368 .sizeimage = 160 * 120,
369 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300370 .priv = SCALE_160x120 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300371 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300372 .bytesperline = 160,
Brian Johnson26e744b2009-07-19 05:52:58 -0300373 .sizeimage = 240 * 120,
374 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300375 .priv = SCALE_160x120},
Brian Johnson26e744b2009-07-19 05:52:58 -0300376 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300377 .bytesperline = 320,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300378 .sizeimage = 320 * 240 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300379 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300380 .priv = SCALE_320x240 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300381 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
382 .bytesperline = 320,
383 .sizeimage = 320 * 240 ,
384 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300385 .priv = SCALE_320x240 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300386 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300387 .bytesperline = 320,
Brian Johnson26e744b2009-07-19 05:52:58 -0300388 .sizeimage = 480 * 240 ,
389 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300390 .priv = SCALE_320x240},
Brian Johnson26e744b2009-07-19 05:52:58 -0300391 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300392 .bytesperline = 640,
Hans de Goede6899a9c2011-02-16 08:37:54 -0300393 .sizeimage = 640 * 480 * 4 / 8 + 590,
Brian Johnson26e744b2009-07-19 05:52:58 -0300394 .colorspace = V4L2_COLORSPACE_JPEG,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300395 .priv = SCALE_640x480 | MODE_JPEG},
Brian Johnson26e744b2009-07-19 05:52:58 -0300396 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
397 .bytesperline = 640,
398 .sizeimage = 640 * 480,
399 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300400 .priv = SCALE_640x480 | MODE_RAW},
Brian Johnson26e744b2009-07-19 05:52:58 -0300401 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
Jean-François Moineb1e46652010-09-13 05:25:41 -0300402 .bytesperline = 640,
Brian Johnson26e744b2009-07-19 05:52:58 -0300403 .sizeimage = 960 * 480,
404 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300405 .priv = SCALE_640x480},
Brian Johnson26e744b2009-07-19 05:52:58 -0300406 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
407 .bytesperline = 1280,
Jean-François Moine9b1d3ca2010-09-13 05:26:35 -0300408 .sizeimage = 1280 * 1024,
Brian Johnson26e744b2009-07-19 05:52:58 -0300409 .colorspace = V4L2_COLORSPACE_SRGB,
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -0300410 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
Brian Johnson26e744b2009-07-19 05:52:58 -0300411};
412
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -0300413static const struct v4l2_pix_format mono_mode[] = {
414 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
415 .bytesperline = 160,
416 .sizeimage = 160 * 120,
417 .colorspace = V4L2_COLORSPACE_SRGB,
418 .priv = SCALE_160x120 | MODE_RAW},
419 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
420 .bytesperline = 320,
421 .sizeimage = 320 * 240 ,
422 .colorspace = V4L2_COLORSPACE_SRGB,
423 .priv = SCALE_320x240 | MODE_RAW},
424 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
425 .bytesperline = 640,
426 .sizeimage = 640 * 480,
427 .colorspace = V4L2_COLORSPACE_SRGB,
428 .priv = SCALE_640x480 | MODE_RAW},
429 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
430 .bytesperline = 1280,
431 .sizeimage = 1280 * 1024,
432 .colorspace = V4L2_COLORSPACE_SRGB,
433 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
434};
435
Joe Perches58aa68c2009-09-02 01:12:13 -0300436static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300437 41, 44, 46, 48, 50, 52, 54, 56,
438 58, 60, 62, 64, 66, 68, 70, 72,
439 74, 76, 78, 80, 81, 83, 85, 87,
440 88, 90, 92, 93, 95, 97, 98, 100,
441 101, 102, 104, 105, 107, 108, 109, 110,
442 112, 113, 114, 115, 116, 117, 118, 119,
443 120, 121, 122, 123, 123, 124, 125, 125,
444 126, 127, 127, 128, 128, 129, 129, 129,
445 130, 130, 130, 130, 131, 131, 131, 131,
446 131, 131, 131, 131, 130, 130, 130, 130,
447 129, 129, 129, 128, 128, 127, 127, 126,
448 125, 125, 124, 123, 122, 122, 121, 120,
449 119, 118, 117, 116, 115, 114, 112, 111,
450 110, 109, 107, 106, 105, 103, 102, 101,
451 99, 98, 96, 94, 93, 91, 90, 88,
452 86, 84, 83, 81, 79, 77, 75, 74,
453 72, 70, 68, 66, 64, 62, 60, 58,
454 56, 54, 52, 49, 47, 45, 43, 41,
455 39, 36, 34, 32, 30, 28, 25, 23,
456 21, 19, 16, 14, 12, 9, 7, 5,
457 3, 0, -1, -3, -6, -8, -10, -12,
458 -15, -17, -19, -22, -24, -26, -28, -30,
459 -33, -35, -37, -39, -41, -44, -46, -48,
460 -50, -52, -54, -56, -58, -60, -62, -64,
461 -66, -68, -70, -72, -74, -76, -78, -80,
462 -81, -83, -85, -87, -88, -90, -92, -93,
463 -95, -97, -98, -100, -101, -102, -104, -105,
464 -107, -108, -109, -110, -112, -113, -114, -115,
465 -116, -117, -118, -119, -120, -121, -122, -123,
466 -123, -124, -125, -125, -126, -127, -127, -128,
467 -128, -128, -128, -128, -128, -128, -128, -128,
468 -128, -128, -128, -128, -128, -128, -128, -128,
469 -128, -128, -128, -128, -128, -128, -128, -128,
470 -128, -127, -127, -126, -125, -125, -124, -123,
471 -122, -122, -121, -120, -119, -118, -117, -116,
472 -115, -114, -112, -111, -110, -109, -107, -106,
473 -105, -103, -102, -101, -99, -98, -96, -94,
474 -93, -91, -90, -88, -86, -84, -83, -81,
475 -79, -77, -75, -74, -72, -70, -68, -66,
476 -64, -62, -60, -58, -56, -54, -52, -49,
477 -47, -45, -43, -41, -39, -36, -34, -32,
478 -30, -28, -25, -23, -21, -19, -16, -14,
479 -12, -9, -7, -5, -3, 0, 1, 3,
480 6, 8, 10, 12, 15, 17, 19, 22,
481 24, 26, 28, 30, 33, 35, 37, 39, 41
482};
483
Joe Perches58aa68c2009-09-02 01:12:13 -0300484static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300485 82, 80, 78, 76, 74, 73, 71, 69,
486 67, 65, 63, 61, 58, 56, 54, 52,
487 50, 48, 46, 44, 41, 39, 37, 35,
488 32, 30, 28, 26, 23, 21, 19, 16,
489 14, 12, 10, 7, 5, 3, 0, -1,
490 -3, -6, -8, -10, -13, -15, -17, -19,
491 -22, -24, -26, -29, -31, -33, -35, -38,
492 -40, -42, -44, -46, -48, -51, -53, -55,
493 -57, -59, -61, -63, -65, -67, -69, -71,
494 -73, -75, -77, -79, -81, -82, -84, -86,
495 -88, -89, -91, -93, -94, -96, -98, -99,
496 -101, -102, -104, -105, -106, -108, -109, -110,
497 -112, -113, -114, -115, -116, -117, -119, -120,
498 -120, -121, -122, -123, -124, -125, -126, -126,
499 -127, -128, -128, -128, -128, -128, -128, -128,
500 -128, -128, -128, -128, -128, -128, -128, -128,
501 -128, -128, -128, -128, -128, -128, -128, -128,
502 -128, -128, -128, -128, -128, -128, -128, -128,
503 -127, -127, -126, -125, -125, -124, -123, -122,
504 -121, -120, -119, -118, -117, -116, -115, -114,
505 -113, -111, -110, -109, -107, -106, -105, -103,
506 -102, -100, -99, -97, -96, -94, -92, -91,
507 -89, -87, -85, -84, -82, -80, -78, -76,
508 -74, -73, -71, -69, -67, -65, -63, -61,
509 -58, -56, -54, -52, -50, -48, -46, -44,
510 -41, -39, -37, -35, -32, -30, -28, -26,
511 -23, -21, -19, -16, -14, -12, -10, -7,
512 -5, -3, 0, 1, 3, 6, 8, 10,
513 13, 15, 17, 19, 22, 24, 26, 29,
514 31, 33, 35, 38, 40, 42, 44, 46,
515 48, 51, 53, 55, 57, 59, 61, 63,
516 65, 67, 69, 71, 73, 75, 77, 79,
517 81, 82, 84, 86, 88, 89, 91, 93,
518 94, 96, 98, 99, 101, 102, 104, 105,
519 106, 108, 109, 110, 112, 113, 114, 115,
520 116, 117, 119, 120, 120, 121, 122, 123,
521 124, 125, 126, 126, 127, 128, 128, 129,
522 129, 130, 130, 131, 131, 131, 131, 132,
523 132, 132, 132, 132, 132, 132, 132, 132,
524 132, 132, 132, 131, 131, 131, 130, 130,
525 130, 129, 129, 128, 127, 127, 126, 125,
526 125, 124, 123, 122, 121, 120, 119, 118,
527 117, 116, 115, 114, 113, 111, 110, 109,
528 107, 106, 105, 103, 102, 100, 99, 97,
529 96, 94, 92, 91, 89, 87, 85, 84, 82
530};
531
Joe Perches58aa68c2009-09-02 01:12:13 -0300532static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300533 -124, -124, -125, -125, -125, -125, -125, -125,
534 -125, -126, -126, -125, -125, -125, -125, -125,
535 -125, -124, -124, -124, -123, -123, -122, -122,
536 -121, -121, -120, -120, -119, -118, -117, -117,
537 -116, -115, -114, -113, -112, -111, -110, -109,
538 -108, -107, -105, -104, -103, -102, -100, -99,
539 -98, -96, -95, -93, -92, -91, -89, -87,
540 -86, -84, -83, -81, -79, -77, -76, -74,
541 -72, -70, -69, -67, -65, -63, -61, -59,
542 -57, -55, -53, -51, -49, -47, -45, -43,
543 -41, -39, -37, -35, -33, -30, -28, -26,
544 -24, -22, -20, -18, -15, -13, -11, -9,
545 -7, -4, -2, 0, 1, 3, 6, 8,
546 10, 12, 14, 17, 19, 21, 23, 25,
547 27, 29, 32, 34, 36, 38, 40, 42,
548 44, 46, 48, 50, 52, 54, 56, 58,
549 60, 62, 64, 66, 68, 70, 71, 73,
550 75, 77, 78, 80, 82, 83, 85, 87,
551 88, 90, 91, 93, 94, 96, 97, 98,
552 100, 101, 102, 104, 105, 106, 107, 108,
553 109, 111, 112, 113, 113, 114, 115, 116,
554 117, 118, 118, 119, 120, 120, 121, 122,
555 122, 123, 123, 124, 124, 124, 125, 125,
556 125, 125, 125, 125, 125, 126, 126, 125,
557 125, 125, 125, 125, 125, 124, 124, 124,
558 123, 123, 122, 122, 121, 121, 120, 120,
559 119, 118, 117, 117, 116, 115, 114, 113,
560 112, 111, 110, 109, 108, 107, 105, 104,
561 103, 102, 100, 99, 98, 96, 95, 93,
562 92, 91, 89, 87, 86, 84, 83, 81,
563 79, 77, 76, 74, 72, 70, 69, 67,
564 65, 63, 61, 59, 57, 55, 53, 51,
565 49, 47, 45, 43, 41, 39, 37, 35,
566 33, 30, 28, 26, 24, 22, 20, 18,
567 15, 13, 11, 9, 7, 4, 2, 0,
568 -1, -3, -6, -8, -10, -12, -14, -17,
569 -19, -21, -23, -25, -27, -29, -32, -34,
570 -36, -38, -40, -42, -44, -46, -48, -50,
571 -52, -54, -56, -58, -60, -62, -64, -66,
572 -68, -70, -71, -73, -75, -77, -78, -80,
573 -82, -83, -85, -87, -88, -90, -91, -93,
574 -94, -96, -97, -98, -100, -101, -102, -104,
575 -105, -106, -107, -108, -109, -111, -112, -113,
576 -113, -114, -115, -116, -117, -118, -118, -119,
577 -120, -120, -121, -122, -122, -123, -123, -124, -124
578};
579
Joe Perches58aa68c2009-09-02 01:12:13 -0300580static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300581 -100, -99, -98, -97, -95, -94, -93, -91,
582 -90, -89, -87, -86, -84, -83, -81, -80,
583 -78, -76, -75, -73, -71, -70, -68, -66,
584 -64, -63, -61, -59, -57, -55, -53, -51,
585 -49, -48, -46, -44, -42, -40, -38, -36,
586 -34, -32, -30, -27, -25, -23, -21, -19,
587 -17, -15, -13, -11, -9, -7, -4, -2,
588 0, 1, 3, 5, 7, 9, 11, 14,
589 16, 18, 20, 22, 24, 26, 28, 30,
590 32, 34, 36, 38, 40, 42, 44, 46,
591 48, 50, 52, 54, 56, 58, 59, 61,
592 63, 65, 67, 68, 70, 72, 74, 75,
593 77, 78, 80, 82, 83, 85, 86, 88,
594 89, 90, 92, 93, 95, 96, 97, 98,
595 100, 101, 102, 103, 104, 105, 106, 107,
596 108, 109, 110, 111, 112, 112, 113, 114,
597 115, 115, 116, 116, 117, 117, 118, 118,
598 119, 119, 119, 120, 120, 120, 120, 120,
599 121, 121, 121, 121, 121, 121, 120, 120,
600 120, 120, 120, 119, 119, 119, 118, 118,
601 117, 117, 116, 116, 115, 114, 114, 113,
602 112, 111, 111, 110, 109, 108, 107, 106,
603 105, 104, 103, 102, 100, 99, 98, 97,
604 95, 94, 93, 91, 90, 89, 87, 86,
605 84, 83, 81, 80, 78, 76, 75, 73,
606 71, 70, 68, 66, 64, 63, 61, 59,
607 57, 55, 53, 51, 49, 48, 46, 44,
608 42, 40, 38, 36, 34, 32, 30, 27,
609 25, 23, 21, 19, 17, 15, 13, 11,
610 9, 7, 4, 2, 0, -1, -3, -5,
611 -7, -9, -11, -14, -16, -18, -20, -22,
612 -24, -26, -28, -30, -32, -34, -36, -38,
613 -40, -42, -44, -46, -48, -50, -52, -54,
614 -56, -58, -59, -61, -63, -65, -67, -68,
615 -70, -72, -74, -75, -77, -78, -80, -82,
616 -83, -85, -86, -88, -89, -90, -92, -93,
617 -95, -96, -97, -98, -100, -101, -102, -103,
618 -104, -105, -106, -107, -108, -109, -110, -111,
619 -112, -112, -113, -114, -115, -115, -116, -116,
620 -117, -117, -118, -118, -119, -119, -119, -120,
621 -120, -120, -120, -120, -121, -121, -121, -121,
622 -121, -121, -120, -120, -120, -120, -120, -119,
623 -119, -119, -118, -118, -117, -117, -116, -116,
624 -115, -114, -114, -113, -112, -111, -111, -110,
625 -109, -108, -107, -106, -105, -104, -103, -102, -100
626};
627
Joe Perches58aa68c2009-09-02 01:12:13 -0300628static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300629 112, 113, 114, 114, 115, 116, 117, 117,
630 118, 118, 119, 119, 120, 120, 120, 121,
631 121, 121, 122, 122, 122, 122, 122, 122,
632 122, 122, 122, 122, 122, 122, 121, 121,
633 121, 120, 120, 120, 119, 119, 118, 118,
634 117, 116, 116, 115, 114, 113, 113, 112,
635 111, 110, 109, 108, 107, 106, 105, 104,
636 103, 102, 100, 99, 98, 97, 95, 94,
637 93, 91, 90, 88, 87, 85, 84, 82,
638 80, 79, 77, 76, 74, 72, 70, 69,
639 67, 65, 63, 61, 60, 58, 56, 54,
640 52, 50, 48, 46, 44, 42, 40, 38,
641 36, 34, 32, 30, 28, 26, 24, 22,
642 19, 17, 15, 13, 11, 9, 7, 5,
643 2, 0, -1, -3, -5, -7, -9, -12,
644 -14, -16, -18, -20, -22, -24, -26, -28,
645 -31, -33, -35, -37, -39, -41, -43, -45,
646 -47, -49, -51, -53, -54, -56, -58, -60,
647 -62, -64, -66, -67, -69, -71, -73, -74,
648 -76, -78, -79, -81, -83, -84, -86, -87,
649 -89, -90, -92, -93, -94, -96, -97, -98,
650 -99, -101, -102, -103, -104, -105, -106, -107,
651 -108, -109, -110, -111, -112, -113, -114, -114,
652 -115, -116, -117, -117, -118, -118, -119, -119,
653 -120, -120, -120, -121, -121, -121, -122, -122,
654 -122, -122, -122, -122, -122, -122, -122, -122,
655 -122, -122, -121, -121, -121, -120, -120, -120,
656 -119, -119, -118, -118, -117, -116, -116, -115,
657 -114, -113, -113, -112, -111, -110, -109, -108,
658 -107, -106, -105, -104, -103, -102, -100, -99,
659 -98, -97, -95, -94, -93, -91, -90, -88,
660 -87, -85, -84, -82, -80, -79, -77, -76,
661 -74, -72, -70, -69, -67, -65, -63, -61,
662 -60, -58, -56, -54, -52, -50, -48, -46,
663 -44, -42, -40, -38, -36, -34, -32, -30,
664 -28, -26, -24, -22, -19, -17, -15, -13,
665 -11, -9, -7, -5, -2, 0, 1, 3,
666 5, 7, 9, 12, 14, 16, 18, 20,
667 22, 24, 26, 28, 31, 33, 35, 37,
668 39, 41, 43, 45, 47, 49, 51, 53,
669 54, 56, 58, 60, 62, 64, 66, 67,
670 69, 71, 73, 74, 76, 78, 79, 81,
671 83, 84, 86, 87, 89, 90, 92, 93,
672 94, 96, 97, 98, 99, 101, 102, 103,
673 104, 105, 106, 107, 108, 109, 110, 111, 112
674};
675
Joe Perches58aa68c2009-09-02 01:12:13 -0300676static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300677 -11, -13, -15, -17, -19, -21, -23, -25,
678 -27, -29, -31, -33, -35, -37, -39, -41,
679 -43, -45, -46, -48, -50, -52, -54, -55,
680 -57, -59, -61, -62, -64, -66, -67, -69,
681 -71, -72, -74, -75, -77, -78, -80, -81,
682 -83, -84, -86, -87, -88, -90, -91, -92,
683 -93, -95, -96, -97, -98, -99, -100, -101,
684 -102, -103, -104, -105, -106, -106, -107, -108,
685 -109, -109, -110, -111, -111, -112, -112, -113,
686 -113, -114, -114, -114, -115, -115, -115, -115,
687 -116, -116, -116, -116, -116, -116, -116, -116,
688 -116, -115, -115, -115, -115, -114, -114, -114,
689 -113, -113, -112, -112, -111, -111, -110, -110,
690 -109, -108, -108, -107, -106, -105, -104, -103,
691 -102, -101, -100, -99, -98, -97, -96, -95,
692 -94, -93, -91, -90, -89, -88, -86, -85,
693 -84, -82, -81, -79, -78, -76, -75, -73,
694 -71, -70, -68, -67, -65, -63, -62, -60,
695 -58, -56, -55, -53, -51, -49, -47, -45,
696 -44, -42, -40, -38, -36, -34, -32, -30,
697 -28, -26, -24, -22, -20, -18, -16, -14,
698 -12, -10, -8, -6, -4, -2, 0, 1,
699 3, 5, 7, 9, 11, 13, 15, 17,
700 19, 21, 23, 25, 27, 29, 31, 33,
701 35, 37, 39, 41, 43, 45, 46, 48,
702 50, 52, 54, 55, 57, 59, 61, 62,
703 64, 66, 67, 69, 71, 72, 74, 75,
704 77, 78, 80, 81, 83, 84, 86, 87,
705 88, 90, 91, 92, 93, 95, 96, 97,
706 98, 99, 100, 101, 102, 103, 104, 105,
707 106, 106, 107, 108, 109, 109, 110, 111,
708 111, 112, 112, 113, 113, 114, 114, 114,
709 115, 115, 115, 115, 116, 116, 116, 116,
710 116, 116, 116, 116, 116, 115, 115, 115,
711 115, 114, 114, 114, 113, 113, 112, 112,
712 111, 111, 110, 110, 109, 108, 108, 107,
713 106, 105, 104, 103, 102, 101, 100, 99,
714 98, 97, 96, 95, 94, 93, 91, 90,
715 89, 88, 86, 85, 84, 82, 81, 79,
716 78, 76, 75, 73, 71, 70, 68, 67,
717 65, 63, 62, 60, 58, 56, 55, 53,
718 51, 49, 47, 45, 44, 42, 40, 38,
719 36, 34, 32, 30, 28, 26, 24, 22,
720 20, 18, 16, 14, 12, 10, 8, 6,
721 4, 2, 0, -1, -3, -5, -7, -9, -11
722};
723
724static u16 i2c_ident[] = {
725 V4L2_IDENT_OV9650,
726 V4L2_IDENT_OV9655,
727 V4L2_IDENT_SOI968,
728 V4L2_IDENT_OV7660,
729 V4L2_IDENT_OV7670,
730 V4L2_IDENT_MT9V011,
731 V4L2_IDENT_MT9V111,
732 V4L2_IDENT_MT9V112,
733 V4L2_IDENT_MT9M001C12ST,
734 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300735 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300736 V4L2_IDENT_HV7131R,
737};
738
739static u16 bridge_init[][2] = {
740 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
741 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
742 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
743 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
744 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
745 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
746 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
747 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
748 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
749 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
750 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
751 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
752 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
753 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
754 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
755 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
756 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
757 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300758 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
759 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300760};
761
762/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
763static u8 ov_gain[] = {
764 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
765 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
766 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
767 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
768 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
769 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
770 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
771 0x70 /* 8x */
772};
773
774/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
775static u16 micron1_gain[] = {
776 /* 1x 1.25x 1.5x 1.75x */
777 0x0020, 0x0028, 0x0030, 0x0038,
778 /* 2x 2.25x 2.5x 2.75x */
779 0x00a0, 0x00a4, 0x00a8, 0x00ac,
780 /* 3x 3.25x 3.5x 3.75x */
781 0x00b0, 0x00b4, 0x00b8, 0x00bc,
782 /* 4x 4.25x 4.5x 4.75x */
783 0x00c0, 0x00c4, 0x00c8, 0x00cc,
784 /* 5x 5.25x 5.5x 5.75x */
785 0x00d0, 0x00d4, 0x00d8, 0x00dc,
786 /* 6x 6.25x 6.5x 6.75x */
787 0x00e0, 0x00e4, 0x00e8, 0x00ec,
788 /* 7x 7.25x 7.5x 7.75x */
789 0x00f0, 0x00f4, 0x00f8, 0x00fc,
790 /* 8x */
791 0x01c0
792};
793
794/* mt9m001 sensor uses a different gain formula then other micron sensors */
795/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
796static u16 micron2_gain[] = {
797 /* 1x 1.25x 1.5x 1.75x */
798 0x0008, 0x000a, 0x000c, 0x000e,
799 /* 2x 2.25x 2.5x 2.75x */
800 0x0010, 0x0012, 0x0014, 0x0016,
801 /* 3x 3.25x 3.5x 3.75x */
802 0x0018, 0x001a, 0x001c, 0x001e,
803 /* 4x 4.25x 4.5x 4.75x */
804 0x0020, 0x0051, 0x0052, 0x0053,
805 /* 5x 5.25x 5.5x 5.75x */
806 0x0054, 0x0055, 0x0056, 0x0057,
807 /* 6x 6.25x 6.5x 6.75x */
808 0x0058, 0x0059, 0x005a, 0x005b,
809 /* 7x 7.25x 7.5x 7.75x */
810 0x005c, 0x005d, 0x005e, 0x005f,
811 /* 8x */
812 0x0060
813};
814
815/* Gain = .5 + bit[7:0] / 16 */
816static u8 hv7131r_gain[] = {
817 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
818 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
819 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
820 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
821 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
822 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
823 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
824 0x78 /* 8x */
825};
826
Joe Perches58aa68c2009-09-02 01:12:13 -0300827static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300828 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
829 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
830 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
831 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
832 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
833 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300834 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300835 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
836 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
837 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
838 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
839};
840
Joe Perches58aa68c2009-09-02 01:12:13 -0300841static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300842 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
843 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
844 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
Hans de Goede8bc50f32011-02-16 07:11:14 -0300845 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
846 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
847 {0x17, 0x10}, {0x18, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300848 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
849 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
850 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
851};
852
Joe Perches58aa68c2009-09-02 01:12:13 -0300853static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300854 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
855 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
856 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
857 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
858 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
859 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
860 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
861 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
862 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
863 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
864 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
865 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
866 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
867 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
868 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
869 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
870 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
871 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
872 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
873 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
874 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
875 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
876 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
877 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
878 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
879 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
880 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
881 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
882 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
883 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
884 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
885 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
886 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
887 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
888 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
889 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
890 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
891 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
892 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
893 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
894 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
895 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
896 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
897 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
898 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
899 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
900 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
901 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
902 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
903 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
904 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
905 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
906 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
907 {0x93, 0x00},
908};
909
Joe Perches58aa68c2009-09-02 01:12:13 -0300910static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300911 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
912 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
913 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
914 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
915 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
916 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
917 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
918 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
919 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
920 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
921 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
922 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
923 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
924 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
925 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
926 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
927 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
928 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
929 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
930 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
931 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
932 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
933 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
934 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
935 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
936 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
937 {0xaa, 0x92}, {0xab, 0x0a},
938};
939
Joe Perches58aa68c2009-09-02 01:12:13 -0300940static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300941 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
942 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
943 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
944 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
945 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
946 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
947 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
948 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
949 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
950 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
951 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
952 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
953 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
954 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
955 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
956 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300957 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300958 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
959 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300960 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300961 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
962 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
963 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
964 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300965};
966
Joe Perches58aa68c2009-09-02 01:12:13 -0300967static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300968 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
969 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
970 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
971 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
972 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
973 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
974 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
975 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
976 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
977 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
978 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
979 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
980 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
981 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
982 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
983 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
984};
985
Joe Perches58aa68c2009-09-02 01:12:13 -0300986static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300987 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
Brian Johnson6ea23bd2010-05-05 13:22:45 -0300988 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
989 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
990 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
991 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
992 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
993 {0x0e, 0x0008}, {0x20, 0x0000}
Brian Johnson26e744b2009-07-19 05:52:58 -0300994};
995
Joe Perches58aa68c2009-09-02 01:12:13 -0300996static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300997 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
998 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
999 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1000 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1001 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1002 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1003 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1004 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1005 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1006 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1007 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1008 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1009 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1010 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1011 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1012 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1013 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1014 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1015 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1016 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1017 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1018 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1019 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1020 {0x06, 0x0029}, {0x05, 0x0009},
1021};
1022
Joe Perches58aa68c2009-09-02 01:12:13 -03001023static struct i2c_reg_u16 mt9m001_init[] = {
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001024 {0x0d, 0x0001},
1025 {0x0d, 0x0000},
1026 {0x04, 0x0500}, /* hres = 1280 */
1027 {0x03, 0x0400}, /* vres = 1024 */
1028 {0x20, 0x1100},
1029 {0x06, 0x0010},
1030 {0x2b, 0x0024},
1031 {0x2e, 0x0024},
1032 {0x35, 0x0024},
1033 {0x2d, 0x0020},
1034 {0x2c, 0x0020},
1035 {0x09, 0x0ad4},
1036 {0x35, 0x0057},
Brian Johnson26e744b2009-07-19 05:52:58 -03001037};
1038
Joe Perches58aa68c2009-09-02 01:12:13 -03001039static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001040 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1041 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001042 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1043 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001044};
1045
Brian Johnsone99ac542010-03-16 13:58:28 -03001046static struct i2c_reg_u16 mt9m112_init[] = {
1047 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1048 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1049 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1050 {0xf0, 0x0000},
1051};
1052
Joe Perches58aa68c2009-09-02 01:12:13 -03001053static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001054 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1055 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1056 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1057 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1058 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1059 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1060 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1061 {0x23, 0x09}, {0x01, 0x08},
1062};
1063
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
Brian Johnson26e744b2009-07-19 05:52:58 -03001236 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001237 i2c_w1(gspca_dev, ov9650_init[i].reg,
1238 ov9650_init[i].val);
1239 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001240 pr_err("OV9650 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001241 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001242 }
1243 }
1244 sd->hstart = 1;
1245 sd->vstart = 7;
Brian Johnson26e744b2009-07-19 05:52:58 -03001246}
1247
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001248static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001249{
1250 int i;
1251 struct sd *sd = (struct sd *) gspca_dev;
1252
1253 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001254 i2c_w1(gspca_dev, ov9655_init[i].reg,
1255 ov9655_init[i].val);
1256 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001257 pr_err("OV9655 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001258 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001259 }
1260 }
1261 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001262 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001263 sd->hstart = 1;
1264 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001265}
1266
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001267static void soi968_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001268{
1269 int i;
1270 struct sd *sd = (struct sd *) gspca_dev;
1271
1272 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001273 i2c_w1(gspca_dev, soi968_init[i].reg,
1274 soi968_init[i].val);
1275 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001276 pr_err("SOI968 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001277 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001278 }
1279 }
1280 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001281 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1282 | (1 << EXPOSURE);
Brian Johnson26e744b2009-07-19 05:52:58 -03001283 sd->hstart = 60;
1284 sd->vstart = 11;
Brian Johnson26e744b2009-07-19 05:52:58 -03001285}
1286
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001287static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001288{
1289 int i;
1290 struct sd *sd = (struct sd *) gspca_dev;
1291
1292 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001293 i2c_w1(gspca_dev, ov7660_init[i].reg,
1294 ov7660_init[i].val);
1295 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001296 pr_err("OV7660 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001297 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001298 }
1299 }
Hans de Goede8bc50f32011-02-16 07:11:14 -03001300 sd->hstart = 3;
1301 sd->vstart = 3;
Brian Johnson26e744b2009-07-19 05:52:58 -03001302}
1303
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001304static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001305{
1306 int i;
1307 struct sd *sd = (struct sd *) gspca_dev;
1308
1309 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001310 i2c_w1(gspca_dev, ov7670_init[i].reg,
1311 ov7670_init[i].val);
1312 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001313 pr_err("OV7670 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001314 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001315 }
1316 }
1317 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001318 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Brian Johnson26e744b2009-07-19 05:52:58 -03001319 sd->hstart = 0;
1320 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001321}
1322
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001323static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001324{
1325 struct sd *sd = (struct sd *) gspca_dev;
1326 int i;
1327 u16 value;
Brian Johnson26e744b2009-07-19 05:52:58 -03001328
1329 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001330 i2c_r2(gspca_dev, 0xff, &value);
1331 if (gspca_dev->usb_err >= 0
1332 && value == 0x8243) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001333 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001334 i2c_w2(gspca_dev, mt9v011_init[i].reg,
1335 mt9v011_init[i].val);
1336 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001337 pr_err("MT9V011 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001338 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001339 }
1340 }
1341 sd->hstart = 2;
1342 sd->vstart = 2;
1343 sd->sensor = SENSOR_MT9V011;
Joe Perches91f58422011-08-21 19:56:55 -03001344 pr_info("MT9V011 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001345 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001346 }
1347
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001348 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001349 sd->i2c_addr = 0x5c;
1350 i2c_w2(gspca_dev, 0x01, 0x0004);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001351 i2c_r2(gspca_dev, 0xff, &value);
1352 if (gspca_dev->usb_err >= 0
1353 && value == 0x823a) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001354 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001355 i2c_w2(gspca_dev, mt9v111_init[i].reg,
1356 mt9v111_init[i].val);
1357 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001358 pr_err("MT9V111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001359 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001360 }
1361 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001362 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1363 | (1 << AUTOGAIN)
1364 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001365 sd->hstart = 2;
1366 sd->vstart = 2;
1367 sd->sensor = SENSOR_MT9V111;
Joe Perches91f58422011-08-21 19:56:55 -03001368 pr_info("MT9V111 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001369 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001370 }
1371
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001372 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001373 sd->i2c_addr = 0x5d;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001374 i2c_w2(gspca_dev, 0xf0, 0x0000);
1375 if (gspca_dev->usb_err < 0) {
1376 gspca_dev->usb_err = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001377 sd->i2c_addr = 0x48;
1378 i2c_w2(gspca_dev, 0xf0, 0x0000);
1379 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001380 i2c_r2(gspca_dev, 0x00, &value);
1381 if (gspca_dev->usb_err >= 0
1382 && value == 0x1229) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001383 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001384 i2c_w2(gspca_dev, mt9v112_init[i].reg,
1385 mt9v112_init[i].val);
1386 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001387 pr_err("MT9V112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001388 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001389 }
1390 }
1391 sd->hstart = 6;
1392 sd->vstart = 2;
1393 sd->sensor = SENSOR_MT9V112;
Joe Perches91f58422011-08-21 19:56:55 -03001394 pr_info("MT9V112 sensor detected\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001395 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001396 }
1397
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001398 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001399}
1400
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001401static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnsone99ac542010-03-16 13:58:28 -03001402{
1403 struct sd *sd = (struct sd *) gspca_dev;
1404 int i;
1405 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001406 i2c_w2(gspca_dev, mt9m112_init[i].reg,
1407 mt9m112_init[i].val);
1408 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001409 pr_err("MT9M112 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001410 return;
Brian Johnsone99ac542010-03-16 13:58:28 -03001411 }
1412 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001413 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1414 | (1 << GAIN);
Brian Johnsone99ac542010-03-16 13:58:28 -03001415 sd->hstart = 0;
1416 sd->vstart = 2;
Brian Johnsone99ac542010-03-16 13:58:28 -03001417}
1418
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001419static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001420{
1421 struct sd *sd = (struct sd *) gspca_dev;
1422 int i;
1423 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001424 i2c_w2(gspca_dev, mt9m111_init[i].reg,
1425 mt9m111_init[i].val);
1426 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001427 pr_err("MT9M111 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001428 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001429 }
1430 }
Jean-François Moinec5224d82012-03-19 04:30:07 -03001431 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1432 | (1 << GAIN);
Brian Johnson26e744b2009-07-19 05:52:58 -03001433 sd->hstart = 0;
1434 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001435}
1436
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001437static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001438{
1439 struct sd *sd = (struct sd *) gspca_dev;
1440 int i;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001441 u16 id;
1442
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001443 i2c_r2(gspca_dev, 0x00, &id);
1444 if (gspca_dev->usb_err < 0)
1445 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001446
1447 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1448 switch (id) {
1449 case 0x8411:
1450 case 0x8421:
Joe Perches91f58422011-08-21 19:56:55 -03001451 pr_info("MT9M001 color sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001452 break;
1453 case 0x8431:
Joe Perches91f58422011-08-21 19:56:55 -03001454 pr_info("MT9M001 mono sensor detected\n");
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001455 break;
1456 default:
Joe Perches91f58422011-08-21 19:56:55 -03001457 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001458 gspca_dev->usb_err = -ENODEV;
1459 return;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001460 }
1461
Brian Johnson26e744b2009-07-19 05:52:58 -03001462 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001463 i2c_w2(gspca_dev, mt9m001_init[i].reg,
1464 mt9m001_init[i].val);
1465 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001466 pr_err("MT9M001 sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001467 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001468 }
1469 }
1470 /* disable hflip and vflip */
Jean-François Moinec5224d82012-03-19 04:30:07 -03001471 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001472 sd->hstart = 1;
1473 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001474}
1475
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001476static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001477{
1478 int i;
1479 struct sd *sd = (struct sd *) gspca_dev;
1480
1481 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001482 i2c_w1(gspca_dev, hv7131r_init[i].reg,
1483 hv7131r_init[i].val);
1484 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001485 pr_err("HV7131R Sensor initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001486 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001487 }
1488 }
1489 sd->hstart = 0;
1490 sd->vstart = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001491}
1492
Jean-François Moinec5224d82012-03-19 04:30:07 -03001493static void set_cmatrix(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001494{
1495 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001496 int satur;
1497 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001498 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001499
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001500 memset(cmatrix, 0, sizeof cmatrix);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001501 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26;
Brian Johnson26e744b2009-07-19 05:52:58 -03001502 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1503 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001504 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80;
Brian Johnson26e744b2009-07-19 05:52:58 -03001505
Jean-François Moinec5224d82012-03-19 04:30:07 -03001506 satur = sd->ctrls[SATURATION].val;
1507 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001508 cmatrix[6] = hue_coord;
1509 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001510
Jean-François Moinec5224d82012-03-19 04:30:07 -03001511 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001512 cmatrix[8] = hue_coord;
1513 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001514
Jean-François Moinec5224d82012-03-19 04:30:07 -03001515 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001516 cmatrix[10] = hue_coord;
1517 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001518
Jean-François Moinec5224d82012-03-19 04:30:07 -03001519 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001520 cmatrix[12] = hue_coord;
1521 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001522
Jean-François Moinec5224d82012-03-19 04:30:07 -03001523 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001524 cmatrix[14] = hue_coord;
1525 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001526
Jean-François Moinec5224d82012-03-19 04:30:07 -03001527 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001528 cmatrix[16] = hue_coord;
1529 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001530
Jean-François Moinec5224d82012-03-19 04:30:07 -03001531 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
Brian Johnson26e744b2009-07-19 05:52:58 -03001532}
1533
Jean-François Moinec5224d82012-03-19 04:30:07 -03001534static void set_gamma(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537 u8 gamma[17];
Jean-François Moinec5224d82012-03-19 04:30:07 -03001538 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100;
Brian Johnson26e744b2009-07-19 05:52:58 -03001539
1540 gamma[0] = 0x0a;
1541 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1542 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1543 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1544 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1545 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1546 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1547 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1548 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1549 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1550 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1551 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1552 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1553 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1554 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1555 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1556 gamma[16] = 0xf5;
1557
Jean-François Moinec5224d82012-03-19 04:30:07 -03001558 reg_w(gspca_dev, 0x1190, gamma, 17);
Brian Johnson26e744b2009-07-19 05:52:58 -03001559}
1560
Jean-François Moinec5224d82012-03-19 04:30:07 -03001561static void set_redblue(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001562{
1563 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001564
1565 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1566 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001567}
1568
Jean-François Moinec5224d82012-03-19 04:30:07 -03001569static void set_hvflip(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001570{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001571 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001572 u16 value2;
1573 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001574
1575 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001576 hflip = !sd->ctrls[HFLIP].val;
1577 vflip = !sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001578 } else {
Jean-François Moinec5224d82012-03-19 04:30:07 -03001579 hflip = sd->ctrls[HFLIP].val;
1580 vflip = sd->ctrls[VFLIP].val;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001581 }
1582
Brian Johnson26e744b2009-07-19 05:52:58 -03001583 switch (sd->sensor) {
Hans de Goede779b51f2011-02-16 08:17:36 -03001584 case SENSOR_OV7660:
1585 value = 0x01;
1586 if (hflip)
1587 value |= 0x20;
1588 if (vflip) {
1589 value |= 0x10;
1590 sd->vstart = 2;
1591 } else
1592 sd->vstart = 3;
1593 reg_w1(gspca_dev, 0x1182, sd->vstart);
1594 i2c_w1(gspca_dev, 0x1e, value);
1595 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001596 case SENSOR_OV9650:
1597 i2c_r1(gspca_dev, 0x1e, &value);
1598 value &= ~0x30;
1599 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001600 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001601 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001602 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001603 value |= 0x10;
1604 tslb = 0x49;
1605 }
1606 i2c_w1(gspca_dev, 0x1e, value);
1607 i2c_w1(gspca_dev, 0x3a, tslb);
1608 break;
1609 case SENSOR_MT9V111:
1610 case SENSOR_MT9V011:
1611 i2c_r2(gspca_dev, 0x20, &value2);
1612 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001613 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001614 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001615 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001616 value2 |= 0x4020;
1617 i2c_w2(gspca_dev, 0x20, value2);
1618 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001619 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001620 case SENSOR_MT9M111:
1621 case SENSOR_MT9V112:
1622 i2c_r2(gspca_dev, 0x20, &value2);
1623 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001624 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001625 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001626 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001627 value2 |= 0x0001;
1628 i2c_w2(gspca_dev, 0x20, value2);
1629 break;
1630 case SENSOR_HV7131R:
1631 i2c_r1(gspca_dev, 0x01, &value);
1632 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001633 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001634 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001635 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001636 value |= 0x02;
1637 i2c_w1(gspca_dev, 0x01, value);
1638 break;
1639 }
Brian Johnson26e744b2009-07-19 05:52:58 -03001640}
1641
Jean-François Moinec5224d82012-03-19 04:30:07 -03001642static void set_exposure(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001643{
1644 struct sd *sd = (struct sd *) gspca_dev;
1645 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001646 int expo;
1647
1648 expo = sd->ctrls[EXPOSURE].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001649 switch (sd->sensor) {
1650 case SENSOR_OV7660:
1651 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001652 case SENSOR_OV9655:
1653 case SENSOR_OV9650:
1654 exp[0] |= (3 << 4);
1655 exp[2] = 0x2d;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001656 exp[3] = expo;
1657 exp[4] = expo >> 8;
Brian Johnson26e744b2009-07-19 05:52:58 -03001658 break;
1659 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001660 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001661 case SENSOR_MT9V011:
1662 exp[0] |= (3 << 4);
1663 exp[2] = 0x09;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001664 exp[3] = expo >> 8;
1665 exp[4] = expo;
Brian Johnson26e744b2009-07-19 05:52:58 -03001666 break;
1667 case SENSOR_HV7131R:
1668 exp[0] |= (4 << 4);
1669 exp[2] = 0x25;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001670 exp[3] = expo >> 5;
1671 exp[4] = expo << 3;
German Galkine10f7312010-03-07 06:19:02 -03001672 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001673 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001674 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001675 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001676 }
1677 i2c_w(gspca_dev, exp);
Brian Johnson26e744b2009-07-19 05:52:58 -03001678}
1679
Jean-François Moinec5224d82012-03-19 04:30:07 -03001680static void set_gain(struct gspca_dev *gspca_dev)
Brian Johnson26e744b2009-07-19 05:52:58 -03001681{
1682 struct sd *sd = (struct sd *) gspca_dev;
1683 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
Jean-François Moinec5224d82012-03-19 04:30:07 -03001684 int g;
1685
1686 g = sd->ctrls[GAIN].val;
Brian Johnson26e744b2009-07-19 05:52:58 -03001687 switch (sd->sensor) {
1688 case SENSOR_OV7660:
1689 case SENSOR_OV7670:
1690 case SENSOR_SOI968:
1691 case SENSOR_OV9655:
1692 case SENSOR_OV9650:
1693 gain[0] |= (2 << 4);
Jean-François Moinec5224d82012-03-19 04:30:07 -03001694 gain[3] = ov_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001695 break;
1696 case SENSOR_MT9V011:
Brian Johnson26e744b2009-07-19 05:52:58 -03001697 gain[0] |= (3 << 4);
1698 gain[2] = 0x35;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001699 gain[3] = micron1_gain[g] >> 8;
1700 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001701 break;
1702 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001703 gain[0] |= (3 << 4);
1704 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001705 gain[3] = micron1_gain[g] >> 8;
1706 gain[4] = micron1_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001707 break;
1708 case SENSOR_MT9M001:
1709 gain[0] |= (3 << 4);
1710 gain[2] = 0x2f;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001711 gain[3] = micron2_gain[g] >> 8;
1712 gain[4] = micron2_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001713 break;
1714 case SENSOR_HV7131R:
1715 gain[0] |= (2 << 4);
1716 gain[2] = 0x30;
Jean-François Moinec5224d82012-03-19 04:30:07 -03001717 gain[3] = hv7131r_gain[g];
Brian Johnson26e744b2009-07-19 05:52:58 -03001718 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001719 default:
Jean-François Moinec5224d82012-03-19 04:30:07 -03001720 return;
Brian Johnson26e744b2009-07-19 05:52:58 -03001721 }
1722 i2c_w(gspca_dev, gain);
Brian Johnson26e744b2009-07-19 05:52:58 -03001723}
1724
1725#ifdef CONFIG_VIDEO_ADV_DEBUG
1726static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1727 struct v4l2_dbg_register *reg)
1728{
1729 struct sd *sd = (struct sd *) gspca_dev;
1730 switch (reg->match.type) {
1731 case V4L2_CHIP_MATCH_HOST:
1732 if (reg->match.addr != 0)
1733 return -EINVAL;
1734 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1735 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001736 reg_r(gspca_dev, reg->reg, 1);
Brian Johnson26e744b2009-07-19 05:52:58 -03001737 reg->val = gspca_dev->usb_buf[0];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001738 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001739 case V4L2_CHIP_MATCH_I2C_ADDR:
1740 if (reg->match.addr != sd->i2c_addr)
1741 return -EINVAL;
1742 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001743 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001744 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001745 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001746 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001747 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001748 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001749 }
1750 return -EINVAL;
1751}
1752
1753static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1754 struct v4l2_dbg_register *reg)
1755{
1756 struct sd *sd = (struct sd *) gspca_dev;
1757 switch (reg->match.type) {
1758 case V4L2_CHIP_MATCH_HOST:
1759 if (reg->match.addr != 0)
1760 return -EINVAL;
1761 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1762 return -EINVAL;
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001763 reg_w1(gspca_dev, reg->reg, reg->val);
1764 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001765 case V4L2_CHIP_MATCH_I2C_ADDR:
1766 if (reg->match.addr != sd->i2c_addr)
1767 return -EINVAL;
1768 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001769 sd->sensor <= SENSOR_MT9M112) {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001770 i2c_w2(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001771 } else {
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001772 i2c_w1(gspca_dev, reg->reg, reg->val);
Brian Johnson26e744b2009-07-19 05:52:58 -03001773 }
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001774 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001775 }
1776 return -EINVAL;
1777}
1778#endif
1779
1780static int sd_chip_ident(struct gspca_dev *gspca_dev,
1781 struct v4l2_dbg_chip_ident *chip)
1782{
1783 struct sd *sd = (struct sd *) gspca_dev;
1784
1785 switch (chip->match.type) {
1786 case V4L2_CHIP_MATCH_HOST:
1787 if (chip->match.addr != 0)
1788 return -EINVAL;
1789 chip->revision = 0;
1790 chip->ident = V4L2_IDENT_SN9C20X;
1791 return 0;
1792 case V4L2_CHIP_MATCH_I2C_ADDR:
1793 if (chip->match.addr != sd->i2c_addr)
1794 return -EINVAL;
1795 chip->revision = 0;
1796 chip->ident = i2c_ident[sd->sensor];
1797 return 0;
1798 }
1799 return -EINVAL;
1800}
1801
1802static int sd_config(struct gspca_dev *gspca_dev,
1803 const struct usb_device_id *id)
1804{
1805 struct sd *sd = (struct sd *) gspca_dev;
1806 struct cam *cam;
1807
1808 cam = &gspca_dev->cam;
Hans de Goedeeb3fb7c2012-01-01 16:35:01 -03001809 cam->needs_full_bandwidth = 1;
Brian Johnson26e744b2009-07-19 05:52:58 -03001810
1811 sd->sensor = (id->driver_info >> 8) & 0xff;
1812 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001813 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001814
1815 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001816 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001817 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001818 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001819 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001820 cam->cam_mode = sxga_mode;
1821 cam->nmodes = ARRAY_SIZE(sxga_mode);
1822 break;
Mauro Carvalho Chehabd162e7a2010-12-07 19:39:33 -03001823 case SENSOR_MT9M001:
1824 cam->cam_mode = mono_mode;
1825 cam->nmodes = ARRAY_SIZE(mono_mode);
1826 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001827 default:
1828 cam->cam_mode = vga_mode;
1829 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001830 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001831 }
1832
1833 sd->old_step = 0;
1834 sd->older_step = 0;
1835 sd->exposure_step = 16;
1836
Jean-François Moinec5224d82012-03-19 04:30:07 -03001837 gspca_dev->cam.ctrls = sd->ctrls;
Brian Johnson26e744b2009-07-19 05:52:58 -03001838
1839 sd->quality = 95;
1840
Brian Johnson26e744b2009-07-19 05:52:58 -03001841 return 0;
1842}
1843
1844static int sd_init(struct gspca_dev *gspca_dev)
1845{
1846 struct sd *sd = (struct sd *) gspca_dev;
1847 int i;
1848 u8 value;
1849 u8 i2c_init[9] =
1850 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1851
1852 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1853 value = bridge_init[i][1];
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001854 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1855 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001856 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001857 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001858 }
1859 }
1860
Brian Johnson0c045eb2010-03-16 13:58:27 -03001861 if (sd->flags & LED_REVERSE)
1862 reg_w1(gspca_dev, 0x1006, 0x00);
1863 else
1864 reg_w1(gspca_dev, 0x1006, 0x20);
1865
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001866 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1867 if (gspca_dev->usb_err < 0) {
Joe Perches91f58422011-08-21 19:56:55 -03001868 pr_err("Device initialization failed\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001869 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001870 }
1871
1872 switch (sd->sensor) {
1873 case SENSOR_OV9650:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001874 ov9650_init_sensor(gspca_dev);
1875 if (gspca_dev->usb_err < 0)
1876 break;
Joe Perches91f58422011-08-21 19:56:55 -03001877 pr_info("OV9650 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001878 break;
1879 case SENSOR_OV9655:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001880 ov9655_init_sensor(gspca_dev);
1881 if (gspca_dev->usb_err < 0)
1882 break;
Joe Perches91f58422011-08-21 19:56:55 -03001883 pr_info("OV9655 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001884 break;
1885 case SENSOR_SOI968:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001886 soi968_init_sensor(gspca_dev);
1887 if (gspca_dev->usb_err < 0)
1888 break;
Joe Perches91f58422011-08-21 19:56:55 -03001889 pr_info("SOI968 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001890 break;
1891 case SENSOR_OV7660:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001892 ov7660_init_sensor(gspca_dev);
1893 if (gspca_dev->usb_err < 0)
1894 break;
Joe Perches91f58422011-08-21 19:56:55 -03001895 pr_info("OV7660 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001896 break;
1897 case SENSOR_OV7670:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001898 ov7670_init_sensor(gspca_dev);
1899 if (gspca_dev->usb_err < 0)
1900 break;
Joe Perches91f58422011-08-21 19:56:55 -03001901 pr_info("OV7670 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001902 break;
1903 case SENSOR_MT9VPRB:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001904 mt9v_init_sensor(gspca_dev);
1905 if (gspca_dev->usb_err < 0)
1906 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001907 break;
1908 case SENSOR_MT9M111:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001909 mt9m111_init_sensor(gspca_dev);
1910 if (gspca_dev->usb_err < 0)
1911 break;
Joe Perches91f58422011-08-21 19:56:55 -03001912 pr_info("MT9M111 sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001913 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001914 case SENSOR_MT9M112:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001915 mt9m112_init_sensor(gspca_dev);
1916 if (gspca_dev->usb_err < 0)
1917 break;
Joe Perches91f58422011-08-21 19:56:55 -03001918 pr_info("MT9M112 sensor detected\n");
Brian Johnsone99ac542010-03-16 13:58:28 -03001919 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001920 case SENSOR_MT9M001:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001921 mt9m001_init_sensor(gspca_dev);
1922 if (gspca_dev->usb_err < 0)
1923 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001924 break;
1925 case SENSOR_HV7131R:
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001926 hv7131r_init_sensor(gspca_dev);
1927 if (gspca_dev->usb_err < 0)
1928 break;
Joe Perches91f58422011-08-21 19:56:55 -03001929 pr_info("HV7131R sensor detected\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03001930 break;
1931 default:
Joe Perches91f58422011-08-21 19:56:55 -03001932 pr_info("Unsupported Sensor\n");
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001933 gspca_dev->usb_err = -ENODEV;
Brian Johnson26e744b2009-07-19 05:52:58 -03001934 }
1935
Jean-François Moinefe86ec72012-03-19 04:32:15 -03001936 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03001937}
1938
1939static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1940{
1941 struct sd *sd = (struct sd *) gspca_dev;
1942 u8 value;
1943 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001944 case SENSOR_SOI968:
1945 if (mode & MODE_SXGA) {
1946 i2c_w1(gspca_dev, 0x17, 0x1d);
1947 i2c_w1(gspca_dev, 0x18, 0xbd);
1948 i2c_w1(gspca_dev, 0x19, 0x01);
1949 i2c_w1(gspca_dev, 0x1a, 0x81);
1950 i2c_w1(gspca_dev, 0x12, 0x00);
1951 sd->hstart = 140;
1952 sd->vstart = 19;
1953 } else {
1954 i2c_w1(gspca_dev, 0x17, 0x13);
1955 i2c_w1(gspca_dev, 0x18, 0x63);
1956 i2c_w1(gspca_dev, 0x19, 0x01);
1957 i2c_w1(gspca_dev, 0x1a, 0x79);
1958 i2c_w1(gspca_dev, 0x12, 0x40);
1959 sd->hstart = 60;
1960 sd->vstart = 11;
1961 }
1962 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001963 case SENSOR_OV9650:
1964 if (mode & MODE_SXGA) {
1965 i2c_w1(gspca_dev, 0x17, 0x1b);
1966 i2c_w1(gspca_dev, 0x18, 0xbc);
1967 i2c_w1(gspca_dev, 0x19, 0x01);
1968 i2c_w1(gspca_dev, 0x1a, 0x82);
1969 i2c_r1(gspca_dev, 0x12, &value);
1970 i2c_w1(gspca_dev, 0x12, value & 0x07);
1971 } else {
1972 i2c_w1(gspca_dev, 0x17, 0x24);
1973 i2c_w1(gspca_dev, 0x18, 0xc5);
1974 i2c_w1(gspca_dev, 0x19, 0x00);
1975 i2c_w1(gspca_dev, 0x1a, 0x3c);
1976 i2c_r1(gspca_dev, 0x12, &value);
1977 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1978 }
1979 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001980 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001981 case SENSOR_MT9M111:
1982 if (mode & MODE_SXGA) {
1983 i2c_w2(gspca_dev, 0xf0, 0x0002);
1984 i2c_w2(gspca_dev, 0xc8, 0x970b);
1985 i2c_w2(gspca_dev, 0xf0, 0x0000);
1986 } else {
1987 i2c_w2(gspca_dev, 0xf0, 0x0002);
1988 i2c_w2(gspca_dev, 0xc8, 0x8000);
1989 i2c_w2(gspca_dev, 0xf0, 0x0000);
1990 }
1991 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001992 }
1993}
1994
Hans de Goeded80dd5d2012-01-01 16:03:37 -03001995static int sd_isoc_init(struct gspca_dev *gspca_dev)
1996{
1997 struct usb_interface *intf;
1998 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
1999
2000 /*
2001 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
2002 * than our regular bandwidth calculations reserve, so we force the
2003 * use of a specific altsetting when using the SN9C20X_I420 fmt.
2004 */
2005 if (!(flags & (MODE_RAW | MODE_JPEG))) {
2006 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
2007
2008 if (intf->num_altsetting != 9) {
2009 pr_warn("sn9c20x camera with unknown number of alt "
2010 "settings (%d), please report!\n",
2011 intf->num_altsetting);
2012 gspca_dev->alt = intf->num_altsetting;
2013 return 0;
2014 }
2015
2016 switch (gspca_dev->width) {
2017 case 160: /* 160x120 */
2018 gspca_dev->alt = 2;
2019 break;
2020 case 320: /* 320x240 */
2021 gspca_dev->alt = 6;
2022 break;
2023 default: /* >= 640x480 */
2024 gspca_dev->alt = 9;
2025 }
2026 }
2027
2028 return 0;
2029}
2030
Brian Johnson26e744b2009-07-19 05:52:58 -03002031#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002032((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002033(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2034(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2035
2036#define CLR_WIN(width, height) \
2037((const u8 [])\
2038{0, width >> 2, 0, height >> 1,\
2039((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2040
2041static int sd_start(struct gspca_dev *gspca_dev)
2042{
2043 struct sd *sd = (struct sd *) gspca_dev;
2044 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2045 int width = gspca_dev->width;
2046 int height = gspca_dev->height;
2047 u8 fmt, scale = 0;
2048
Brian Johnson26e744b2009-07-19 05:52:58 -03002049 jpeg_define(sd->jpeg_hdr, height, width,
2050 0x21);
2051 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2052
2053 if (mode & MODE_RAW)
2054 fmt = 0x2d;
2055 else if (mode & MODE_JPEG)
2056 fmt = 0x2c;
2057 else
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002058 fmt = 0x2f; /* YUV 420 */
Brian Johnson26e744b2009-07-19 05:52:58 -03002059
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002060 switch (mode & SCALE_MASK) {
2061 case SCALE_1280x1024:
Brian Johnson26e744b2009-07-19 05:52:58 -03002062 scale = 0xc0;
Joe Perches91f58422011-08-21 19:56:55 -03002063 pr_info("Set 1280x1024\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002064 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002065 case SCALE_640x480:
Brian Johnson26e744b2009-07-19 05:52:58 -03002066 scale = 0x80;
Joe Perches91f58422011-08-21 19:56:55 -03002067 pr_info("Set 640x480\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002068 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002069 case SCALE_320x240:
Brian Johnson26e744b2009-07-19 05:52:58 -03002070 scale = 0x90;
Joe Perches91f58422011-08-21 19:56:55 -03002071 pr_info("Set 320x240\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002072 break;
Mauro Carvalho Chehab86701c12010-12-07 14:47:10 -03002073 case SCALE_160x120:
Brian Johnson26e744b2009-07-19 05:52:58 -03002074 scale = 0xa0;
Joe Perches91f58422011-08-21 19:56:55 -03002075 pr_info("Set 160x120\n");
Brian Johnson26e744b2009-07-19 05:52:58 -03002076 break;
2077 }
2078
2079 configure_sensor_output(gspca_dev, mode);
Jean-François Moine9a731a32010-06-04 05:26:42 -03002080 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2081 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
Brian Johnson26e744b2009-07-19 05:52:58 -03002082 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2083 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2084 reg_w1(gspca_dev, 0x1189, scale);
2085 reg_w1(gspca_dev, 0x10e0, fmt);
2086
2087 set_cmatrix(gspca_dev);
2088 set_gamma(gspca_dev);
2089 set_redblue(gspca_dev);
2090 set_gain(gspca_dev);
2091 set_exposure(gspca_dev);
2092 set_hvflip(gspca_dev);
2093
Brian Johnson0c045eb2010-03-16 13:58:27 -03002094 reg_w1(gspca_dev, 0x1007, 0x20);
2095
Brian Johnson26e744b2009-07-19 05:52:58 -03002096 reg_r(gspca_dev, 0x1061, 1);
2097 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
Jean-François Moinefe86ec72012-03-19 04:32:15 -03002098 return gspca_dev->usb_err;
Brian Johnson26e744b2009-07-19 05:52:58 -03002099}
2100
2101static void sd_stopN(struct gspca_dev *gspca_dev)
2102{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002103 reg_w1(gspca_dev, 0x1007, 0x00);
2104
Brian Johnson26e744b2009-07-19 05:52:58 -03002105 reg_r(gspca_dev, 0x1061, 1);
2106 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2107}
2108
Brian Johnsone1430472009-09-02 12:39:41 -03002109static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002110{
2111 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002112 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002113
2114 /*
2115 * some hardcoded values are present
2116 * like those for maximal/minimal exposure
2117 * and exposure steps
2118 */
2119 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002120 if (sd->ctrls[EXPOSURE].val > 0x1770)
Brian Johnson26e744b2009-07-19 05:52:58 -03002121 return;
2122
Jean-François Moinec5224d82012-03-19 04:30:07 -03002123 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002124 if (new_exp > 0x1770)
2125 new_exp = 0x1770;
2126 if (new_exp < 0x10)
2127 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002128 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002129 set_exposure(gspca_dev);
2130
2131 sd->older_step = sd->old_step;
2132 sd->old_step = 1;
2133
2134 if (sd->old_step ^ sd->older_step)
2135 sd->exposure_step /= 2;
2136 else
2137 sd->exposure_step += 2;
2138 }
2139 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002140 if (sd->ctrls[EXPOSURE].val < 0x10)
Brian Johnson26e744b2009-07-19 05:52:58 -03002141 return;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002142 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step;
Brian Johnson26e744b2009-07-19 05:52:58 -03002143 if (new_exp > 0x1700)
2144 new_exp = 0x1770;
2145 if (new_exp < 0x10)
2146 new_exp = 0x10;
Jean-François Moinec5224d82012-03-19 04:30:07 -03002147 sd->ctrls[EXPOSURE].val = new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002148 set_exposure(gspca_dev);
2149 sd->older_step = sd->old_step;
2150 sd->old_step = 0;
2151
2152 if (sd->old_step ^ sd->older_step)
2153 sd->exposure_step /= 2;
2154 else
2155 sd->exposure_step += 2;
2156 }
2157}
2158
Brian Johnsone1430472009-09-02 12:39:41 -03002159static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2160{
2161 struct sd *sd = (struct sd *) gspca_dev;
2162
2163 if (avg_lum < MIN_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002164 if (sd->ctrls[GAIN].val + 1 <= 28) {
2165 sd->ctrls[GAIN].val++;
Brian Johnsone1430472009-09-02 12:39:41 -03002166 set_gain(gspca_dev);
2167 }
2168 }
2169 if (avg_lum > MAX_AVG_LUM) {
Jean-François Moinec5224d82012-03-19 04:30:07 -03002170 if (sd->ctrls[GAIN].val > 0) {
2171 sd->ctrls[GAIN].val--;
Brian Johnsone1430472009-09-02 12:39:41 -03002172 set_gain(gspca_dev);
2173 }
2174 }
2175}
2176
2177static void sd_dqcallback(struct gspca_dev *gspca_dev)
2178{
2179 struct sd *sd = (struct sd *) gspca_dev;
2180 int avg_lum;
2181
Jean-François Moinec5224d82012-03-19 04:30:07 -03002182 if (!sd->ctrls[AUTOGAIN].val)
Brian Johnsone1430472009-09-02 12:39:41 -03002183 return;
2184
2185 avg_lum = atomic_read(&sd->avg_lum);
2186 if (sd->sensor == SENSOR_SOI968)
2187 do_autogain(gspca_dev, avg_lum);
2188 else
2189 do_autoexposure(gspca_dev, avg_lum);
2190}
2191
Jean-François Moine28566432010-10-01 07:33:26 -03002192#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002193static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2194 u8 *data, /* interrupt packet */
2195 int len) /* interrupt packet length */
2196{
2197 struct sd *sd = (struct sd *) gspca_dev;
2198 int ret = -EINVAL;
Brian Johnson33ddc162010-04-18 21:42:40 -03002199 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002200 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2201 input_sync(gspca_dev->input_dev);
2202 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2203 input_sync(gspca_dev->input_dev);
2204 ret = 0;
2205 }
2206 return ret;
2207}
2208#endif
2209
Brian Johnson26e744b2009-07-19 05:52:58 -03002210static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002211 u8 *data, /* isoc packet */
2212 int len) /* iso packet length */
2213{
2214 struct sd *sd = (struct sd *) gspca_dev;
2215 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002216 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002217 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Jean-François Moine1f42df02012-03-19 04:22:44 -03002218 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03002219 avg_lum = ((data[35] >> 2) & 3) |
2220 (data[20] << 2) |
2221 (data[19] << 10);
2222 avg_lum += ((data[35] >> 4) & 3) |
2223 (data[22] << 2) |
2224 (data[21] << 10);
2225 avg_lum += ((data[35] >> 6) & 3) |
2226 (data[24] << 2) |
2227 (data[23] << 10);
2228 avg_lum += (data[36] & 3) |
2229 (data[26] << 2) |
2230 (data[25] << 10);
2231 avg_lum += ((data[36] >> 2) & 3) |
2232 (data[28] << 2) |
2233 (data[27] << 10);
2234 avg_lum += ((data[36] >> 4) & 3) |
2235 (data[30] << 2) |
2236 (data[29] << 10);
2237 avg_lum += ((data[36] >> 6) & 3) |
2238 (data[32] << 2) |
2239 (data[31] << 10);
2240 avg_lum += ((data[44] >> 4) & 3) |
2241 (data[34] << 2) |
2242 (data[33] << 10);
2243 avg_lum >>= 9;
2244 atomic_set(&sd->avg_lum, avg_lum);
Jean-François Moine04d174e2010-09-13 05:22:37 -03002245 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Jean-François Moine1f42df02012-03-19 04:22:44 -03002246 len -= 64;
2247 if (len == 0)
2248 return;
2249 data += 64;
Brian Johnson26e744b2009-07-19 05:52:58 -03002250 }
2251 if (gspca_dev->last_packet_type == LAST_PACKET) {
2252 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2253 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002254 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002255 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002256 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002257 data, len);
2258 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002259 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002260 data, len);
2261 }
2262 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002263 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002264 }
2265}
2266
2267/* sub-driver description */
2268static const struct sd_desc sd_desc = {
2269 .name = MODULE_NAME,
2270 .ctrls = sd_ctrls,
2271 .nctrls = ARRAY_SIZE(sd_ctrls),
2272 .config = sd_config,
2273 .init = sd_init,
Hans de Goeded80dd5d2012-01-01 16:03:37 -03002274 .isoc_init = sd_isoc_init,
Brian Johnson26e744b2009-07-19 05:52:58 -03002275 .start = sd_start,
2276 .stopN = sd_stopN,
Brian Johnson26e744b2009-07-19 05:52:58 -03002277 .pkt_scan = sd_pkt_scan,
Jean-François Moine28566432010-10-01 07:33:26 -03002278#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002279 .int_pkt_scan = sd_int_pkt_scan,
2280#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002281 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002282#ifdef CONFIG_VIDEO_ADV_DEBUG
2283 .set_register = sd_dbg_s_register,
2284 .get_register = sd_dbg_g_register,
2285#endif
2286 .get_chip_ident = sd_chip_ident,
2287};
2288
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002289#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002290 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002291 | (SENSOR_ ## sensor << 8) \
2292 | (i2c_addr)
2293
Jean-François Moine95c967c2011-01-13 05:20:29 -03002294static const struct usb_device_id device_table[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03002295 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2296 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2297 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002298 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002299 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2300 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2301 (FLIP_DETECT | HAS_NO_BUTTON))},
Brian Johnson26e744b2009-07-19 05:52:58 -03002302 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2303 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2304 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2305 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
Hans de Goede779b51f2011-02-16 08:17:36 -03002306 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002307 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2308 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2309 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2310 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002311 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002312 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002313 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2314 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2315 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2316 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
Frank Schaefer114cfbd2011-09-23 05:05:37 -03002317 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
Hans de Goedeb39e0cb2011-02-16 08:33:16 -03002318 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002319 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2320 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2321 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2322 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002323 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2324 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002325 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2326 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2327 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2328 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnson33ddc162010-04-18 21:42:40 -03002329 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002330 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2331 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2332 {}
2333};
2334MODULE_DEVICE_TABLE(usb, device_table);
2335
2336/* -- device connect -- */
2337static int sd_probe(struct usb_interface *intf,
2338 const struct usb_device_id *id)
2339{
2340 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2341 THIS_MODULE);
2342}
2343
Brian Johnson26e744b2009-07-19 05:52:58 -03002344static struct usb_driver sd_driver = {
2345 .name = MODULE_NAME,
2346 .id_table = device_table,
2347 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002348 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002349#ifdef CONFIG_PM
2350 .suspend = gspca_suspend,
2351 .resume = gspca_resume,
2352 .reset_resume = gspca_resume,
2353#endif
2354};
2355
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08002356module_usb_driver(sd_driver);